HTML5 Accessibility Chops: notes on using ARIA

I have jotted down some notes on ARIA concepts and usage that may be useful for developers.

Note: this information is now being actively maintained as part of Using ARIA in HTML.

Custom ARIA - HTML5 logoThe first rule of ARIA use

If you can use a native HTML element or attribute instead of an ARIA role, state or property, then do so.

Under what circumstances may this not be possible?

The Second rule of ARIA use

Do not change native semantics, unless you really have to.

For example: Developer wants to build a heading that’s a button.

Do not do this:

<h1 role=button>heading button</h1>

Do this:

<h1><span role=button>heading button</span></h1>

Or better, do this:

<h1><button>heading button</button></h1>

Note: it is OK to use native HTML elements, that have similar semantics to ARIA roles used, for fallback. For example using HTML list elements for the skeleton of an ARIA enabled, scripted tree widget.

What does adding a role do to the native semantics?

Adding an ARIA role overrides the native role semantics.

For example:

<h1 role=button>text</h1>

Becomes this in the accessibility tree:


What adding a role does not do?

Adding an ARIA role does not change the behaviours, states and properties

For example:


<button role=heading>text</button>

Becomes this in the accessibility tree:


But it is can still be pressed, it is still in the default tab order, still looks like a button, still triggers any associated actions when pressed. That’s why it is a HTML5 conformance error to change a button into a heading.

Note: likewise, changing the role of an element does not add behaviours, properties or states of the role used. You must add those yourself.

Add ARIA inline or via script?

If the ARIA role or aria-* attribute does not rely on scripting to provide interaction behaviour, then it is safe to include the ARIA markup inline. For example, it is fine to add ARIA landmark roles or ARIA labelling and describing roles inline. If the content and interaction is only supported in a scripting enabled browsing context, for example Google docs applications require JavaScript enabled to work, so it is safe for them to include the ARIA markup inline.

Google spreadsheet application displaying a message ‘Your browser must support JavaScript.’

Otherwise add ARIA via scripting.

ARIA validation

The easiest method is to use the HTML5 DOCTYPE with ARIA markup and validate using the W3C Nu Markup Validation Service. ARIA works equally well with any other DOCTYPE, but validation tools will produce errors when they encounter ARIA markup as the associated DTDs have not been updated to recognise ARIA markup and it is unlikely they ever will be.

Use of role=presentation

role=presentation removes the semantics from the element it is on.

For example.


<h1 role=presentation>text</h1>

becomes this:


For elements with no required children, any elements nested inside the element with role=presentation preserve their semantics.

For example.


<h1 role=presentation><abbr>API</abbr></h1>

becomes this:


For elements with required children (such as ul or table any required child elements nested inside the element with role=presentation also have their semantics removed.

For example,


<table role=presentation>



becomes this:




Note: Any elements that are not required children of the element with a role=presentation keep their semantics. This includes other elements with required children.

For example;

<table role=presentation>







Becomes this:








aria-labelledby and aria-describedby

Currently aria-labelledby and aria-describedby are only robustly supported for associating text content to a subset of interactive content elements, they do not work correctly on links, support on embedded content is unknown, but can be safely used on form controls including the many input types.

In Internet Explorer, if you use aria-labelledby with multiple id references or aria-describedby with single or multiple id references, the referenced elements must be what Microsoft terms as accessible HTML elements.

The following example of aria-labelledby with multiple references uses the label element as it makes sense and it’s an accessible element (in IE terms). The example could have used a span (for example) but then tabindex=-1 would have to be added. Refer to Making Non accessible Elements Accessible

<label id="l1" for="f3">label text </label>
<input type="text" id="f3" aria-labelledby="l1 l2">
<p>other content</p>
<label id="l2">more label text</label>

Abstract roles

Do not use the following abstract roles as they do not do anything!

Abstract roles are used for the ontology. Authors MUST NOT not use abstract roles in content.

  • command (abstract role)
  • composite (abstract role)
  • input (abstract role)
  • landmark (abstract role)
  • range (abstract role)
  • roletype (abstract role)
  • section (abstract role)
  • sectionhead (abstract role)
  • select (abstract role)
  • structure (abstract role)
  • widget (abstract role)
  • window (abstract role)


Further reading:

Categories: Development

About Steve Faulkner

Steve was the Chief Accessibility Officer at TPGi before he left in October 2023. He joined TPGi in 2006 and was previously a Senior Web Accessibility Consultant at vision australia. Steve is a member of several groups, including the W3C Web Platforms Working Group and the W3C ARIA Working Group. He is an editor of several specifications at the W3C including ARIA in HTML and HTML Accessibility API Mappings 1.0. He also develops and maintains HTML5accessibility and the JAWS bug tracker/standards support.


Great article Steve,

I found interesting the part about “Aria inline or via script”,
Could you add more information about dynamic content best practices? I found this example of adding ARIA via scripting:


Ian Crowther says:


A nice highlight that roles change the semantics, makes perfect sense when you think about it!!