ARIA Allowed Attributes: Getting the Grammar of Accessibility Right

8 min read

What are ARIA Allowed Attributes?

Imagine trying to communicate in a foreign language by randomly combining words without understanding grammar rules. You might be understood sometimes, but often you'd create confusion or say something completely different from what you intended. ARIA allowed attributes work similarly—they represent the "grammar rules" that determine which ARIA attributes can be meaningfully used together on different HTML elements.

ARIA allowed attributes refers to the specification that defines which ARIA attributes are valid and meaningful for each HTML element and ARIA role. When you use ARIA attributes that aren't allowed on specific elements, you create "grammatical errors" that can confuse assistive technologies, potentially making your content less accessible rather than more accessible.

ARIA Attribute Validation Status:

  • Valid Implementation: All ARIA attributes are used correctly according to the specification, with proper combinations and values
  • Some Issues: Most ARIA attributes are valid, but some invalid combinations or values may cause problems
  • Invalid Usage: Multiple ARIA attributes are used incorrectly, potentially confusing assistive technologies

Why ARIA Attribute Validity Matters

Using ARIA attributes correctly isn't just about following specifications—it's about ensuring your accessibility efforts actually work as intended:

  • Assistive Technology Reliability: Screen readers and other assistive technologies rely on valid ARIA attributes to provide accurate information to users. Invalid attributes can cause these tools to ignore or misinterpret your accessibility enhancements.
  • Consistent User Experience: Valid ARIA ensures that your interface behaves predictably across different assistive technologies and browsers.
  • Future Compatibility: Following the specification helps ensure your accessibility implementations continue working as web standards and assistive technologies evolve.
  • Development Efficiency: Understanding which attributes are allowed prevents wasted time debugging accessibility issues caused by invalid implementations.
  • Legal Compliance: Many accessibility regulations require following established standards, which includes using ARIA attributes correctly.
  • User Trust: When accessibility features work reliably, users develop confidence in your interface and are more likely to engage with your content.

Invalid ARIA attributes can be worse than no ARIA at all—they can actively mislead users of assistive technologies, creating confusion and barriers where none should exist.

The Accessibility Paradox

One of the most frustrating situations in web accessibility is when well-intentioned ARIA implementations actually make interfaces less accessible. This often happens when developers use ARIA attributes that aren't allowed or meaningful for specific elements, creating contradictory or confusing information for assistive technologies.

Understanding ARIA Attribute Categories

ARIA attributes fall into different categories, each with specific rules about where they can be used:

1. Global ARIA Attributes

These attributes can be used on any HTML element, regardless of its role or type.

<!-- Global attributes work on any element -->
<div aria-label="Close button">×</div>
<p aria-describedby="help-text">Enter your password</p>
<img src="chart.png" aria-labelledby="chart-title" alt="">
<span aria-hidden="true">👍</span>

<!-- Examples of global ARIA attributes -->
aria-label
aria-labelledby
aria-describedby
aria-hidden
aria-live
aria-atomic
aria-relevant
aria-busy

2. Widget-Specific Attributes

These attributes only make sense on interactive elements or elements with specific widget roles.

<!-- Valid: On interactive elements -->
<button aria-pressed="false">Toggle</button>
<input type="checkbox" aria-checked="mixed">
<div role="tab" aria-selected="true" tabindex="0">Tab 1</div>

<!-- Invalid: On non-interactive elements -->
<p aria-pressed="false">This doesn't make sense</p>
<div aria-checked="true">Not a checkbox</div>

<!-- Widget-specific attributes include -->
aria-checked
aria-pressed
aria-selected
aria-expanded
aria-disabled
aria-required

3. Relationship Attributes

These establish relationships between elements and must reference valid targets.

<!-- Valid: References existing elements -->
<button aria-controls="menu" aria-expanded="false">Menu</button>
<ul id="menu">
  <li>Option 1</li>
  <li>Option 2</li>
</ul>

<input type="text" aria-describedby="pwd-help">
<div id="pwd-help">Password must be 8+ characters</div>

<!-- Invalid: References non-existent elements -->
<button aria-controls="nonexistent-menu">Menu</button>
<input type="text" aria-describedby="missing-help">

<!-- Relationship attributes include -->
aria-controls
aria-describedby
aria-labelledby
aria-owns
aria-flowto

4. Live Region Attributes

These control how dynamic content changes are announced to users.

<!-- Valid: On containers that will have dynamic content -->
<div id="status" aria-live="polite"></div>
<div id="error-messages" aria-live="assertive" role="alert"></div>
<div aria-live="polite" aria-atomic="true">Loading: 50%</div>

<!-- Less useful: On static content that won't change -->
<h1 aria-live="polite">Static Page Title</h1>

<!-- Live region attributes include -->
aria-live
aria-atomic
aria-relevant
aria-busy

Common ARIA Attribute Validation Errors

Understanding the most common validation errors helps you avoid them in your implementations:

1. Using Widget Attributes on Non-Interactive Elements

Widget-specific attributes only make sense on interactive elements or elements with appropriate roles.

<!-- Invalid: Widget attributes on static elements -->
<div aria-checked="true">Completed task</div>
<p aria-expanded="false">This paragraph text</p>
<span aria-pressed="true">Bold text</span>

<!-- Valid: Widget attributes on appropriate elements -->
<div role="checkbox" aria-checked="true" tabindex="0">Completed task</div>
<button aria-expanded="false" aria-controls="details">Show details</button>
<button aria-pressed="true">Bold (toggle button)</button>

<!-- Or use semantic HTML -->
<input type="checkbox" checked> Completed task
<details>
  <summary>Show details</summary>
  <p>Detail content...</p>
</details>

2. Invalid Attribute Values

ARIA attributes have specific allowed values, and using invalid values can break functionality.

<!-- Invalid values -->
<button aria-pressed="yes">Toggle</button> <!-- Should be true/false -->
<div aria-live="immediate">Status</div> <!-- Should be polite/assertive/off -->
<input aria-required="yes"> <!-- Should be true/false -->
<div role="heading" aria-level="large">Title</div> <!-- Should be 1-6 -->

<!-- Valid values -->
<button aria-pressed="true">Toggle</button>
<div aria-live="assertive">Status</div>
<input aria-required="true">
<div role="heading" aria-level="2">Title</div>

<!-- Common valid values for different attributes -->
aria-expanded: true | false
aria-pressed: true | false | mixed
aria-checked: true | false | mixed
aria-live: polite | assertive | off
aria-required: true | false
aria-disabled: true | false
aria-hidden: true | false
aria-level: 1 | 2 | 3 | 4 | 5 | 6

3. Broken Reference Relationships

Attributes that reference other elements must reference existing elements with valid IDs.

<!-- Invalid: References don't exist -->
<button aria-controls="sidebar">Toggle Sidebar</button>
<input aria-describedby="help-text">
<!-- Missing: <div id="sidebar"> and <div id="help-text"> -->

<!-- Invalid: Multiple references with errors -->
<input aria-labelledby="first-label second-label missing-label">
<div id="first-label">Name:</div>
<div id="second-label">Required</div>
<!-- Missing: <div id="missing-label"> -->

<!-- Valid: All references exist -->
<button aria-controls="sidebar">Toggle Sidebar</button>
<div id="sidebar">Sidebar content</div>

<input aria-describedby="help-text">
<div id="help-text">Enter your full name</div>

<input aria-labelledby="first-label second-label">
<div id="first-label">Name:</div>
<div id="second-label">(Required)</div>

4. Conflicting or Redundant Attributes

Some ARIA attributes conflict with each other or with implicit HTML semantics.

<!-- Invalid: Conflicting label sources -->
<button aria-label="Close dialog" aria-labelledby="close-text">
  <span id="close-text">Close</span>
</button>

<!-- Invalid: Redundant with HTML semantics -->
<button disabled aria-disabled="true">Submit</button>
<input required aria-required="true">

<!-- Valid: Choose one labeling method -->
<button aria-label="Close dialog">×</button>
<!-- OR -->
<button aria-labelledby="close-text">
  <span id="close-text">Close</span>
</button>

<!-- Valid: Let HTML handle it when possible -->
<button disabled>Submit</button>
<input required>

<!-- Valid: ARIA when HTML isn't sufficient -->
<div role="button" aria-disabled="true" tabindex="-1">
  Custom disabled button
</div>

Role-Specific ARIA Attribute Rules

Different ARIA roles allow different sets of attributes. Understanding these relationships helps you use ARIA correctly:

Button Role Attributes

<!-- Allowed attributes for button role -->
<div role="button" 
     aria-pressed="false"     <!-- Valid: buttons can be pressed -->
     aria-expanded="false"    <!-- Valid: buttons can control expansion -->
     aria-disabled="true"     <!-- Valid: buttons can be disabled -->
     aria-describedby="help"  <!-- Valid: global attribute -->
     tabindex="0">            <!-- Required for custom buttons -->
  Custom Button
</div>

<!-- Invalid attributes for button role -->
<div role="button" 
     aria-checked="true"      <!-- Invalid: buttons aren't checkboxes -->
     aria-selected="true"     <!-- Invalid: buttons aren't selectable options -->
     aria-level="2">          <!-- Invalid: buttons don't have levels -->
  Invalid Button
</div>

Tab and Tabpanel Attributes

<!-- Valid tab interface -->
<div role="tablist">
  <div role="tab" 
       aria-selected="true"     <!-- Valid: tabs can be selected -->
       aria-controls="panel1"   <!-- Valid: tabs control panels -->
       tabindex="0">
    Tab 1
  </div>
  <div role="tab" 
       aria-selected="false"
       aria-controls="panel2"
       tabindex="-1">
    Tab 2
  </div>
</div>

<div role="tabpanel" 
     id="panel1"
     aria-labelledby="tab1">   <!-- Valid: panels can be labeled -->
  Panel 1 content
</div>

<!-- Invalid: Wrong attributes for tab role -->
<div role="tab" 
     aria-checked="true"      <!-- Invalid: tabs aren't checkboxes -->
     aria-pressed="false">    <!-- Invalid: tabs aren't buttons -->
  Invalid Tab
</div>

Form Control Attributes

<!-- Valid form control attributes -->
<div role="textbox" 
     aria-required="true"     <!-- Valid: form controls can be required -->
     aria-invalid="false"     <!-- Valid: can indicate validation state -->
     aria-describedby="help"  <!-- Valid: can reference help text -->
     contenteditable="true"   <!-- Required for custom textbox -->
     tabindex="0">
</div>

<div role="checkbox"
     aria-checked="mixed"     <!-- Valid: checkboxes have checked states -->
     aria-required="true"     <!-- Valid: can be required -->
     aria-describedby="info"  <!-- Valid: global attribute -->
     tabindex="0">
  Custom checkbox
</div>

<!-- Invalid: Wrong attributes for form controls -->
<div role="textbox"
     aria-expanded="true"     <!-- Invalid: textboxes don't expand -->
     aria-pressed="false">    <!-- Invalid: textboxes aren't buttons -->
  Invalid textbox
</div>

Tools and Techniques for Validating ARIA Attributes

Several approaches can help you identify and fix ARIA attribute validation issues:

1. Automated Testing Tools

Use accessibility testing tools that include ARIA validation.

  • axe-core: Includes comprehensive ARIA validation rules
  • WAVE: Identifies many ARIA attribute issues
  • Lighthouse: Built into Chrome DevTools, includes ARIA checks
  • Pa11y: Command-line tool for automated accessibility testing
  • HTML5 Validator: W3C validator includes basic ARIA validation
// Example: Using axe-core programmatically
import { axe, toHaveNoViolations } from 'jest-axe';

test('should not have ARIA violations', async () => {
  const { container } = render(<MyComponent />);
  const results = await axe(container);
  expect(results).toHaveNoViolations();
});

// Example: Using Pa11y for ARIA validation
const pa11y = require('pa11y');

pa11y('http://localhost:3000', {
  standard: 'WCAG2AA',
  includeNotices: false,
  includeWarnings: true
}).then((results) => {
  console.log(results.issues);
});

2. Browser Developer Tools

Modern browsers provide built-in accessibility inspection tools.

<!-- Chrome DevTools Accessibility Panel -->
1. Open DevTools (F12)
2. Go to Elements panel
3. Select element with ARIA attributes
4. Look at Accessibility panel (may need to enable)
5. Check for warnings about invalid attributes

<!-- Firefox Accessibility Inspector -->
1. Open DevTools (F12)
2. Go to Accessibility panel
3. Inspect elements for ARIA issues
4. Use the accessibility tree view

<!-- Safari Web Inspector -->
1. Open Web Inspector
2. Go to Elements tab
3. Check Accessibility section in sidebar
4. Review ARIA attribute validity

3. Screen Reader Testing

Test with actual screen readers to identify when invalid ARIA causes confusion.

  • NVDA (Windows): Free screen reader for testing
  • VoiceOver (Mac/iOS): Built into Apple devices
  • TalkBack (Android): Built into Android devices
  • JAWS (Windows): Popular commercial screen reader

Pay attention to whether the screen reader announces information that matches your visual interface, or if invalid ARIA creates confusion.

4. Linting and Build-Time Validation

Integrate ARIA validation into your development workflow.

// ESLint with jsx-a11y plugin
{
  "extends": ["plugin:jsx-a11y/recommended"],
  "rules": {
    "jsx-a11y/aria-props": "error",
    "jsx-a11y/aria-proptypes": "error",
    "jsx-a11y/aria-unsupported-elements": "error",
    "jsx-a11y/role-has-required-aria-props": "error",
    "jsx-a11y/role-supports-aria-props": "error"
  }
}

// Stylelint with a11y plugin
{
  "plugins": ["stylelint-a11y"],
  "rules": {
    "a11y/content-property-no-static-value": true,
    "a11y/font-size-is-readable": true,
    "a11y/line-height-is-vertical-rhythmed": true
  }
}

// Pre-commit hooks for validation
{
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "*.{js,jsx,ts,tsx}": [
      "eslint --fix",
      "npm run test:a11y"
    ]
  }
}

Best Practices for ARIA Attribute Validation

Follow these practices to maintain valid ARIA implementations:

1. Start with Semantic HTML

Use semantic HTML elements first, then enhance with ARIA only when necessary.

<!-- Good: Semantic HTML needs minimal ARIA -->
<button type="submit">Submit Form</button>
<input type="checkbox" required>
<select aria-describedby="format-help">
  <option>Choose format</option>
</select>
<div id="format-help">Select your preferred file format</div>

<!-- Avoid: Recreating semantic elements with ARIA -->
<div role="button" 
     aria-pressed="false" 
     tabindex="0" 
     onclick="submitForm()">
  Submit Form
</div>

2. Validate During Development

Use tools during development rather than trying to fix issues later.

// React example with validation
import React from 'react';

function CustomButton({ pressed, disabled, children, ...props }) {
  // Validate props during development
  if (process.env.NODE_ENV === 'development') {
    if (typeof pressed !== 'boolean' && pressed !== undefined) {
      console.warn('aria-pressed must be true, false, or undefined');
    }
    if (typeof disabled !== 'boolean' && disabled !== undefined) {
      console.warn('aria-disabled must be true, false, or undefined');
    }
  }
  
  return (
    <div
      role="button"
      aria-pressed={pressed}
      aria-disabled={disabled}
      tabIndex={disabled ? -1 : 0}
      {...props}
    >
      {children}
    </div>
  );
}

3. Test State Changes

Ensure ARIA attributes remain valid as component states change.

// Example: Validating dynamic ARIA states
function ExpandableSection({ title, children }) {
  const [expanded, setExpanded] = React.useState(false);
  const contentId = React.useId();
  
  return (
    <div>
      <button
        aria-expanded={expanded}     // Always boolean
        aria-controls={contentId}    // Always valid ID
        onClick={() => setExpanded(!expanded)}
      >
        {title}
      </button>
      
      <div
        id={contentId}               // ID matches aria-controls
        hidden={!expanded}           // Visual state matches ARIA
      >
        {children}
      </div>
    </div>
  );
}

// Test all states
test('maintains valid ARIA in all states', () => {
  const { getByRole } = render(<ExpandableSection title="Test" />);
  const button = getByRole('button');
  
  // Test collapsed state
  expect(button).toHaveAttribute('aria-expanded', 'false');
  
  // Test expanded state
  fireEvent.click(button);
  expect(button).toHaveAttribute('aria-expanded', 'true');
});

The Business Impact of Valid ARIA Implementation

Proper ARIA validation delivers concrete business benefits:

  • Reliable User Experience: Valid ARIA ensures accessibility features work consistently, building user trust and confidence in your interface.
  • Reduced Support Burden: When accessibility features work correctly, you receive fewer support requests from users struggling with broken implementations.
  • Legal Risk Mitigation: Following established standards and specifications helps demonstrate good-faith efforts to meet accessibility requirements.
  • Development Efficiency: Valid implementations are easier to maintain and debug, reducing long-term development costs.
  • Future Compatibility: Standards-compliant code is more likely to work with new assistive technologies and browser updates.
  • Team Knowledge: Understanding ARIA validation improves your team's overall accessibility expertise and implementation quality.
  • Brand Reputation: Demonstrating technical competence in accessibility reflects positively on your organization's commitment to inclusion.

These benefits compound over time, creating more sustainable and successful accessibility implementations that serve users effectively while supporting business objectives.

ARIA Validation Across Different Development Contexts

Different development environments require tailored approaches to ARIA validation:

  • React applications can use ESLint plugins and TypeScript to catch ARIA validation issues during development, with testing libraries to verify runtime behavior.
  • Vue.js projects can implement custom validators and use accessibility testing tools integrated into their testing workflows.
  • Angular applications can leverage built-in form validation patterns and CDK accessibility features to maintain valid ARIA implementations.
  • WordPress sites can use accessibility plugins and theme validation tools to ensure ARIA attributes are used correctly in templates and content.
  • Content management systems can implement validation rules in their editing interfaces to prevent content creators from adding invalid ARIA attributes.
  • Static site generators can include build-time validation steps to catch ARIA issues before deployment.

The key is integrating validation into your existing development workflow rather than treating it as a separate, manual process.

Conclusion: Precision in Accessibility Implementation

ARIA allowed attributes represent the precision required to make accessibility implementations truly effective. Like any powerful tool, ARIA's effectiveness depends on using it correctly according to established standards and specifications.

The goal of understanding ARIA validation isn't to memorize every rule, but to develop an appreciation for the systematic approach that makes web accessibility work reliably. When ARIA attributes are used correctly, they create seamless bridges between visual interfaces and assistive technologies.

What makes ARIA validation particularly important is its role in preventing accessibility regressions. Invalid ARIA can be worse than no ARIA at all, creating confusion and barriers where none should exist. By validating your ARIA implementations, you ensure that your accessibility efforts actually improve user experiences.

As web applications become more complex and interactive, the importance of valid ARIA implementation only increases. The investment in understanding and implementing ARIA correctly pays dividends in reliable, maintainable accessibility that serves users effectively across different technologies and contexts.

Ready to ensure your ARIA implementation is bulletproof?

Greadme's easy-to-use tools can help you identify invalid ARIA attributes on your website and provide clear guidance on fixing them—even if you're not technically minded.

Validate Your Website's ARIA Implementation Today