Custom Element Semantics
The default semantics of a custom element is dependent upon the form in which it is instantiated:
- by default a custom tag has no special meaning at all. It represents its children.
- by default a type extension inherits the semantics of the element type it extends.
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>
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>
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.