Bad code
<body>
<header>…</header>
<main>…</main>
<footer>…</footer>
<div class="cookie_consent modal">
<p>We use cookies…</p>
<div class="cookie_consent__close">
<i class="fa fa-times"></i>
</div>
<div class="cookie_consent__ok">OK</div>
</div>
</body>
Issues and how to fix them
- The modal is not the first item on the page and focus is not on the modal when the page loads. Keyboard users have to tab through all items on the page to access the cookie consent window.
- A
div
isn’t keyboard focusable. - Content inside these
div
s is semantically just text. Assistive technology doesn’t know that these fake buttons are actually buttons. - A click event on a
div
triggers only on click. A click event on abutton
triggers on click and if the user presses the Enter or Space key. - There’s no text alternative for the icon.
- Font Awesome advises to hide icons semantically by settings
aria-hidden="true"
on the<i>
element. - Font Awesome adds Unicode content via the
::before
pseudo element. Assistive technology may announce the Unicode equivalent, which in this specific example would be “times” since fa-times is not a cross but a multiplication sign. (Please note: Talkback and VoiceOver didn’t announce anything in this example.) - Bonus: it should be possible to close modals by pressing Esc.
Good code
<body>
<div class="cookie_consent modal">
<h2 class="sr-only">Cookie notice</h2>
<p>We use cookies…</p>
<button class="cookie_consent__ok">OK</button>
<button class="cookie_consent__close">
<span class="sr-only">Close notification</span>
<i class="fa fa-times" aria-hidden="true"></i>
</button>
</div>
<header>…</header>
<main>…</main>
<footer>…</footer>
</body>
Unfortunately, there’s no native way of hiding content only visually.
The .sr-only
class makes sure that content is visually hidden but still accessible to screen reader users.
.sr-only {
position: absolute;
white-space: nowrap;
width: 1px;
height: 1px;
overflow: hidden;
border: 0;
padding: 0;
clip: rect(0 0 0 0);
clip-path: inset(50%);
margin: -1px;
}