<html>
The root of the page. Give it a lang attribute for the page’s main language, so screen readers use the right voice and pronunciation and browsers pick the right fonts and hyphenation.
<html lang="en">The HTML and ARIA that matter for accessibility: what each one does for it, with an example and the guides that use it.
<html>The root of the page. Give it a lang attribute for the page’s main language, so screen readers use the right voice and pronunciation and browsers pick the right fonts and hyphenation.
<html lang="en"><title>The page’s name, shown in the tab and read first when the page loads. Make each one unique and put the specific part first: “Checkout – Fern & Fold”.
<title>Order confirmed – Fern & Fold</title><meta>Page metadata: the character set, the viewport, a description. Never set maximum-scale=1 or user-scalable=no in the viewport: it stops people zooming on mobile.
<meta name="viewport" content="width=device-width, initial-scale=1">Guides that use it
<header>Introductory content, such as the site’s logo and navigation. It is the banner landmark only when it is not inside <article>, <aside>, <main>, <nav> or <section>; there it is just a header for that part.
<header>
<a href="/">Fern & Fold</a>
<nav aria-label="Main">…</nav>
</header>role="banner"<footer><nav>A major block of navigation links. With more than one on a page, name each with aria-label (“Main”, “Footer”) and leave the word “navigation” out: the screen reader says it.
<nav aria-label="Main">
<ul>…</ul>
</nav>role="navigation"aria-labelaria-current<search>Wraps a search or filter form and makes it a search landmark, without adding role="search" to the form.
<search>
<form action="/search">…</form>
</search>role="search"<form><main>The page’s main content, once per page (others must be hidden). Screen reader users jump straight to it, and a skip link can point to it.
<main id="content">
<h1>Your basket</h1>
</main>role="main"<a><section>A thematic section of the page, normally with a heading. It becomes a region landmark only when it has a name, such as aria-labelledby pointing to that heading.
<section aria-labelledby="faq">
<h2 id="faq">Questions</h2>
</section>role="region"aria-labelledby<article>A self-contained piece that would make sense on its own: a post, a comment, a product card. Start it with a heading.
<article>
<h2>Spring opening hours</h2>
<p>…</p>
</article><h1>–<h6>Headings, ranked by level. Screen reader users list them and jump between them, so give the page one <h1>, don’t skip levels going down, and choose the level by structure, not size.
<h1>Delivery</h1>
<h2>UK orders</h2>
<h2>International orders</h2>role="heading"aria-level<aside>Content related to the page but separate from its main content, such as a sidebar. It is a complementary landmark; name it when there is more than one.
<aside aria-label="Related articles">…</aside>role="complementary"<footer>Closing content, such as copyright, contact and policy links. It is the contentinfo landmark only when it is not inside <article>, <aside>, <main>, <nav> or <section>.
<footer>
<a href="/contact">Contact us</a>
</footer>role="contentinfo"<header><ul>An unordered list of items. Outside <nav>, Safari with VoiceOver drops the list role when list-style: none is set; add role="list" if the count matters there.
<ul>
<li>Free returns</li>
<li>Next-day delivery</li>
</ul>role="list"<li><ol>An ordered list, where the sequence matters, such as steps. Screen readers say how many items there are and which one you are on.
<ol>
<li>Add to basket</li>
<li>Pay</li>
</ol>role="list"<li><li>An item in <ol>, <ul> or <menu>. It must be a direct child of one of them, or it is not counted as part of the list.
<ul>
<li><a href="/shop">Shop</a></li>
</ul>role="listitem"<dl>A description list of term and description pairs, such as specifications or a glossary. Keep only <dt>, <dd> and wrapping <div> elements directly inside it.
<dl>
<dt>Weight</dt>
<dd>220 g</dd>
</dl>Guides that use it
<figure>Self-contained content such as an image, chart or code sample, usually with a <figcaption> that names it. The caption does not replace an image’s alt.
<figure>
<img src="chart.png" alt="Sales doubled from May to June">
<figcaption>Sales, 2026</figcaption>
</figure>role="figure"<figcaption><img>Guides that use it
<figcaption>The caption of its <figure>, as its first or last child. It gives the figure its accessible name.
<figcaption>Figure 2: the checkout flow</figcaption><figure>Guides that use it
<a>A link to another page or place: a link only with an href, and reached with Tab and Enter. Its text must say where it goes; for an action on the page, use <button>.
<a href="/returns">Returns policy</a>role="link"hrefaria-current<abbr>An abbreviation. Its title attribute is not reliably read or shown on touch screens, so spell the term out in the text the first time it appears.
<p>Web Content Accessibility Guidelines (<abbr>WCAG</abbr>)</p>title<ruby>Ruby annotation: small text above or beside characters, such as furigana showing how kanji are read. Screen readers vary in how they read it, often saying both base and ruby.
<ruby>漢字<rp>(</rp><rt>かんじ</rt><rp>)</rp></ruby><mark>Text highlighted for reference, such as search matches. Many screen readers don’t announce it, so don’t rely on the highlight alone to convey something.
<p>Results for <mark>notebook</mark> covers</p><s>Text that is no longer accurate or relevant, such as an old price. Screen readers often don’t say it is struck through, so add words like “was” if it matters.
<p><s>£30</s> Now £20</p><del>Guides that use it
<del>Text removed from the document, for a record of edits. Most screen readers don’t announce it by default, so say in words what changed if it matters.
<p>Open <del>until 6pm</del> <ins>until 8pm</ins>.</p><ins>Text added to the document, for a record of edits. Most screen readers don’t announce it by default.
<p>Open <ins>until 8pm</ins> on Fridays.</p><del><img>An image. alt is required: describe what the image tells the reader, or use alt="" for a decorative image so screen readers skip it. Without alt, many screen readers read the file name.
<img src="mug.jpg" alt="Blue enamel mug with a white rim"><area>A clickable area in an image map. With an href it is a link, and its alt is the link text, so it is required.
<area shape="circle" coords="120,80,30" href="/toilets" alt="Toilets">role="link"alt<svg>An inline SVG drawing. For a meaningful image, add role="img" and a name with aria-label or <title>; for decoration, add aria-hidden="true".
<svg role="img" aria-label="Rated 4 out of 5" viewBox="0 0 80 16">…</svg>role="img"aria-hiddenaria-label<canvas>A surface drawn on with script. What is drawn is invisible to assistive technology, so give the same information as text, in the fallback content or nearby.
<canvas width="400" height="200">
<p>Visitors rose from 200 in May to 450 in June.</p>
</canvas><iframe>Embeds another page, such as a map or a video player. Give it a title that says what it contains, so screen reader users know whether to go in.
<iframe src="https://maps.example.com/shop" title="Map to our shop"></iframe>title<video>A video player. Add controls, captions with <track>, and an audio description or transcript; don’t autoplay with sound.
<video src="tour.mp4" controls>
<track kind="captions" src="tour.en.vtt" srclang="en" label="English">
</video><audio>An audio player. Add controls and offer a transcript; audio that plays on its own for more than three seconds needs a way to stop it.
<audio src="episode-12.mp3" controls></audio>
<a href="episode-12.html">Transcript</a><track>How captions and audio descriptions reach a <video>: a WebVTT file whose kind says which it is. Prerecorded video with sound needs captions (WCAG 1.2.2).
<track kind="captions" src="tour.en.vtt" srclang="en" label="English" default><table>A data table, where screen readers announce each cell with its headers. Use it for data in rows and columns, not for layout, and give it a <caption>.
<table>
<caption>Delivery prices</caption>
…
</table>role="table"<caption><th><caption>The title of a table, as its first child. It names the table, so screen reader users know what it holds before reading cells.
<caption>Opening hours</caption><table>Guides that use it
<th>A header cell for its column or row. Set scope="col" or scope="row" so its direction is clear, and use headers for complex tables.
<th scope="col">Price</th><td>A data cell. Screen readers announce it with its row and column headers, worked out from <th> elements or the headers attribute.
<td>£3.50</td><form>A form that submits its fields. Submitting with Enter works only inside one. It is a form landmark only when it has a name.
<form action="/subscribe" method="post" aria-label="Newsletter">…</form>role="form"<search><button><fieldset>Groups related fields, such as a set of radio buttons or an address, under the question in its <legend>, which screen readers announce with the fields.
<fieldset>
<legend>Delivery speed</legend>
…
</fieldset><legend>The caption of a <fieldset>, as its first child. Keep it short: some screen readers repeat it on every field in the group.
<legend>Payment method</legend><fieldset><label>The visible name of a form field, tied to it with for and the field’s id, or by wrapping it. It is read when the field gets focus, and clicking it focuses the field.
<label for="email">Email</label>
<input id="email" type="email" autocomplete="email">for<input><input>A form field whose type sets what it is: text, email, checkbox, radio, number, date and more. Every one needs a label, and the right type and autocomplete give people the right keyboard and autofill.
<label for="tel">Phone</label>
<input id="tel" type="tel" autocomplete="tel">role="textbox"role="searchbox"role="checkbox"role="radio"role="button"role="slider"role="spinbutton"role="combobox"<label>typeautocompletename<textarea>A multi-line text field. Like any field it needs a label; don’t stop it being resized if people may need more room.
<label for="note">Gift message</label>
<textarea id="note" rows="4"></textarea>role="textbox"<label><select>A list of options to choose from, with keyboard and screen reader support built in. Give it a label, and don’t submit or navigate when the selection changes.
<label for="size">Size</label>
<select id="size" name="size">
<option>A5</option>
</select><optgroup><optgroup>Groups related options in a <select> under a label, which many screen readers announce with the options.
<optgroup label="Notebooks">
<option>A5 dotted</option>
</optgroup>role="group"<select>label<datalist>Suggestions for an <input>, tied to it with the input’s list attribute; people can still type anything. Screen reader support for the suggestions varies between browsers.
<label for="city">City</label>
<input id="city" list="cities">
<datalist id="cities">
<option value="Osaka">
</datalist><input>Guides that use it
<button>A button that does something on the page. It is focusable and works with Enter and Space for free. Inside a form it submits by default, so set type="button" for other actions.
<button type="button" aria-expanded="false">Menu</button>role="button"typearia-pressed<output>The result of a calculation or user action, such as a total. It is a status live region, so screen readers may announce changes to it.
<output for="qty price" name="total">£24</output><progress>How far a task has got, such as an upload. Give it a label; without a value it shows that something is happening but not how much.
<label for="up">Uploading</label>
<progress id="up" max="100" value="40">40%</progress>role="progressbar"Guides that use it
<meter>A measurement within a known range, such as password strength, which screen readers announce with its value. Give it a label, and say the level in text too, not by colour alone (WCAG 1.4.1). For task progress, use <progress>.
<label for="disk">Storage</label>
<meter id="disk" min="0" max="10" value="7">7 of 10 GB</meter>role="meter"<details>A disclosure widget that shows and hides its content when its <summary> is pressed, with keyboard and screen reader support built in. Several with the same name open one at a time.
<details>
<summary>Delivery and returns</summary>
<p>Free returns within 30 days.</p>
</details><summary>The always-visible label of a <details> that opens and closes it. Most browsers expose it as a button-like control with its expanded state, though the exact role varies; don’t put other interactive elements inside it.
<summary>Size guide</summary><dialog>A dialog box. Opened with showModal(), it is modal: it moves focus inside, makes the rest of the page inert and closes with Esc. Give it a name from its heading.
<dialog aria-labelledby="del-title">
<h2 id="del-title">Delete this list?</h2>
…
</dialog>aria-modalinertlangSets the language of the element's content, so screen readers pronounce it with the right voice and browsers hyphenate and translate it correctly. Set it on <html> for the page (WCAG 3.1.1) and on any passage in another language (WCAG 3.1.2).
<html lang="en">
…
<p>The French call it <i lang="fr">l'esprit de l'escalier</i>.</p><html>dirdirltrrtlautoSets the text direction. Use rtl for Arabic, Hebrew and other right-to-left scripts, and auto for user-generated text whose direction is not known in advance.
<p lang="ar" dir="rtl">مرحبا بكم</p>langtitleAdvisory text shown as a tooltip on mouse hover. Do not rely on it: keyboard and touch users never see it, and screen readers read it inconsistently. Its one dependable use is naming an <iframe>.
<iframe src="/map" title="Map of our shop on Hill Street"></iframe>inertMakes an element and everything in it unreachable: it cannot be focused, clicked or found by a screen reader, though it stays visible. Use it on the page behind a custom modal or on content that is shown but not yet usable.
<main inert>…</main>
<div role="dialog" aria-modal="true" aria-labelledby="dlg-title">…</div>aria-modalGuides that use it
tabindexinteger (use 0 or -1)Controls whether an element takes keyboard focus. 0 adds it to the Tab order in source order, -1 lets scripts focus it without putting it in the Tab order. Never use a positive number: it jumps the element ahead of everything else.
<h2 id="results-title" tabindex="-1">12 results</h2>aria-activedescendantautofocusMoves focus to the element when the page or dialog opens. Use it only where people expect to start, such as the first field of a dialog; elsewhere it skips content a screen reader user has not heard yet.
<dialog>
<label for="rename">New name</label>
<input id="rename" autofocus>
</dialog>accesskeyAssigns a keyboard shortcut to an element. Avoid it: the keys clash with screen reader, browser and system shortcuts, the modifier differs between browsers, and nothing tells people the shortcut exists.
<a href="/search" accesskey="s">Search</a>aria-keyshortcutscontenteditabletruefalseplaintext-onlyMakes the element's content editable in place. The browser exposes it as an editable text area, but it has no name: give it a label with aria-labelledby or aria-label, and aria-multiline where it takes several lines.
<p id="note-label">Note</p>
<div contenteditable="true" role="textbox" aria-labelledby="note-label" aria-multiline="true"></div>inputmodenonetextdecimalnumerictelsearchemailurlChooses which on-screen keyboard to show, such as a number pad for a one-time code, without the validation and spin buttons of type="number".
<label for="code">Security code</label>
<input id="code" inputmode="numeric" autocomplete="one-time-code">typeautocompleteGuides that use it
roleGives an element one of the ARIA roles, which tells assistive technology what it is. It changes only what is announced, never behaviour, so a native element that already has the role is better (see the ARIA roles below).
<div role="status">3 results</div>role="button"role="status"popoverautomanualhintTurns an element into a popover shown in the top layer, opened by a button with popovertarget. An auto popover closes with Escape and when you click outside it; popover does not trap focus or make the page inert, so it is not a modal dialog.
<button type="button" popovertarget="help">Help</button>
<div id="help" popover>Codes are on the back of your card.</div>popovertargethttp-equivcontent-typedefault-stylerefreshcontent-security-policyx-ua-compatibleMakes a <meta> act like an HTTP header. Avoid http-equiv="refresh" with a delay: a page that reloads or redirects on its own takes people away before they finish reading (WCAG 2.2.1).
<meta http-equiv="content-security-policy" content="default-src 'self'"><meta>Guides that use it
hrefThe URL a link goes to. An <a> without href is not a link and cannot be focused; never use href="#" or javascript: to make a link act as a button.
<a href="/returns">Returns policy</a><a><area>role="link"<button>target_self_blank_parent_topnameWhere to open the link. _blank opens a new tab or window, which disorients people and breaks the Back button, so use it sparingly and say so in the link text.
<a href="/terms.pdf" target="_blank">Terms (PDF, opens in a new tab)</a>Guides that use it
altThe text alternative for an image: what it conveys in this context (WCAG 1.1.1). Use alt="" for a purely decorative image so screen readers skip it; leaving alt out makes many read the file name.
<img src="chart.png" alt="Sales rose 40% between April and June."><img><area><input>role="img"controlsShows the browser's own playback controls, which work with the keyboard and screen readers. Keep them unless you build a custom player that is just as accessible.
<video src="tour.mp4" controls>
<track kind="captions" src="tour.en.vtt" srclang="en" label="English">
</video>autoplayStarts playback as soon as it can. Sound that plays on its own for more than 3 seconds needs a way to pause or mute it (WCAG 1.4.2), and moving video needs a pause control (WCAG 2.2.2); better not to autoplay at all.
<video src="loop.mp4" autoplay muted loop playsinline controls></video>Guides that use it
mutedStarts the media with its sound off. Browsers allow muted video to autoplay; it still needs a pause control if it moves.
<video src="hero.mp4" autoplay muted playsinline controls></video>Guides that use it
loopRestarts the media when it ends. Looping video that starts on its own and moves for more than 5 seconds needs a way to pause it (WCAG 2.2.2).
<video src="steam.mp4" muted loop controls></video>Guides that use it
kindsubtitlescaptionsdescriptionschaptersmetadataWhat a text track is. Use captions for dialogue plus sound effects for deaf viewers (WCAG 1.2.2), subtitles for when the sound can be heard but not understood, such as a translation, and descriptions for text audio description.
<track kind="captions" src="talk.en.vtt" srclang="en" label="English">srclangThe language of a text track, required for subtitles. Pair it with a label that names the language in words people recognise.
<track kind="subtitles" src="talk.ja.vtt" srclang="ja" label="日本語">defaultTurns this text track on by default. Put it on the captions in the page's language, so captions are there without hunting for the setting.
<track kind="captions" src="talk.en.vtt" srclang="en" label="English" default>scopecolrowcolgrouprowgroupSays whether a header cell labels its column, row or group of them, so screen readers read the right header with each data cell.
<th scope="row">Saturday</th><th>headersrole="columnheader"role="rowheader"headersA list of header cell ids that apply to this cell, for tables too complex for scope. Prefer simplifying the table first.
<td headers="tokyo q1">120</td>Guides that use it
abbrA short form of a header cell's text, for when the full header is long. Screen reader support is patchy, so keep the visible header itself reasonably short.
<th scope="col" abbr="Qty">Quantity ordered</th><th>colspanHow many columns a cell spans. Screen readers announce the span, but merged cells make tables harder to follow; split complex tables where you can.
<th colspan="2" scope="colgroup">Opening hours</th><td><th>rowspanscopearia-colspanGuides that use it
rowspanHow many rows a cell spans. As with colspan, keep merged cells to a minimum so people can follow the table cell by cell.
<th rowspan="3" scope="rowgroup">Weekdays</th><td><th>colspanaria-rowspanforTies a <label> to the control with that id, which gives the control its accessible name and makes clicking the label focus or toggle the control.
<label for="postcode">Postcode</label>
<input id="postcode" autocomplete="postal-code"><label><output>aria-labelledbylabelNames an <optgroup>, which many screen readers announce with its options, or a <track>, shown in the player’s captions menu, where the language should be named in words people recognise.
<optgroup label="Europe">
<option>Lisbon</option>
</optgroup>nameGroups radio buttons, so the arrow keys move between them and screen readers say how many there are. It is not an accessible name: each control still needs a label.
<input id="size-s" type="radio" name="size" value="s">
<label for="size-s">Small</label><input><button><select><textarea><form><fieldset><output><iframe><meta><details>aria-labeltypeOn <input>, the kind of control (text, email, checkbox, date…), which sets its role, keyboard and validation. On <button>, submit, reset or button: set type="button" on any button that does not submit a form.
<button type="button" aria-expanded="false" aria-controls="filters">Filters</button>autocompletenameemailtelstreet-addresspostal-codecc-numberusernamenew-passwordcurrent-passwordone-time-codeoff…Says what personal data a field collects, so browsers and password managers can fill it in. Fields about the user need the matching token (WCAG 1.3.5), which also saves typing for people with motor and memory impairments.
<label for="email">Email</label>
<input id="email" type="email" autocomplete="email"><input><select><textarea><form>typeplaceholderSample text shown in an empty field. It is not a label: it disappears as soon as people type, is often low contrast, and is not read reliably. Put instructions in a visible label or hint.
<label for="search">Search recipes</label>
<input id="search" type="search" placeholder="e.g. miso soup"><input><textarea><label>aria-placeholderrequiredMakes a field mandatory: the browser blocks submission and screen readers announce the field as required. Also show that it is required in the visible label, not with colour or an unexplained asterisk alone.
<label for="name">Full name (required)</label>
<input id="name" autocomplete="name" required><input><select><textarea>aria-invaliddisabledDisables a form control: it is removed from the Tab order, cannot be used and is not submitted. Because it cannot be focused, people may not find it or learn why it is off; aria-disabled keeps it focusable instead.
<button type="submit" disabled>Place order</button>readonlyMakes a field's value unchangeable while keeping it focusable, readable and submitted. Unlike disabled, people can still reach it and select its text.
<label for="ref">Order reference</label>
<input id="ref" value="A-20931" readonly><input><textarea>aria-readonlyGuides that use it
listTies a field to a <datalist>, so the browser offers suggestions and handles their keys itself, while people can still type anything. Simpler than a scripted combobox when the list needn’t be styled.
<label for="city">City</label>
<input id="city" list="cities">
<datalist id="cities"><option value="Osaka"></option></datalist><input><datalist>role="combobox"Guides that use it
openShows the content of a <details> element, or shows a <dialog>. Open a dialog with showModal() instead of setting open, so it is modal and focus moves into it.
<details open>
<summary>Delivery</summary>
<p>Free over ¥5,000.</p>
</details><details><dialog>aria-expandedpopovertargetMakes a button open, close or toggle the popover with that id. The browser exposes the button's expanded state and, if focus is inside the popover when it closes, moves focus back to where it was before (usually the button).
<button type="button" popovertarget="menu">Account</button>
<div id="menu" popover>…</div><button><input>popoveraria-expandedcommandshow-modalcloserequest-closeshow-popoverhide-popovertoggle-popover--customOpens or closes a <dialog> or popover from a button with no script. show-modal opens a dialog as showModal() does: modal, with focus moved inside and the page behind inert.
<button type="button" commandfor="confirm" command="show-modal">Delete</button><button>commandfor<dialog>commandforNames, by id, the dialog or popover a button’s command acts on, so the button works without a script, even before scripts have loaded.
<button type="button" commandfor="confirm" command="close">Cancel</button><button>commandpopovertargetrole= "button"Something that performs an action when pressed. With the role you must add tabindex="0" and make Enter and Space activate it yourself. Prefer <button>, which does all of that already.
<div role="button" tabindex="0">Save</div>Guides that use it
role= "link"A reference that takes people somewhere when activated. With the role you must add focus and Enter yourself, and lose the browser’s link features. Prefer <a href>.
<span role="link" tabindex="0">Delivery terms</span><a><area>hrefaria-currentrole= "checkbox"A box that is checked, unchecked or, with aria-checked="mixed", partly checked. Requires aria-checked, focus and Space to toggle it. Prefer <input type="checkbox">.
<div role="checkbox" aria-checked="false" tabindex="0">
Email me updates
</div><input>aria-checkedrole="switch"Guides that use it
role= "radio"One option in a set where only one can be checked. Requires aria-checked, sits in a radiogroup, and the arrow keys move and check within the set. Prefer <input type="radio">.
<div role="radio" aria-checked="true" tabindex="0">Standard delivery</div>Guides that use it
role= "switch"An on/off control, such as a setting that takes effect at once. Requires aria-checked ("true" or "false"); a <button> with the role is the simplest base.
<button type="button" role="switch" aria-checked="false">
Dark mode
</button>Guides that use it
role= "option"A selectable item in a listbox. It must be owned by a listbox (or a group in one), and ARIA 1.2 requires aria-selected on it: true on selected options, false on the rest.
<li role="option" id="opt-tokyo" aria-selected="true">Tokyo</li>role= "menuitem"An action in a menu or menubar. It must be inside a menu, menubar or a group within one, and the menu moves focus between items with the arrow keys.
<ul role="menu" aria-label="Row actions">
<li role="menuitem" tabindex="-1">Rename</li>
</ul>role= "menuitemcheckbox"A menu item that can be checked or unchecked, such as “Show grid”. Requires aria-checked; activating it toggles the state and usually leaves the menu open.
<li role="menuitemcheckbox" aria-checked="true" tabindex="-1">
Show grid
</li>role="menu"aria-checkedrole= "menuitemradio"One of a set of menu items where only one can be checked, such as a sort order. Requires aria-checked; group the set with role="group" or separators.
<li role="menuitemradio" aria-checked="true" tabindex="-1">
Newest first
</li>role= "tab"One label in a tablist, which shows its tabpanel. Set aria-selected on it and aria-controls to its panel; the arrow keys move between tabs.
<button role="tab" id="tab-1" aria-selected="true"
aria-controls="panel-1">Details</button>Guides that use it
role= "tabpanel"The content a tab shows. Name it with aria-labelledby pointing to its tab, and hide the panels that aren’t shown.
<div role="tabpanel" id="panel-1" aria-labelledby="tab-1">
…
</div>role="tab"aria-labelledbyhiddenGuides that use it
role= "textbox"A field for free text; with aria-multiline="true", one that takes several lines. Prefer <input> or <textarea>; a contenteditable element needs the role and a name.
<div role="textbox" contenteditable="true" aria-multiline="true"
aria-label="Message"></div>role= "searchbox"A text field for search terms. Prefer <input type="search">, which has the role, and put the search form in a search landmark.
<input role="searchbox" aria-label="Search products">role= "slider"Picks a value from a range by moving a thumb. Requires aria-valuenow and a name, and arrow keys to change the value. Prefer <input type="range">.
<div role="slider" aria-label="Volume" tabindex="0"
aria-valuenow="5" aria-valuemin="0" aria-valuemax="10"></div>Guides that use it
role= "spinbutton"A field holding a number that the Up and Down arrows step through. Set aria-valuenow when it has a value. Prefer <input type="number"> for real quantities.
<div role="spinbutton" aria-label="Quantity" tabindex="0"
aria-valuenow="1" aria-valuemin="1">1</div><input>aria-valuenowrole= "progressbar"Shows how far a task has got. Give it a name and aria-valuenow (with aria-valuemin and aria-valuemax); leave out aria-valuenow when the progress is unknown. Prefer <progress>.
<div role="progressbar" aria-label="Upload" aria-valuenow="40"
aria-valuemin="0" aria-valuemax="100"></div>Guides that use it
role= "treeitem"An item in a tree. One with children takes aria-expanded; it must be owned by a tree or by a group inside one.
<li role="treeitem" aria-expanded="false" tabindex="0">
Documents
</li>Guides that use it
role= "gridcell"A cell in a grid or treegrid, which can take focus or be edited. It must be owned by a row in a grid; the arrow keys move between cells.
<div role="row">
<div role="gridcell" tabindex="-1">Mon 3</div>
</div>role= "combobox"A field that pops up a listbox, grid, tree or dialog of suggestions. Requires aria-expanded and, in ARIA 1.2, aria-controls pointing at the popup; use aria-activedescendant for the highlighted option.
<input role="combobox" aria-expanded="false" aria-controls="cities"
aria-autocomplete="list" aria-label="City">role= "listbox"A list of options to choose one or, with aria-multiselectable, several. It needs a name and options; the arrow keys move the selection. Prefer <select> where it fits.
<ul role="listbox" aria-label="City" tabindex="0">
<li role="option" aria-selected="true">Tokyo</li>
</ul>role= "menu"A list of actions or settings, like an application’s menu. It is not for site navigation links: screen readers switch to menu mode and expect arrow-key behaviour.
<ul role="menu" aria-label="File">
<li role="menuitem" tabindex="-1">Open</li>
</ul>role= "menubar"A row of menus that usually stays visible, as in a desktop application. Left and Right move between its items; like menu, it is not for a website’s navigation.
<ul role="menubar" aria-label="Editor">
<li role="menuitem" aria-haspopup="menu" tabindex="0">File</li>
</ul>role= "radiogroup"Groups a set of radio buttons under one name. Give it a name; with native radios, a <fieldset> and <legend> do the same job.
<div role="radiogroup" aria-labelledby="ship-label">
<div role="radio" aria-checked="true" tabindex="0">Standard</div>
</div>role= "tablist"The container of a set of tabs. It must own the tabs; give it a name, and aria-orientation="vertical" when the tabs are stacked.
<div role="tablist" aria-label="Product">
<button role="tab" aria-selected="true">Details</button>
</div>Guides that use it
role= "tree"A list of items that can be expanded and collapsed, such as folders. It needs a name and treeitems; the arrow keys move, open and close items.
<ul role="tree" aria-label="Files">
<li role="treeitem" aria-expanded="false" tabindex="0">Documents</li>
</ul>Guides that use it
role= "treegrid"A grid whose rows can be expanded and collapsed like a tree, such as an email thread list. Rows take aria-expanded and aria-level.
<div role="treegrid" aria-label="Inbox">
<div role="row" aria-level="1" aria-expanded="true">…</div>
</div>role= "grid"A table of cells navigated with the arrow keys, such as a calendar or a spreadsheet. Only one cell is in the Tab order; use a plain table when nothing in it is interactive.
<div role="grid" aria-label="May 2026">
<div role="row">
<div role="gridcell" tabindex="0">1</div>
</div>
</div>role= "heading"A heading for a section, which screen reader users jump between. Requires aria-level; browsers usually treat a missing level as 2. Prefer <h1>–<h6>.
<div role="heading" aria-level="2">Delivery</div><h1>–<h6>aria-levelGuides that use it
role= "list"A list of items, announced with its count. It must contain listitems. Prefer <ul> or <ol>; add the role back only where CSS such as list-style: none drops it in Safari.
<ul role="list" class="plain">
<li>Free returns</li>
</ul>role= "listitem"One item in a list; it must be contained in or owned by a list. Prefer <li>.
<div role="list">
<div role="listitem">Free returns</div>
</div><li>role="list"Guides that use it
role= "table"Data in rows and columns that isn’t interactive. Prefer <table>; the role is for tables built from other elements, and needs rows and cells inside.
<div role="table" aria-label="Opening hours">
<div role="row">…</div>
</div><table>role="grid"role="row"Guides that use it
role= "row"A row of cells in a table, grid or treegrid; it must be inside one, or in a rowgroup within one. Prefer <tr>.
<div role="row">
<div role="cell">Mon–Fri</div>
</div>role="cell"role="rowgroup"Guides that use it
role= "rowgroup"A group of rows, such as a table’s head or body. Prefer <thead>, <tbody> and <tfoot>.
<div role="rowgroup">
<div role="row">…</div>
</div>role="row"role= "columnheader"The header of a column, read with each cell under it. Prefer <th scope="col">; in a sortable table it takes aria-sort.
<div role="columnheader" aria-sort="ascending">Price</div>Guides that use it
role= "rowheader"The header of a row, read with each cell in it. Prefer <th scope="row">.
<div role="row">
<div role="rowheader">Saturday</div>
<div role="cell">10:00–16:00</div>
</div><th>scoperole="columnheader"Guides that use it
role= "cell"A cell in a static table, owned by a row. Prefer <td>; for a layout built with CSS grid, the roles restore the table that display: grid can hide.
<div role="row">
<div role="cell">Mon–Fri</div>
<div role="cell">9:00–18:00</div>
</div><td>role="row"role="gridcell"Guides that use it
role= "img"One image, possibly made of several parts, such as an inline SVG, emoji or icon font. It needs aria-label or aria-labelledby; its children are not read.
<svg role="img" aria-label="4 out of 5 stars" viewBox="0 0 80 16">
…
</svg>role= "figure"A self-contained illustration, chart or code sample, usually with a caption. Prefer <figure> with <figcaption>.
<div role="figure" aria-labelledby="fig-1">
<img src="sales.png" alt="…">
<p id="fig-1">Sales by month</p>
</div><figure><figcaption>role= "group"A set of related elements that isn’t a landmark, such as related fields or the options in a menu section. Give it a name when the grouping matters. Prefer <fieldset> for form fields.
<div role="group" aria-labelledby="addr">
<h3 id="addr">Delivery address</h3>
…
</div>role= "toolbar"A set of controls, such as text formatting buttons. Give it a name when there is more than one; only one control is in the Tab order and the arrow keys move between them.
<div role="toolbar" aria-label="Formatting">
<button type="button" aria-pressed="false">Bold</button>
</div>aria-orientationaria-pressedrole= "separator"A divider between sections or menu groups. Prefer <hr>. A focusable separator is a widget that resizes panes, and then needs aria-valuenow.
<div role="separator" aria-orientation="vertical" tabindex="0"
aria-valuenow="30" aria-label="Resize sidebar"></div>aria-orientationaria-valuenowrole= "tooltip"A short description that appears when its owner has focus or the pointer. It never takes focus itself; the owner points to it with aria-describedby, and Escape hides it.
<button type="button" aria-describedby="tip">Share</button>
<div role="tooltip" id="tip">Copy a link to this page</div>aria-describedbypopoverGuides that use it
role= "note"A note that is parenthetical or ancillary to the main content, such as a tip beside a step.
<div role="note">
<p>Tip: keep your receipt.</p>
</div>role="complementary"<aside>role= "article"A self-contained piece, such as a post, a comment or a product card. Prefer <article>.
<div role="article" aria-labelledby="post-1">
<h2 id="post-1">Spring menu</h2>
</div><article>role="feed"role= "feed"A scrolling list of articles that loads more as people reach the end. Its articles take aria-posinset and aria-setsize, and the feed sets aria-busy while it adds them.
<div role="feed" aria-label="Posts" aria-busy="false">
<article aria-posinset="1" aria-setsize="-1">…</article>
</div>Guides that use it
role= "meter"A value within a known range, such as disk use or password strength; not progress. Requires aria-valuenow and a name. Prefer <meter>.
<div role="meter" aria-label="Storage used" aria-valuenow="72"
aria-valuemin="0" aria-valuemax="100"></div>role= "none"Removes an element’s own role, keeping its content, such as a layout table. Ignored on focusable elements and on those with global ARIA attributes. Same as presentation.
<table role="none">
<tr><td>…</td></tr>
</table>Guides that use it
role= "presentation"The older name for none: removes an element’s role but keeps its content. Ignored on focusable elements and on those with global ARIA; an <img alt=""> already has it.
<ul role="presentation">
<li role="presentation">…</li>
</ul>role= "application"Tells screen readers to pass every key to the page, turning off their reading keys. Almost never right: only for a widget that handles all keys itself and needs no reading.
<div role="application" aria-label="Map">
…
</div>role= "banner"The site-wide header, with the logo and main navigation; one per page. Prefer a <header> that isn’t inside article, aside, main, nav or section.
<div role="banner">
<a href="/">Fern & Fold</a>
</div><header>role="contentinfo"Guides that use it
role= "navigation"A set of links for moving around the site or page. Name each one when there is more than one, without the word “navigation”. Prefer <nav>.
<div role="navigation" aria-label="Breadcrumb">
…
</div><nav>aria-labelrole="menubar"Guides that use it
role= "search"The region that holds the site or page search. Prefer <search>; put the role on the <form> where older browsers matter.
<form role="search" action="/search">
<input type="search" name="q" aria-label="Search">
</form>role= "main"The page’s main content, which a skip link and screen reader shortcuts jump to; one visible per page. Prefer <main>.
<div role="main" id="content">
<h1>Spring menu</h1>
</div><main>Guides that use it
role= "region"A section important enough to be listed among the landmarks. It is a landmark only when it has a name; a <section> with aria-labelledby gets the role.
<section aria-labelledby="cart-title">
<h2 id="cart-title">Your bag</h2>
</section>role= "form"A region holding a form. It is a landmark only when it has a name, so name the forms people need to find. Prefer <form> with aria-label or aria-labelledby.
<div role="form" aria-label="Newsletter">
…
</div><form>role="search"role= "complementary"Content that supports the main content but makes sense on its own, such as related links. Name it when there is more than one. Prefer <aside>.
<div role="complementary" aria-label="Related articles">
…
</div><aside>role="note"role= "contentinfo"The site-wide footer, with copyright and policy links; one per page. Prefer a <footer> that isn’t inside article, aside, main, nav or section.
<div role="contentinfo">
<a href="/privacy">Privacy</a>
</div><footer>role="banner"Guides that use it
role= "status"Advisory information, such as “Saved” or a result count, read when the screen reader is free (polite, atomic). Put it on the page empty, before the message arrives.
<p role="status"></p><output>aria-atomicrole= "alert"An urgent message read at once, interrupting what is being read (aria-live="assertive"). Keep it for messages people must act on now; put it on the page before the message arrives.
<p role="alert"></p>role= "log"A region where new entries are added in order, such as a chat. It is polite: new entries are read when the screen reader is free, and old ones aren’t repeated.
<div role="log" aria-label="Chat">
<p>Sam: On my way</p>
</div>aria-relevantGuides that use it
role= "timer"A counter of time elapsed or remaining. Its changes are not announced (aria-live="off"), so a running clock doesn’t talk over the page; announce milestones separately.
Sale ends in <span role="timer">02:14:09</span>Guides that use it
role= "dialog"A window over the page that people interact with. It needs a name, focus moved into it, and aria-modal="true" when it blocks the page. Prefer <dialog> opened with showModal().
<div role="dialog" aria-modal="true" aria-labelledby="d-title">
<h2 id="d-title">Edit address</h2>
</div>aria-modalrole= "alertdialog"A dialog with an urgent message that needs a response, such as “Delete this file?”. Name it, describe it with aria-describedby, and move focus into it.
<div role="alertdialog" aria-modal="true" aria-labelledby="d-title"
aria-describedby="d-text">
…
</div>aria-labelstringGives an element its accessible name when no visible text does, such as an icon button. Use it on interactive elements and landmarks, not on a div or span with no role, and include any visible label in it so voice control users can say it.
<button type="button" aria-label="Search">
<svg aria-hidden="true">…</svg>
</button>aria-labelledbyID reference listNames an element with the text of other elements, by their ids, so the name stays in step with what is shown. It takes precedence over aria-label and the element’s own content, and can point to hidden elements.
<h2 id="billing">Billing address</h2>
<section aria-labelledby="billing">…</section>aria-describedbyID reference listPoints to elements whose text adds a description to the name, such as a hint or an error under a field. Screen readers usually read it after the name and role, and some only on focus, so don’t put anything essential only there.
<label for="pw">Password</label>
<input id="pw" type="password" aria-describedby="pw-hint">
<p id="pw-hint">At least 12 characters.</p>aria-descriptionaria-errormessagearia-descriptionstringGives an element a description as a string, like aria-describedby without an element to point to. Text that sighted people need too belongs on the page, referenced with aria-describedby, instead.
<button type="button" aria-description="Opens in a new window">Help</button>aria-describedbyaria-detailsID referencePoints to an element with longer, structured details about this one, such as a table that explains a chart. Unlike aria-describedby, the details are not read out as a flat string: screen readers that support it say that details exist and let people go to them.
<img src="sales.png" alt="Sales by quarter" aria-details="sales-table">
<table id="sales-table">…</table>aria-describedby<figure>aria-roledescriptionstringReplaces the spoken name of an element’s role with your own words, such as “slide” for a carousel group. Use it rarely, only on an element with a real role, never on a generic div or span, and never to rename widgets people already know.
<div role="group" aria-roledescription="slide" aria-label="2 of 5">
…
</div>role="group"Guides that use it
aria-expandedtruefalseundefinedWhether the content a control shows and hides is open: put it on the button, menu button or combobox that toggles it, not on the panel, and update it every time. Leave it off a control that expands nothing.
<button type="button" aria-expanded="false" aria-controls="faq-1">
Delivery times
</button>
<div id="faq-1" hidden>…</div>aria-controls<details>role="combobox"hiddenaria-haspopupfalsetruemenulistboxtreegriddialogSays that the control opens a popup and what kind: true means menu. Use it only when the popup really has that role, such as menu for a role="menu"; a disclosure that shows plain content needs aria-expanded instead.
<button type="button" aria-haspopup="menu" aria-expanded="false"
aria-controls="actions">Actions</button>aria-pressedtruefalsemixedundefinedTurns a button into a toggle button and says whether it is pressed, such as Bold or Mute. Keep the name the same when the state changes; changing the label and aria-pressed together says it twice.
<button type="button" aria-pressed="false">Mute</button>role="button"role="switch"aria-checkedtruefalsemixedundefinedThe checked state of a custom checkbox, radio, switch or checkable menu item; mixed is for a checkbox that stands for a partly checked group. Update it on every change. A native input type="checkbox" needs none.
<div role="checkbox" aria-checked="false" tabindex="0">
Subscribe
</div>aria-selectedtruefalseundefinedMarks the selected item in a tablist, listbox, grid or tree: the open tab, the chosen option. It is not for checkboxes (aria-checked) or the current page in a menu (aria-current).
<button role="tab" aria-selected="true" aria-controls="panel-1">
Details
</button>aria-disabledtruefalseMarks an element as disabled while keeping it focusable and in the reading order, so people can still find it and learn why. Unlike the disabled attribute it doesn’t block anything: your script must ignore clicks and keys.
<button type="submit" aria-disabled="true"
aria-describedby="why">Pay now</button>aria-readonlyGuides that use it
aria-readonlytruefalseSays a custom widget’s value can be read and focused but not changed, such as a grid cell or a textbox. A native input uses the readonly attribute instead.
<div role="textbox" aria-readonly="true" tabindex="0"
aria-label="Order number">A-10293</div>readonlyaria-disabledaria-requiredtruefalseSays a field must be filled in, for screen readers only: it doesn’t stop the form submitting. On native fields the required attribute does both; either way, show that the field is required in the visible label too.
<p id="size-q">Size (required)</p>
<div role="radiogroup" aria-labelledby="size-q" aria-required="true">
<div role="radio" aria-checked="false" tabindex="0">Small</div>
…
</div>aria-invalidaria-invalidfalsetruegrammarspellingSays a field’s value fails validation, so screen readers announce it as invalid. Set it after the user submits or leaves the field, not before they type, and pair it with a visible message referenced by aria-describedby or aria-errormessage.
<label for="zip">Postcode</label>
<input id="zip" aria-invalid="true" aria-describedby="zip-err">
<p id="zip-err">Enter a 7-digit postcode.</p>aria-errormessagearia-describedbyaria-requiredaria-errormessageID referencePoints to the element holding a field’s error message. It is only used while the field has aria-invalid="true". Support is still uneven, so many sites also reference the message with aria-describedby.
<label for="email">Email</label>
<input id="email" aria-invalid="true" aria-errormessage="email-err">
<p id="email-err">Enter an email address like [email protected].</p>aria-invalidaria-describedbyaria-placeholderstringA short hint shown in an empty custom textbox or searchbox, like the placeholder attribute. It is not a label: give the field a name as well.
<div role="textbox" contenteditable="true" aria-label="Note"
aria-placeholder="Add a note"></div>placeholderrole="textbox"aria-autocompletenoneinlinelistbothTells screen readers that a combobox or text field suggests completions as you type: inline completes the text in the field, list shows a popup of suggestions, both does the two. It describes the behaviour; your script still has to provide it.
<input role="combobox" aria-label="City" aria-autocomplete="list"
aria-expanded="false" aria-controls="cities">Guides that use it
aria-multilinetruefalseSays a role="textbox" takes more than one line, so people know Enter may add a line rather than submit; your script still has to handle the key. A native textarea already says so.
<div role="textbox" contenteditable="true"
aria-multiline="true" aria-labelledby="msg-label"></div>role="textbox"<textarea>aria-multiselectabletruefalseSays more than one item can be selected at once in a listbox, grid, tablist or tree, so screen readers tell people they can pick several. Mark each chosen item with aria-selected.
<ul role="listbox" aria-multiselectable="true" aria-label="Toppings">
<li role="option" aria-selected="true">Cheese</li>
</ul>aria-selectedrole="listbox"Guides that use it
aria-modaltruefalseTells screen readers that a dialog is modal, so they treat the rest of the page as out of reach. Use it on a role="dialog" or alertdialog only when the page behind really is inert; a <dialog> opened with showModal() doesn’t need it.
<div role="dialog" aria-modal="true" aria-labelledby="dlg-title">
<h2 id="dlg-title">Delete file?</h2>
</div>aria-levelinteger (1 or more)The level of an element in a hierarchy: a role="heading" (where it is required; browsers usually treat a missing level as 2), a tree item, or a row in a treegrid. For headings, an h1–h6 element is better than role="heading" with aria-level.
<div role="heading" aria-level="2">Shipping</div>Guides that use it
aria-orientationhorizontalverticalundefinedWhether a slider, scrollbar, separator, listbox, menu, tablist, toolbar or similar runs horizontally or vertically, which tells people which arrow keys move through it. Set it when it differs from the role’s default.
<div role="tablist" aria-orientation="vertical" aria-label="Settings">
…
</div>aria-sortascendingdescendingnoneotherSays which way a table or grid is sorted by this column header. Put it on only the header currently sorted, and keep a button inside the header to change the order.
<th aria-sort="ascending">
<button type="button">Price</button>
</th>aria-valuenownumberThe current value of a custom slider, spinbutton, meter, scrollbar or progress bar; update it as the value changes. Leave it off a progress bar whose progress is unknown.
<div role="progressbar" aria-valuemin="0" aria-valuemax="100"
aria-valuenow="60" aria-label="Uploading"></div>aria-valueminnumberThe smallest value of a custom slider, spinbutton, progress bar, meter or scrollbar. Native range inputs and meters use their min attribute instead.
<div role="spinbutton" aria-valuemin="1" aria-valuemax="10"
aria-valuenow="2" aria-label="Quantity" tabindex="0">2</div>aria-valuemaxnumberThe largest value of a custom slider, spinbutton, progress bar, meter or scrollbar. A native input type="range", progress or meter uses its max attribute instead.
<div role="slider" aria-valuemin="0" aria-valuemax="100"
aria-valuenow="40" aria-label="Volume" tabindex="0"></div>aria-valuetextstringA readable form of aria-valuenow when the number alone means little, such as “Wednesday” or “3 of 8 steps”. Screen readers read it instead of the number.
<div role="slider" aria-valuemin="1" aria-valuemax="7" aria-valuenow="3"
aria-valuetext="Wednesday" aria-label="Day" tabindex="0"></div>aria-controlsID reference listPoints to the element a control changes, such as the panel of a tab or a disclosure, or the listbox of a combobox. Few screen readers do anything with it, so it doesn’t replace aria-expanded or a clear name.
<button type="button" aria-expanded="true" aria-controls="filters">
Filters
</button>
<div id="filters">…</div>aria-ownsID reference listMakes elements elsewhere in the DOM children of this one in the accessibility tree, such as a popup rendered at the end of the body. Use it only when you can’t move the elements in the DOM, and never for elements that are already its descendants.
<div role="menuitem" aria-haspopup="menu" aria-expanded="false"
aria-owns="more-menu" tabindex="-1">More</div>
<div id="more-menu" role="menu">…</div>aria-controlsaria-flowtoaria-activedescendantID referencePoints to the active option or item inside a composite widget while keyboard focus stays on the widget itself, as in a combobox whose input keeps focus while arrow keys move through suggestions. Update it on every move and draw the highlight from it.
<input role="combobox" aria-label="City" aria-expanded="true" aria-controls="list"
aria-activedescendant="opt-2">
<ul id="list" role="listbox">…</ul>aria-flowtoID reference listSuggests an alternative reading order, pointing to the element to read next. Few screen readers support it; put the content in the right order in the DOM instead.
<div id="step-1" aria-flowto="step-2">…</div>
<div id="step-2">…</div>aria-ownsaria-posinsetinteger (1 or more)An item’s position in its set, such as an option, tab, tree item or article in a feed, when not every item is in the DOM. Pair it with aria-setsize; browsers count items that are all present.
<article aria-posinset="11" aria-setsize="-1" aria-labelledby="t11">
…
</article>Guides that use it
aria-setsizeinteger (-1 if unknown)The number of items in the set an item belongs to, when not all are in the DOM, so screen readers can say “3 of 40”. Use -1 when the size is unknown, as in an endless feed.
<li role="option" aria-posinset="3" aria-setsize="40">Osaka</li>Guides that use it
aria-rowcountinteger (-1 if unknown)The total number of rows in a table, grid or treegrid when only some are in the DOM, as with paging or lazy loading. Use -1 when the total is unknown.
<table aria-rowcount="500">
<tr aria-rowindex="41">…</tr>
</table>aria-rowindexinteger (1 or more)A row’s or cell’s position, counted from 1, in a table, grid or treegrid where not every row is in the DOM. Pair it with aria-rowcount.
<div role="row" aria-rowindex="41">
<div role="gridcell">Order 41</div>
</div>aria-rowcountaria-colindexaria-rowspaninteger (0 or more)How many rows a cell spans in an ARIA table or grid built from divs. A native td or th uses its rowspan attribute instead.
<div role="rowheader" aria-rowspan="3">Morning</div>aria-colcountinteger (-1 if unknown)The total number of columns in a table or grid when only some of them are in the DOM, such as a virtualised grid. Use -1 when the total is unknown.
<div role="grid" aria-colcount="24" aria-label="Schedule">
…
</div>aria-colindexinteger (1 or more)A cell’s or row’s column position, counted from 1, in a table or grid where not every column is in the DOM. Pair it with aria-colcount.
<div role="row">
<div role="gridcell" aria-colindex="7">Room 4</div>
</div>aria-colcountaria-rowindexaria-colspaninteger (1 or more)How many columns a cell spans in an ARIA table or grid built from divs. A native td or th uses its colspan attribute instead.
<div role="cell" aria-colspan="2">Total</div>colspanaria-rowspanrole="cell"aria-liveoffpoliteassertiveMakes an element a live region whose changes screen readers announce: polite waits until they finish speaking, assertive may interrupt. The region must be in the page before its text changes; use polite or role="status" for most messages.
<div aria-live="polite"></div>
<!-- later, from script: -->
<!-- region.textContent = "Saved"; -->aria-atomicaria-relevantaria-atomictruefalseWhether a screen reader reads the whole live region when part of it changes (true) or only the changed part (false, the default). role="status" and role="alert" already set it to true, so you rarely write it: add it to a bare aria-live region whose change only makes sense with the rest, such as “3 items in your basket”.
<p aria-live="polite" aria-atomic="true">
<span id="count">3</span> items in your basket
</p>Guides that use it
aria-relevantadditionsremovalstextall (space-separated)Which changes in a live region are announced; the default is additions text. Removals are rarely useful and poorly supported, so leave the default unless items leaving matters, as in a chat roster.
<ul aria-live="polite" aria-relevant="additions removals"
aria-label="People in this chat">…</ul>aria-livearia-atomicaria-busytruefalseSays an element is being updated, so assistive technology can wait until it is set back to false before reading the changes. Set it while a live region or feed loads several changes at once.
<section aria-live="polite" aria-busy="true">
Loading results…
</section>Guides that use it
aria-currentpagesteplocationdatetimetruefalseMarks the current item in a set: the link to the page you are on, the current step of a process, today in a calendar. Use it rather than aria-selected for navigation, and show the same thing visually.
<nav aria-label="Main">
<a href="/shop" aria-current="page">Shop</a>
</nav>role="navigation"aria-keyshortcutsstring (keys joined with +, shortcuts separated by spaces)Tells assistive technology which keyboard shortcuts activate or focus an element, such as Control+S. It only describes them: your script must handle the keys, and the shortcut should be shown visually too.
<button type="button" aria-keyshortcuts="Control+S">
Save <kbd>Ctrl+S</kbd>
</button>accesskeyGuides that use it