Skip to content
easeweb

Learn

Easily confused HTML and ARIA

Attributes and roles that look alike but behave differently, side by side, and which to use.

Hiding content

NameOn screenKeyboard can reach itScreen readers read it
hiddenNoNoNo
inertYesNoNo
aria-hidden="true"YesYes, if it is focusable: never do thisNo

hiddenNot on screen, not reachable by keyboard, not read

Payment Linen tea towel, 12.00

inertOn screen, but not reachable by keyboard and not read

Free delivery

aria-hidden="true"The icon is on screen; screen readers skip it and read the words beside it

Which to use

hidden
Content nobody should see yet, such as a closed panel.
inert
The page behind a modal you built yourself, or content shown but not usable yet.
aria-hidden="true"
Decoration that repeats nearby text, such as an icon beside its label. Never on anything focusable.

Removing meaning

NameRemovesContent still read
role="none"The element’s roleYes
role="presentation"The element’s roleYes
aria-hidden="true"The element and everything in itNo
alt=""The imageNothing to read
Linen tea towel12.00

role="none"No table, row or cell any more; its text is still read

role="presentation"The same as role="none", under its older name

4.5 out of 5

aria-hidden="true"The stars and everything in them are not read; the words are

alt=""The image is decoration: nothing to read

Which to use

role="none"
A table used only for layout, or markup whose role gets in the way.
role="presentation"
The same as role="none", under its older name.
aria-hidden="true"
Decoration that repeats nearby text.
alt=""
A decorative image.

Unavailable and unchangeable fields

NameFocusableValue can changeSubmitted with the form
disabledNoNoNo
aria-disabled="true"YesUnless your script stops itYes, for a native field
readonlyYesNoYes

Coupons open on 1 November.

disabledCan’t be focused or changed, and isn’t submitted

aria-disabled="true"Can be focused, so it is still found; our script stops it

readonlyCan be focused and copied, not changed; it is submitted

Which to use

disabled
A control that really can’t be used now, with the reason shown nearby.
aria-disabled="true"
A control people should still find and hear, such as a Submit button that explains what is missing.
readonly
A value people may read and copy but not change, such as a reference number.

Guides that decide between these

Names and descriptions

NameGivesText comes fromVisible
<label>NameIts own textYes
aria-labelledbyNameOther elements, by idUsually
aria-labelNameThe attributeNo
aria-describedbyDescriptionOther elements, by idUsually
titleName only when nothing else doesThe attributeOnly on mouse hover

<label>Name: “Email”, from its own text

Delivery address

aria-labelledbyName: “Delivery address”, from the heading, by id

aria-label="Search"Name: “Search”, not on screen

At least 8 characters

aria-describedbyDescription: “At least 8 characters”, read after the name

title="Shop location"Name: “Shop location”, as nothing else names the iframe

Which to use

<label>
Every visible form field.
aria-labelledby
A widget or region whose name is already on screen, such as a dialog’s heading.
aria-label
A control with no visible text, such as an icon button. Include any visible words in it.
aria-describedby
Hints and error messages, read after the name.
title
Naming an <iframe>. Elsewhere, don’t rely on it.

Announcing changes

NamePolitenessRead on a change
role="status"Polite: waitsThe whole message: aria-atomic="true" is built in
role="alert"Assertive: may interruptThe whole message: aria-atomic="true" is built in
aria-live="polite"Polite: waitsOnly what changed, unless you add aria-atomic="true"
aria-live="assertive"Assertive: may interruptOnly what changed, unless you add aria-atomic="true"
role="log"Polite: waitsNew entries
role="timer"OffNothing

role="status"Polite: waits. Reads the whole message

role="alert"Assertive: may interrupt. Reads the whole message

3 left in stock

aria-live="polite"Polite: waits. Changes when you add one to the bag

aria-live="assertive"Assertive: may interrupt. Reads only the new items, and it stays a list

  1. No questions yet

role="log"New entries, added at the end, are read

Offer ends in 4:59

role="timer"Off: not read on every tick

Which to use

role="status"
Results, “Saved”, loading messages: anything that can wait.
role="alert"
Errors and warnings people must act on now. Use it sparingly.
aria-live="polite"
A message that can wait, where only the part that changed should be read or the element must keep its own role.
aria-live="assertive"
The same, for something urgent, such as a list of errors that must stay a list. Otherwise use role="alert".
role="log"
Chat messages and activity feeds, with new entries added at the end.
role="timer"
A running clock or countdown, which must not be read on every tick.

Pressed, expanded, checked, selected, current

NameGoes onTells people
aria-pressedA buttonA toggle is on or off
aria-expandedThe button that shows and hides contentWhat it controls is open or closed
aria-checkedCheckbox, radio, switchIt is checked, or on
aria-selectedTab, option, row, cellIt is the chosen one in its set
aria-currentAny elementIt is where you are now

aria-current="page"On “Kitchen”

Linen tea towel

aria-pressed="false"

50 by 70 cm, in natural linen.

aria-selected="true"On “Details”

aria-expanded="false"

aria-checked="true"

Which to use

aria-pressed
A button that turns something on and off, such as Mute or Bold.
aria-expanded
Disclosures, accordions and menu buttons.
aria-checked
Checkboxes, radios and switches you build yourself; native inputs need none.
aria-selected
The chosen tab, or the chosen options in a listbox or grid.
aria-current
The current page in a nav, or the current step in a process.

Dialogs and popovers

NameModalFocus moves inEscape closes itWhat you build
<dialog> with showModal()YesYesYesLittle: a name and a close button
role="dialog"Only if you make it soOnly if you move itOnly if you script itAll of it
role="alertdialog"Only if you make it soOnly if you move itOnly if you script itAll of it, unless on <dialog>
popoverNoNoYes, for popover="auto"Little

Delivery address 12 Mill Lane, Leeds

Edit address

<dialog>Closed. Opened with showModal().

role="dialog"Closed. Only where <dialog> can’t be used.

Delete this address?

12 Mill Lane, Leeds

role="alertdialog"Closed. On a <dialog>, for a question that needs an answer.

Tea towels are 50 by 70 cm.

popover="auto"Closed. Focus stays where it was when it opens.

Which to use

<dialog> with showModal()
Any modal dialog.
role="dialog"
Only where <dialog> can’t be used.
role="alertdialog"
An urgent question that needs an answer, such as confirming a deletion.
popover
Non-modal menus, pickers and tips that sit over the page.

Choosing from options

NameFree text allowedWhat you build
<select>NoNothing
<datalist>YesNothing, but it can’t be styled
role="listbox"NoKeys, focus and states
role="combobox"If it is editableKeys, the popup and states

<select>Free text: no. You build nothing. Now “M”

<datalist>Free text: yes; the list only suggests. It can’t be styled.

Pattern
Plain
Stripe
Check

role="listbox"Free text: no. This script adds the keys, focus and states. Now “Plain”

role="combobox"Editable, so free text is allowed. This script adds the keys, the popup and states.

Which to use

<select>
One or more choices from a fixed list.
<datalist>
Suggestions for a field that accepts anything.
role="listbox"
A list of options styled in ways <select> can’t be.
role="combobox"
Autocomplete and searchable pickers.

Required fields

NameBrowser blocks submissionAnnounced as required
requiredYesYes
aria-required="true"NoYes

requiredThe browser stops the form until it is filled in; announced as required

Delivery speed

aria-required="true"Announced as required, but the browser sends the form anyway; our script checks it

Which to use

required
Native fields.
aria-required="true"
Fields you build yourself, such as a custom radio group, with your own validation.

Guides that decide between these

Sections and landmarks

NameLandmark
<main>Yes
<aside>Yes, at page level
<section>Only with a name
<article>No

main

Linen tea towel

50 by 70 cm, in natural linen.

<main>A landmark, once per page. Drawn here with a div, as this page has its own

<aside>A landmark when it is at page level

section

Reviews

4.5 out of 5, from 12 reviews.

<section>A landmark, because aria-labelledby gives it a name: “Reviews”

article

Linen apron

Cotton straps, one size.

<article>Not a landmark: complete on its own

Which to use

<main>
The page’s main content, once.
<aside>
Related but separate content, such as a sidebar.
<section>
A part of the page on one theme, with a heading.
<article>
Something complete on its own: a post, a comment, a product card.

Progress or meter

NameShowsWithout a value
<progress>How far a task has gotSomething is happening
<meter>A measurement in a known rangeNot allowed

Photo of your tea towel

<progress>A task: 0 of 100. Starts when you upload.

Strength: Very weak

<meter>A measurement from 0 to 4: now 0. It must have a value.

Which to use

<progress>
Uploads and other long tasks.
<meter>
Disk use, password strength, ratings.

Every name links to its entry in the HTML and ARIA reference, with an example and the guides that use it.