TypeScript (Developer Preview)
Accessibility Attributes
Handle Focus
Mobile-Ready Components
Develop Secure Code
To make your components available to screen readers and other assistive technologies, use HTML attributes on your components. HTML attributes describe the UI elements that they contain. Accessibility software interprets UI elements by reading the attributes aloud.
One critical piece of accessibility is the use of the label attribute. By associating labels with a control, you allow assistive technology to present it to the user and let the user identify the purpose of the control. See WCAG label techniques.
Lightning base components provide built-in accessibility. When you use a base component like lightning-input and lightning-record-form, the label you provide is automatically associated with the input field.
1<lightning-input type="text" label="Enter some text"></lightning-input>The input field is rendered with an associated label.
1<!-- Generated HTML -->
2<lightning-input class="slds-form-element">
3 <label for="input-2" class="slds-form-element__label slds-no-flex">Enter some text</label>
4 <div class="slds-form-element__control slds-grow">
5 <input type="text" id="input-2" class="slds-input" />
6 </div>
7</lightning-input>When the label element cannot be used, use the aria-label attribute to identify form controls like buttons and input fields for screen reader users. Screen readers read aria-label attribute values to a user.
The aria-label attribute doesn’t display visibly for all users, and it only communicates the label to screen readers. If you’re including important information for users and want your content to be accessible, we recommend making the text visible.
Note
1<!-- parent.html -->
2<template>
3 <lightning-button aria-label="Log In" label="Log In"
4</template>That template creates HTML output like the following for the screen reader to read out “Log In” to the user.
1<!-- Generated HTML -->
2<lightning-button>
3 <button aria-label="Log In">Log In</button>
4</lightning-button>Note that the sample code above doesn’t need to use aria-label because the label="Log In" attribute is sufficient to label the component for all users. Use the aria-label attribute to create a label only when one isn’t visually present or to provide additional text for a screen reader user beyond what’s already visible.
The base component examples are for demonstration purposes only. Base component internals are subject to change. We document changes to the features and behavior of components, but don’t document changes to their internals. See the Component Reference for the public attributes and methods on a base component.
Note
When you’re creating a Lightning web component, use @api to expose a public aria-label attribute if you want a screen reader to read a value aloud to the user.
When you take control of an attribute by exposing it as a public property, the attribute no longer appears in the HTML output by default.
Note
To pass the value through to the rendered HTML as an attribute (to reflect the property), define a getter and setter for the property and call the setAttribute() method.
You can also perform operations in the setter. Use a private property to hold the computed value.
1// myComponent.js
2import { LightningElement, api } from "lwc";
3
4export default class MyComponent extends LightningElement {
5 privateAriaLabel;
6 @api
7 get ariaLabel() {
8 return this.privateAriaLabel;
9 }
10
11 set ariaLabel(value) {
12 this.privateAriaLabel = value.toUpperCase();
13 this.setAttribute("aria-label", this.privateAriaLabel);
14 }
15}1<!-- parent.html -->
2<template>
3 <c-my-component aria-label="Custom Input"></c-my-component>
4</template>1/* Generated HTML */
2<c-my-component aria-label="Custom Input">
3 <input type="text" class="slds-input" placeholder="Custom Input" />
4</c-my-component>For more information on using setAttribute(), see Reflect JavaScript Properties to HTML Attributes.
To provide more advanced accessibility, such as a screen reader reading out a button’s current state, use ARIA attributes. These attributes give more detailed information to the screen readers that support the ARIA standard.
You can associate ARIA attributes with id attributes in your HTML template. In a component’s template file, id values must be unique so that screen readers can associate ARIA attributes such as aria-describedby, aria-details, and aria-owns with specific elements.
When a template is rendered, id values may be transformed into globally unique values. Don’t use an id selector in CSS or JavaScript because it won’t match the transformed id. Instead, use the element’s class attribute or a data-* attribute like data-id.
Note
Let’s look at some code. The aria-pressed attribute tells screen readers to say when a button is pressed. When using a lightning-button component, you write:
1<!-- parent.html -->
2<template>
3 <lightning-button
4 label="Liked"
5 onclick={login}
6 aria-label="Like"
7 aria-pressed="true"
8 ></lightning-button>
9</template>The component defines the ARIA attributes as public properties, and uses fields to get and set the public properties.
1<!-- lightning-button.html -->
2<template>
3 <button
4 label="Liked"
5 onclick={login}
6 aria-label={innerLabel}
7 aria-pressed={pressed}
8 ></button>
9</template>The component JavaScript uses the camel-case attribute mappings to get and set the values in lightning-button.js.
1// lightning-button.js
2import { LightningElement, api } from "lwc";
3export default class LightningButton extends LightningElement {
4 innerLabel;
5
6 @api
7 get ariaLabel() {
8 return this.innerLabel;
9 }
10
11 set ariaLabel(newValue) {
12 this.innerLabel = newValue;
13 }
14
15 pressed;
16
17 @api
18 get ariaPressed() {
19 return this.pressed;
20 }
21
22 set ariaPressed(newValue) {
23 this.pressed = newValue;
24 }
25}The generated HTML is:
1<lightning-button>
2 <button
3 label="Liked"
4 onclick={login}
5 aria-label="Like"
6 aria-pressed="true">
7 </button>
8</lightning-button>A screen reader that supports ARIA reads the label and indicates that the button is pressed.
ARIA attributes use camel-case in accessor functions. For example, aria-label becomes ariaLabel. The complete mapping list is defined in the LWC GitHub repo.
Note
A component author may want to define default ARIA attributes on a custom component, and still allow component consumers to specify attribute values. In this case, a component author defines default ARIA values on the component’s element.
1// lightning-button.js sets "Submit Form" as the default label
2import { LightningElement } from "lwc";
3export default class LightningButton extends LightningElement {
4 connectedCallback() {
5 this.template.querySelector("lightning-button").ariaLabel = "Submit Form";
6 }
7}Define attributes in connectedCallback(). Don’t define attributes in constructor(). See Constructor Considerations.
Note
When you use the component and supply an aria-label value, the supplied value appears.
1<!-- parent.html -->
2<template>
3 <lightning-button
4 label="Submit"
5 onclick={submit}
6 aria-label="Submit This Form"
7 aria-pressed
8 ></lightning-button>
9</template>The generated HTML is:
1<lightning-button>
2 <button label="Submit" aria-label="Submit This Form" aria-pressed="true"></button>
3</lightning-button>And, when you don’t supply an aria-label value, the default value appears.
1<!-- parent.html -->
2<template>
3 <lightning-button label="Submit" onclick={submit}></lightning-button>
4</template>The generated HTML is:
1<lightning-button>
2 <button label="Submit" onclick={submit} aria-label="Submit Form"></button>
3</lightning-button>What if you create a custom component and don’t want the value of an attribute to change? A good example is the role attribute. You don’t want a component consumer to change button to tab. A button is a button.
You always want the generated HTML to have the role be button, like in this example.
1<lightning-button>
2 <div label="Log In" onclick={login} role="button"></div>
3</lightning-button>To prevent a consumer from changing an attribute’s value, simply return a string. This example always returns "button" for the role value.
1// lightning-button.js
2import { LightningElement, api } from "lwc";
3export default class LightningButton extends LightningElement {
4 set role(value) {}
5
6 @api
7 get role() {
8 return "button";
9 }
10}IDs and ARIA attributes in the same template are linked automatically. If attributes are in different templates, you must link them manually.
In native shadow DOM, you can’t link IDs and ARIA attributes between elements in separate templates.
To link together two elements using IDs and ARIA attributes, use light DOM to place them in the same shadow root. See the Accessibility section in Light DOM.