Falytom logoFALYTOM
Games
ToolsUI ComponentsServicesProductsAbout
LoginSign Up
menu
  1. Home
  2. /Web Development
  3. /Html
  4. /Aria Attributes
Your Progress0%
0 of 76 completed

Topics

Getting Started

  • What is HTML?
  • How the Web Works
  • Setting Up Your Environment
  • Your First HTML Page

HTML Document Structure

  • The DOCTYPE Declaration
  • The HTML Element
  • The Head Section
  • Meta Tags
  • The Body Element
  • HTML Comments

Text and Formatting

  • Headings (h1-h6)
  • Paragraphs
  • Line Breaks and Horizontal Rules
  • Text Formatting (Bold, Italic, etc.)
  • Quotations and Citations
  • Preformatted Text and Code
  • Subscript and Superscript

Links and Navigation

  • Creating Links
  • Absolute vs Relative URLs
  • Link Targets and Attributes
  • Email and Phone Links
  • Internal Page Links

Images and Media

  • Adding Images
  • Image Attributes
  • Image Formats
  • Figure and Figcaption
  • Responsive Images
  • Audio Elements
  • Video Elements
  • Embedding Content

Lists

  • Unordered Lists
  • Ordered Lists
  • Description Lists
  • Nested Lists

Tables

  • Table Basics
  • Table Headers and Footers
  • Spanning Columns and Rows
  • Table Captions
  • Styling Tables

Forms - Part 1 (Basics)

  • Introduction to Forms
  • Text Input Fields
  • Labels and Placeholders
  • Textarea Element
  • Checkboxes
  • Radio Buttons

Forms - Part 2 (Advanced)

  • Select Dropdowns
  • File Upload Inputs
  • HTML5 Input Types
  • Form Validation
  • Form Buttons
  • Fieldsets and Legends
  • Form Accessibility

Semantic HTML

  • What is Semantic HTML?
  • Header and Footer
  • Nav Element
  • Main and Article
  • Section and Aside
  • Div vs Semantic Elements
  • Time and Mark Elements

HTML5 Features

  • HTML5 Overview
  • Canvas Element
  • SVG in HTML
  • Geolocation API
  • Drag and Drop
  • Local Storage
  • Web Workers

Web Accessibility

  • Introduction to Accessibility
  • ARIA Attributes
  • Keyboard Navigation
  • Alt Text Best Practices
  • Color Contrast and Typography
  • Testing for Accessibility

Best Practices & SEO

  • HTML Best Practices
  • SEO Fundamentals
  • Meta Tags for SEO
  • Structured Data

ARIA Attributes

Making dynamic content accessible with ARIA

ARIA (Accessible Rich Internet Applications) is a set of attributes that make web content and applications more accessible to people with disabilities. ARIA fills gaps in HTML by providing additional information to assistive technologies like screen readers.

What is ARIA?

ARIA is a W3C specification that defines ways to make web content more accessible when native HTML elements aren't sufficient. It's particularly useful for:

  • Dynamic content that updates without page reload
  • Advanced user interface controls (tabs, sliders, dialogs)
  • Custom widgets built with div and span elements
  • Providing additional context for assistive technologies

The First Rule of ARIA

No ARIA is better than bad ARIA!

If you can use a native HTML element with the semantics and behavior you need already built in, instead of re-purposing an element and adding ARIA, then do so. Don't use ARIA unless you have to.

native-vs-aria.html
<!-- GOOD: Use native HTML button -->
<button>Click me</button>

<!-- BAD: Don't reinvent the wheel with ARIA -->
<div role="button" tabindex="0" 
     onclick="handleClick()" 
     onkeypress="handleKeyPress()">
  Click me
</div>

<!-- GOOD: Use native checkbox -->
<input type="checkbox" id="agree">
<label for="agree">I agree</label>

<!-- BAD: Custom checkbox requiring ARIA -->
<div role="checkbox" aria-checked="false" tabindex="0">
  I agree
</div>

Three Components of ARIA

ARIA consists of three main components:

1. Roles

Roles define what an element is or does. They tell assistive technologies the type of element they're interacting with.

aria-roles.html
<!-- Navigation landmark -->
<div role="navigation">
  <a href="/">Home</a>
  <a href="/about">About</a>
</div>

<!-- Alert message -->
<div role="alert">
  Your session is about to expire!
</div>

<!-- Tab interface -->
<div role="tablist">
  <button role="tab" aria-selected="true">Tab 1</button>
  <button role="tab" aria-selected="false">Tab 2</button>
</div>

<!-- Dialog/Modal -->
<div role="dialog" aria-labelledby="dialog-title">
  <h2 id="dialog-title">Confirm Action</h2>
  <p>Are you sure?</p>
</div>

2. Properties

Properties define characteristics of elements. They often describe relationships or provide additional information.

aria-properties.html
<!-- Label an element -->
<button aria-label="Close dialog">×</button>

<!-- Reference another element for label -->
<div id="email-label">Email Address</div>
<input type="email" aria-labelledby="email-label">

<!-- Provide additional description -->
<input type="password" 
       aria-describedby="password-requirements">
<div id="password-requirements">
  Must be at least 8 characters
</div>

<!-- Indicate required field -->
<input type="text" aria-required="true">

<!-- Define element that controls another -->
<button aria-controls="menu-list" aria-expanded="false">
  Menu
</button>
<ul id="menu-list" hidden>
  <li>Option 1</li>
  <li>Option 2</li>
</ul>

3. States

States define the current condition of elements. Unlike properties, states change frequently (often with JavaScript).

aria-states.html
<!-- Expanded/collapsed state -->
<button aria-expanded="false" aria-controls="accordion-panel">
  Show Details
</button>
<div id="accordion-panel" hidden>
  Details content...
</div>

<!-- Selected state -->
<div role="tab" aria-selected="true">Active Tab</div>
<div role="tab" aria-selected="false">Inactive Tab</div>

<!-- Checked state -->
<div role="checkbox" aria-checked="true">
  Subscribe to newsletter
</div>

<!-- Disabled state -->
<button aria-disabled="true">Submit</button>

<!-- Hidden state -->
<div aria-hidden="true">
  This content is hidden from screen readers
</div>

<!-- Busy/loading state -->
<div aria-busy="true">Loading content...</div>

Common ARIA Attributes

aria-label

Provides an accessible name when visible text isn't available or sufficient:

aria-label-examples.html
<!-- Icon button without visible text -->
<button aria-label="Search">
  <svg><!-- search icon --></svg>
</button>

<!-- Link with icon only -->
<a href="https://twitter.com" aria-label="Follow us on Twitter">
  <svg><!-- twitter icon --></svg>
</a>

<!-- Close button with X symbol -->
<button aria-label="Close notification">×</button>

aria-labelledby

References the ID of another element that labels this element:

aria-labelledby-examples.html
<!-- Dialog labeled by its heading -->
<div role="dialog" aria-labelledby="dialog-heading">
  <h2 id="dialog-heading">Delete Account</h2>
  <p>This action cannot be undone.</p>
  <button>Delete</button>
  <button>Cancel</button>
</div>

<!-- Form section labeled by heading -->
<section aria-labelledby="billing-heading">
  <h3 id="billing-heading">Billing Information</h3>
  <!-- form fields -->
</section>

<!-- Can reference multiple IDs -->
<button aria-labelledby="icon-label text-label">
  <svg id="icon-label" aria-label="Settings"></svg>
  <span id="text-label">Preferences</span>
</button>

aria-describedby

References additional descriptive information:

aria-describedby-examples.html
<!-- Input with help text -->
<label for="username">Username</label>
<input type="text" 
       id="username" 
       aria-describedby="username-help">
<div id="username-help">
  Choose a unique username, 3-20 characters
</div>

<!-- Input with error message -->
<label for="email">Email</label>
<input type="email" 
       id="email" 
       aria-invalid="true"
       aria-describedby="email-error">
<div id="email-error" role="alert">
  Please enter a valid email address
</div>

<!-- Can reference multiple descriptions -->
<input type="password" 
       aria-describedby="password-help password-requirements">
<div id="password-help">Enter a strong password</div>
<ul id="password-requirements">
  <li>At least 8 characters</li>
  <li>Include numbers and symbols</li>
</ul>

aria-hidden

Hides content from assistive technologies:

aria-hidden-examples.html
<!-- Hide decorative icons -->
<button>
  <svg aria-hidden="true"><!-- decorative icon --></svg>
  Save Document
</button>

<!-- Hide duplicate content -->
<div>
  <h2 id="section-title">Contact Us</h2>
  <a href="#contact" aria-labelledby="section-title">
    <!-- Hide icon, label already provided -->
    <svg aria-hidden="true"><!-- icon --></svg>
  </a>
</div>

<!-- Warning: Don't hide focusable elements -->
<!-- BAD: This is confusing -->
<button aria-hidden="true">Click me</button>

aria-live

Announces dynamic content changes to screen readers:

aria-live-examples.html
<!-- Polite announcements (wait for pause) -->
<div aria-live="polite" aria-atomic="true">
  Items in cart: 3
</div>

<!-- Assertive announcements (interrupt) -->
<div role="alert" aria-live="assertive">
  Error: Connection lost. Attempting to reconnect...
</div>

<!-- Status messages -->
<div role="status" aria-live="polite">
  Last saved at 2:45 PM
</div>

<!-- Log messages -->
<div role="log" aria-live="polite" aria-atomic="false">
  <p>Message 1</p>
  <p>Message 2</p>
  <p>Message 3</p>
</div>

Practical Examples

Accessible Accordion

accessible-accordion.html
<div class="accordion">
  <h3>
    <button aria-expanded="false" 
            aria-controls="section1-content"
            id="section1-header">
      Section 1
    </button>
  </h3>
  <div id="section1-content" 
       role="region" 
       aria-labelledby="section1-header"
       hidden>
    <p>Content for section 1...</p>
  </div>

  <h3>
    <button aria-expanded="false" 
            aria-controls="section2-content"
            id="section2-header">
      Section 2
    </button>
  </h3>
  <div id="section2-content" 
       role="region" 
       aria-labelledby="section2-header"
       hidden>
    <p>Content for section 2...</p>
  </div>
</div>

<script>
  document.querySelectorAll('.accordion button').forEach(button => {
    button.addEventListener('click', function() {
      const expanded = this.getAttribute('aria-expanded') === 'true';
      const content = document.getElementById(this.getAttribute('aria-controls'));
      
      // Toggle state
      this.setAttribute('aria-expanded', !expanded);
      content.hidden = expanded;
    });
  });
</script>

Accessible Modal Dialog

accessible-modal.html
<button id="openModal">Open Dialog</button>

<div id="myModal" 
     role="dialog" 
     aria-modal="true"
     aria-labelledby="modalTitle"
     aria-describedby="modalDesc"
     hidden>
  
  <h2 id="modalTitle">Confirm Delete</h2>
  <p id="modalDesc">
    Are you sure you want to delete this item? 
    This action cannot be undone.
  </p>
  
  <button id="confirmBtn">Delete</button>
  <button id="cancelBtn">Cancel</button>
  <button aria-label="Close dialog">×</button>
</div>

<script>
  const modal = document.getElementById('myModal');
  const openBtn = document.getElementById('openModal');
  let lastFocusedElement;

  openBtn.addEventListener('click', () => {
    lastFocusedElement = document.activeElement;
    modal.hidden = false;
    // Focus first element in modal
    modal.querySelector('button').focus();
    // Trap focus within modal
    trapFocus(modal);
  });

  function closeModal() {
    modal.hidden = true;
    lastFocusedElement.focus();
  }

  function trapFocus(element) {
    const focusableElements = element.querySelectorAll(
      'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
    );
    const firstElement = focusableElements[0];
    const lastElement = focusableElements[focusableElements.length - 1];

    element.addEventListener('keydown', function(e) {
      if (e.key === 'Tab') {
        if (e.shiftKey && document.activeElement === firstElement) {
          e.preventDefault();
          lastElement.focus();
        } else if (!e.shiftKey && document.activeElement === lastElement) {
          e.preventDefault();
          firstElement.focus();
        }
      } else if (e.key === 'Escape') {
        closeModal();
      }
    });
  }
</script>

Landmark Roles

Landmark roles help users navigate to major sections of a page. Most HTML5 elements have implicit roles, but you can add explicit roles when needed:

landmark-roles.html
<!-- Use semantic HTML (preferred) -->
<header><!-- role="banner" implied --></header>
<nav><!-- role="navigation" implied --></nav>
<main><!-- role="main" implied --></main>
<aside><!-- role="complementary" implied --></aside>
<footer><!-- role="contentinfo" implied --></footer>

<!-- Explicit roles when semantic elements can't be used -->
<div role="banner">Site Header</div>
<div role="navigation">Main Menu</div>
<div role="main">Primary Content</div>
<div role="complementary">Sidebar</div>
<div role="contentinfo">Site Footer</div>
<div role="search">
  <input type="search" aria-label="Search site">
</div>

<!-- Multiple landmarks of same type need labels -->
<nav aria-label="Main navigation"><!-- main menu --></nav>
<nav aria-label="Footer navigation"><!-- footer links --></nav>

Input Validation with ARIA

input-validation.html
<div>
  <label for="email">Email *</label>
  <input type="email" 
         id="email" 
         required
         aria-required="true"
         aria-invalid="false"
         aria-describedby="email-error">
  <span id="email-error" role="alert" hidden>
    Please enter a valid email address
  </span>
</div>

<script>
  const emailInput = document.getElementById('email');
  const emailError = document.getElementById('email-error');
  
  emailInput.addEventListener('blur', function() {
    if (!this.validity.valid) {
      this.setAttribute('aria-invalid', 'true');
      emailError.hidden = false;
    } else {
      this.setAttribute('aria-invalid', 'false');
      emailError.hidden = true;
    }
  });
</script>

ARIA Best Practices

  • Use native HTML first: Semantic HTML is always better than ARIA
  • Don't change native semantics: Don't do<h1 role="button">
  • All interactive elements must be operable: Ensure keyboard accessibility
  • Don't use aria-hidden on focusable elements: This creates confusion
  • Keep ARIA up to date: Update states when UI changes
  • Test with screen readers: ARIA only works if implemented correctly
  • Use aria-label for icon buttons: Provide text alternatives
  • Announce dynamic changes: Use aria-live for real-time updates

Common ARIA Mistakes

aria-mistakes.html
<!-- ❌ BAD: Redundant role on semantic element -->
<button role="button">Click me</button>

<!-- ✅ GOOD: Use semantic HTML -->
<button>Click me</button>

<!-- ❌ BAD: Conflicting roles -->
<h1 role="button">Heading Button</h1>

<!-- ✅ GOOD: Use appropriate element -->
<button>Click me</button>

<!-- ❌ BAD: aria-hidden on focusable element -->
<button aria-hidden="true">Hidden but focusable</button>

<!-- ✅ GOOD: Hide properly or don't hide -->
<button hidden>Truly hidden</button>

<!-- ❌ BAD: Empty aria-label -->
<button aria-label="">Click</button>

<!-- ✅ GOOD: Meaningful label -->
<button aria-label="Submit form">Submit</button>

<!-- ❌ BAD: Incorrect role usage -->
<div role="table">This is not really a table</div>

<!-- ✅ GOOD: Use proper table markup -->
<table><!-- proper table structure --></table>

Key Takeaways

  • ARIA enhances accessibility for dynamic content and custom widgets
  • Always prefer native HTML elements over ARIA when possible
  • ARIA has three components: roles, properties, and states
  • Common attributes include aria-label, aria-labelledby, aria-describedby, and aria-hidden
  • Use aria-live for dynamic content that needs to be announced
  • Landmark roles help users navigate page sections
  • Update ARIA states when your UI changes with JavaScript
  • Test with actual screen readers to verify ARIA works correctly

What's Next?

Now that you understand ARIA attributes, you can make complex web applications accessible. In the next lesson, we'll explore keyboard navigation patterns and how to ensure all functionality is accessible without a mouse.

Know someone who'd find this guide helpful? Please share!

Previous
Introduction to Accessibility
Next
Keyboard Navigation

Never Miss a New HTML Tutorial

Join 1,000+ developers learning HTML step-by-step. Get new tutorials, tips, and exclusive resources delivered to your inbox - completely FREE.

You might also like

UI Components

Ready-made components for your projects

Developer Tools

Boost productivity with handy generators

HTML Game

Learn HTML concepts through interactive gameplay

Join Our Web Development Training Program

Master frontend & backend development with hands-on projects.

Menu

Topics

Getting Started

  • What is HTML?
  • How the Web Works
  • Setting Up Your Environment
  • Your First HTML Page

HTML Document Structure

  • The DOCTYPE Declaration
  • The HTML Element
  • The Head Section
  • Meta Tags
  • The Body Element
  • HTML Comments

Text and Formatting

  • Headings (h1-h6)
  • Paragraphs
  • Line Breaks and Horizontal Rules
  • Text Formatting (Bold, Italic, etc.)
  • Quotations and Citations
  • Preformatted Text and Code
  • Subscript and Superscript

Links and Navigation

  • Creating Links
  • Absolute vs Relative URLs
  • Link Targets and Attributes
  • Email and Phone Links
  • Internal Page Links

Images and Media

  • Adding Images
  • Image Attributes
  • Image Formats
  • Figure and Figcaption
  • Responsive Images
  • Audio Elements
  • Video Elements
  • Embedding Content

Lists

  • Unordered Lists
  • Ordered Lists
  • Description Lists
  • Nested Lists

Tables

  • Table Basics
  • Table Headers and Footers
  • Spanning Columns and Rows
  • Table Captions
  • Styling Tables

Forms - Part 1 (Basics)

  • Introduction to Forms
  • Text Input Fields
  • Labels and Placeholders
  • Textarea Element
  • Checkboxes
  • Radio Buttons

Forms - Part 2 (Advanced)

  • Select Dropdowns
  • File Upload Inputs
  • HTML5 Input Types
  • Form Validation
  • Form Buttons
  • Fieldsets and Legends
  • Form Accessibility

Semantic HTML

  • What is Semantic HTML?
  • Header and Footer
  • Nav Element
  • Main and Article
  • Section and Aside
  • Div vs Semantic Elements
  • Time and Mark Elements

HTML5 Features

  • HTML5 Overview
  • Canvas Element
  • SVG in HTML
  • Geolocation API
  • Drag and Drop
  • Local Storage
  • Web Workers

Web Accessibility

  • Introduction to Accessibility
  • ARIA Attributes
  • Keyboard Navigation
  • Alt Text Best Practices
  • Color Contrast and Typography
  • Testing for Accessibility

Best Practices & SEO

  • HTML Best Practices
  • SEO Fundamentals
  • Meta Tags for SEO
  • Structured Data
Falytom logoFALYTOM

Learn technologies like HTML, CSS, JavaScript, React, NodeJS and more through interactive games, tutorials, components and free tools. Transform your businesses with AI chatbots, SEO-optimized websites, and professional development services.

© 2025 Tomilola Group
  • Facebook logo
  • Twitter logo
  • Instagram logo
  • LinkedIn logo
  • GitHub logo
  • YouTube logo