theme | author | position | position2 | profilePicture | ||
---|---|---|---|---|---|---|
./ |
Ania Karoń |
Specjalista ds. Dostępności |
i Senior Frontend Developer |
anna-karon-photo.jpg |
Warsztaty
Repozytorium: https://github.com/SnowdogApps/a11y-space
Strona: A11y space
HTML, Tailwindcss, JS/TS
Deployment: Vercel (SSG)
- sprawdzenie kodu
- ANDI
- Czytnik ekranu - VoiceOver (macOS), Narrator lub NDVA (Windows), ChromeVox (rozszerzenie do przeglądarki)
- Dokument HTML - RWD, język, tytuł
- Landmarks:
header
,main
,footer
,section
,nav
,aside
- Semantyczne elementy HTML:
<p>
,<ul><li>...</li></ul>
,<button>
,<a href="/">
,<article>
,<address>
,<time>
etc... - Nagłówki -
<h1>
-<h6>
<!DOCTYPE html>
<html lang="en">
<head>
<title>Page title</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<header>
...
</header>
<main>
<h1>Heading</h1>
...
</main>
<aside>
...
</aside>
<footer>
...
</footer>
</body>
</html>
Przekazują prostą koncepcję lub informacje, które można wyrazić w krótkiej frazie lub zdaniu. Alternatywny tekst powinien przekazywać znaczenie lub treść wyświetlaną wizualnie, która zazwyczaj nie jest dosłownym opisem obrazu.
oznaczania informacji, uzupełnienie informacji, przekazywanie wrażeń lub emocji
<img src="informative-image" alt="alternative text" />
Są używane do inicjowania działań, a nie do przekazywania informacji, np w przyciskach i linkach.
<a href="/">
<img src="logo-image" alt="Company logo" />
</a>
<a href="/" aria-label="Homepage">
<img src="logo-image" alt="Company logo" />
</a>
Nie dodają informacji do zawartości strony.
<img src="decorative-image" alt="" aria-hidden="true" />
An alt Decision Tree on WAI Tutorials
Elementy graficzne bez widocznej etykiety powinny mieć tekst alternatywny
::left::
Dodajemy bezpośrednio do elementu
<button type="button" aria-label="Add to cart">
<svg>Add to cart icon</svg>
</button>
::right::
Podpinamy element (np. nagłówek), który opisuje sekcje używając jego id
<section type="button" aria-labelledby="section-heading">
<h2 id="section-heading">Heading section</h2>
</section>
Używamy, by dodać dodatkowy opis (np. do pola formularza lub przycisku), podpinamy element, używając jego id
<form>
<label for="fname">First name</label>
<input aria-describedby="int2" autocomplete="given-name" id="fname" type="text">
<p id="int2">Your first name is sometimes called your "given name".</p>
</form>
Warto pamiętać! Ukrywaj z rozwagą, może to wpłynąć na SEO (np,, wizualne ukrycie nagłówka)
::left::
Dla wszystkich
.element {
display: none;
visibility: hidden;
}
Dla technologii asystujących, nie wizualnie
aria-hidden="true"
<span class="aria-hidden">Decorative element</span>
::right::
Tylko wizualnie
/* Hiding class, making content visible only to screen readers but not visually */
/* "sr" meaning "screen-reader" */
.sr-only:not(:focus):not(:active) {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}
Tailwindcss - sr-only
stan focus
powinien być widoczny
- css
outline
, przeglądarki dostarczająfocus
, jeśli nie dodajecie swoich styli, nie ustawiajcieoutline: none
- kolejność elementów fokusowalnych
:focus
i:focus-visible
<style> li { font-size: 0.875rem; } </style>
::left::
Aria - role i atrybuty
- role=tablist
- role=tab
- role=tabpanel
- aria-selected
- aria-labelledby
- aria-controls
Nawigacja klawiaturą
Tab
- fokusowanie na aktywny tabLeft arrow
,Right arrow
- przeniesienie fokusu między tabamiSpace
iEnter
- aktywacja tabaHome
(opcjonalnie) - przeniesienie fokusu na pierwszy tabEnd
(opcjonalnie) - przeniesienie fokusu na ostatni tab
::right::
<div>
<h2 id="heading">Heading</h2>
<div role="tablist" aria-labelledby="heading">
<button id="tab-1" type="button" role="tab" aria-selected="true" aria-controls="tabpanel-1">
<span>Tab 1</span>
</button>
<button id="tab-2" type="button" role="tab" aria-selected="false" aria-controls="tabpanel-2" tabindex="-1">
<span>Tab 1</span>
</button>
</div>
<div id="tabpanel-1" role="tabpanel" aria-labelledby="tab-1">
<p>
Content tab 1
</p>
</div>
<div id="tabpanel-2" role="tabpanel" aria-labelledby="tab-3" aria-hidden="true">
<p>
Content tab 2
</p>
</div>
</div>
<style> li { font-size: 0.875rem; } </style>
::left::
Aria - role i atrybuty
- role=dialog
- aria-modal
- aria-labelledby
- aria-hidden
Nawigacja klawiaturą
Tab
- fokusowanie następnego elementu fokusowalnego wewnątrz modalaShift + Tab
- fokusowanie poprzdniego elementu fokusowalnego wewnątrz modalaEscape
- zamknięcie modala i powrót fokusu na trigger
::right::
<div
role="dialog"
aria-modal="true"
aria-hidden="true"
class="dialog"
aria-labelledby="heading"
>
<div class="dialog-content" autofocus tabindex="0">
<h2 id="heading">Heading</h2>
dialog content
<button type="button">Close</button>
</div>
</div>
aria-live
- wskazuje AT dynamicznie zmieniające się na stronie (ustawiamy na kontenerze)- wartość
polite
- informuje o zmianie, kiedy akończone zostanie aktualne zadanie - wartość
assertive
- informuje o zmianie natychmiast aria-atomic
- informuje, jak elementy w "obserwowanym" regionie (oznaczonym atrybutemaria-live
) mają zostać przedstawione - tylko zmiany:false
, czy wszystkie elementy:true
layout: thankyou