Custom Element Semantics

'custom element semantics' written across a rainy wind screen, 'custom' obscured. the rest of the text is easier to read as the windscreen wiper has cleared the wind screen.The following content written by me, was until recently a part of the W3C Custom Elements specification, but was removed/substantially re-written when a new editor took over. As we think, in the form represented here, it’s a useful introduction to custom element semantics, we have re-published it.

Custom Element Semantics

The default semantics of a custom element is dependent upon the form in which it is instantiated:

Custom Tag Example

For example, a custom tag could be named taco-button, but the name alone does not express the semantics of a HTML button element simply due to its name. As instantiated a custom tag conveys a similar amount of semantics as an HTML div or span element:

<!-- taco-button represents a span with a fancy name -->
<taco-button></taco-button>

The addition of visual styling and scripted events to the taco-button could provide hints as to its semantics and expected interaction behaviours — for some users — but for the semantics to be formally expressed developers must convey the semantics using ARIA roles, states and properties.

The addition of a tabindex attribute to the custom element provides interaction (the element is included in the focus order) and property/state semantics (it exposes information that it is focusable and if it currently has focus).

<!-- taco-button represents a focusable span with a fancy name -->
<taco-button tabindex="0">Eat Me</taco-button>

The addition of a label, using aria-label, to the custom element provides an Accessible Name for the element.

<!-- taco-button represents a focusable span with a fancy name and a text label -->
<taco-button tabindex="0" aria-label="Eat Me">Eat Me</taco-button>

The addition of keyboard event handlers to the custom element provides the means for keyboard users to operate the control, but does not convey the presence of the functionality.

<!-- taco-button represents focusable span with a fancy name,
    a text label and button like event handling -->
<taco-button tabindex="0" onclick="alert('tasty eh?');"
onkeypress="if(event.keyCode==32||event.keyCode==13){alert('tasty eh?');};"
>Eat Me</taco-button>
Note: The addition of inline event handlers are for demonstration purposes only. The event handlers could be added by the lifecycle callbacks imperatively, or maybe even not used at all. This example demonstrates one method for developers to ensure that a custom control is operable for keyboard users and meets the WCAG 2.0 [WCAG20] criteria “All functionality of the content is operable through a keyboard interface”.

The addition of an ARIA role="button" conveys the custom element’s role semantics, which enables users to successfully interact with the control using the expected button interaction behaviours (pressing the space or enter keys to activate).

<!-- taco-button represents a focusable button with a text label
    and button like event handling -->
<taco-button role="button" tabindex="0" onclick="alert('tasty eh?');"
onkeypress="if(event.keyCode==32||event.keyCode==13){alert('tasty eh?');};"
>Eat Me</taco-button>

The developer may provide a disabled state for the custom element. This could be implemented by removing the tabindex attribute so the element is no longer included in the focus order and removing the functionality so that interacting with the element does nothing. Also the visual styling may also be modified to visually indicate it the element is disabled.

<!-- grayed out non focusable taco-button with functionality removed,
     to indicate the button is in a disabled state  -->
<taco-button role="button" tabindex="0" onclick="alert('tasty eh?');"
onkeypress="if(event.keyCode==32||event.keyCode==13){alert('tasty eh?');};"
>Eat Me</taco-button>

Removing the focusability and functionality of the custom element and modifying its style does not unambiguously express that it is in a disabled state. To unambiguously express the disabled state add aria-disabled="true".

<!-- taco-button represents a focusable button with a text label
       and button like event handling -->
<taco-button role="button" tabindex="0" onclick="alert('tasty eh?');"
  onkeypress="if(event.keyCode==32||event.keyCode==13){alert('tasty eh?');};"
  aria-disabled="true">Eat Me</taco-button>
Note: A disabled attribute would not work here as the custom tag is not based on an HTML element that supports its use.

Type Extension Example

A type extension, for example could extend the HTML button element. As instantiated it would inherit the button element’s name, role, states and properties, built in focus and keyboard interaction behaviours.

<!-- tequila-button represents a button with an accessible name of "Drink Me!" -->
<button is="tequila-button">Drink Me!</button>

To implement the desired tequila-button feature, all that is required is the addition of an event handler. The rest of the semantics and interaction behaviour are provided by the browser as part of its implementation of the button element.

<!-- tequila-button represents a button -->
<button is="tequila-button" onclick="alert('smooth!');">Drink Me!</button>

To implement the disabled state on the tequila-button, all that is required is the addition of the HTML disabled attribute. The semantics, style and interaction behaviour are implemented by the browser.

<!-- tequila-button represents a button -->
<button is="tequila-button" onclick="alert('smooth!');" disabled>Drink Me!</button>

Custom Element Semantics — Conclusion

The simplest and most robust method to create custom elements that are usable and accessible is to implement custom elements as type extensions. This method provides a custom element with built in semantics and interaction behaviours that developers can use as a foundation.

Use ARIA , where needed, to provide semantics for custom elements and follow the ARIA Design Patterns when implementing ARIA attributes and UI interaction behaviours. Ensure that custom tag or type extension custom elements meet the criteria listed in the Custom Control Accessible Development Checklist . Use ARIA in accordance with the Document conformance requirements for use of ARIA attributes in HTML.

Further Reading for Developers

Categories: Technical

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.