Six ways websites lock people out, each one live and broken on this page —
then fixed, in the same breath, with the markup that did it.
Read the transcript
Intro
[record scratch] Yeah… Check the DOM. Check the tree. You can't tab through that.
Chorus
You can't click this. [record scratch] You can't click this. You you you you you you you. You can't click this. Yah. Sema, sema, se-man You can't click this. Stop! Semantic time!
Verse
My, my, my, my markup hits so bad, Makes the screen reader user straight-up mad. Thank you for blessing me With a clickable div that I just can't see! No role, no focus state, Hit the Tab key once, now I gotta wait. Buttons look real, but they have no tags, Accessibility backlog drags.
Chorus
Can't tab this. Look, man, you can't click this. No aria-label, can't click this. Stop! Semantic time!
Outro
Just use a button. CantClickThis.dev. Stop! Semantic time!
Greg Miller, Shrinkray InteractiveTrack: “Can't Click This” by toledogeeks
01 of 06
The clickable div
It looks like a button. It is styled like a button. The mouse agrees. Nothing else does.
Tab through the example. The fake title is skipped — it is a paragraph. Then the outline jumps 4, 6, 3. A screen reader headings list (VoiceOver rotor, NVDA Insert+F7) shows the same gaps.
✕ What breaks it
(flagged, see note 1) <pclass="hero">DevFest 2026</p> (flagged, see note 2) <h4>Schedule</h4> (flagged, see note 3) <h6>Venue</h6><h3>Get tickets</h3>
Looks like the page title. The headings list never sees it — it is a paragraph.
h4 because it looked medium-small. Nothing sits above it, so the outline skips two levels.
h6 as a size token. Almost every home page that uses one also skips levels — this is type size, not a sixth level of structure.
✓ What fixes it
(flagged, see note 1) <h2>DevFest 2026</h2> (flagged, see note 2) <h3>Schedule</h3><h3>Venue</h3><h3>Get tickets</h3>
A real heading. Screen reader users jump here first, the way sighted users look at the big type.
Siblings share a level. Do not pick h4 or h6 because they look smaller — that is CSS, not structure.
Headings are the map, not the type scale. If it looks like a heading, it has to be a heading, at the next level down — never the one that happens to look the right size.
Tab through this row in both states. Same tab order, same elements — only one of them tells you anything.
✕ What breaks it
a,button { (flagged, see note 2) outline: none;}
Nothing replaces it, so keyboard focus becomes invisible across the entire page.
This is usually copied in to hide the ring on mouse click — :focus-visible already does that for you.
✓ What fixes it
(flagged, see note 1) a:focus-visible,button:focus-visible {outline: 3px solid #ffffff;outline-offset: 2px; (flagged, see note 2) box-shadow: 0 0 0 6px #0e1420;}
:focus-visible fires for keyboard focus and stays quiet for mouse clicks — the behaviour people actually wanted.
A second ring in the opposite tone keeps the indicator visible on light and dark backgrounds alike.
Never remove a focus outline without replacing it with something at least as visible. If you cannot see where you are, neither can the person using only a keyboard.
05 of 06
Click here, click here, click here
Screen reader users pull up a list of every link on the page to navigate it. Out of context, most link text collapses into noise.
Open the links list in VoiceOver or NVDA. Out of context, these three links all say nothing useful.
✕ What breaks it
<p>Registration closes Friday. (flagged, see note 1) <ahref="/register">Click here</a> to sign up.</p><p>The schedule is posted. (flagged, see note 2) <ahref="/schedule">Read more</a>.</p>
"Click here" describes the mouse, not the destination — and the destination is the only useful part.
Three links reading "read more" are indistinguishable in a links list, in search results, and on a phone.
✓ What fixes it
<p>Registration closes Friday. (flagged, see note 1) <ahref="/register">Register for DevFest</a>.</p> (flagged, see note 2) <p><ahref="/schedule">View the full schedule</a> for all three tracks.</p>
The link says where it goes, so it survives being read on its own.
Front-loading the verb also makes the sentence shorter. Accessible copy is usually just better copy.
Link text has to make sense with the sentence around it removed. Read the links on their own — if you cannot tell them apart, neither can anyone else.
Registration for DevFest closes Friday. Click here to sign up.
Click or Tab into a field. The placeholder vanishes, and nothing is left to say what the field is for. A screen reader announces "edit text" with no name.
✕ What breaks it
(flagged, see note 1) <inputtype="text"placeholder="Full name"> (flagged, see note 2) <inputtype="text"placeholder="[email protected]">
Placeholder is the only instruction, and it disappears the moment you click or Tab in — which is when you need it.
Nothing is associated with the field, so a screen reader announces "edit text" with no name.
✓ What fixes it
(flagged, see note 1) <labelfor="email">Email</label><inputtype="email"id="email"name="email" (flagged, see note 2) autocomplete="email" (flagged, see note 3) aria-describedby="email-hint" required><pid="email-hint">We send one confirmation and nothing else.</p>
for and id pair them up, so the label is announced with the field and clicking the label focuses it.
autocomplete lets the browser fill it in — a genuine accessibility win under 1.3.5, not just convenience.
required is announced as a state, and aria-describedby attaches the hint without crowding the label.
Every input needs a real label a screen reader can announce. Placeholder text is a hint, not a label, and it disappears the moment it is needed.
Screen reader buffer
Approximate announcement for the focused element. Teaching aid, not a screen reader.