Witaj w Świątyni Uniwersalnej Wiedzy! Podobnie jak starożytni Egipcjanie budowali piramidy z szerokich, dostępnych schodów dla wszystkich, którzy chcieli wejść do wnętrza, tak i my musimy budować strony internetowe dostępne dla wszystkich użytkowników - w tym osób z niepełnosprawnościami. Poznaj ARIA i semantyczne HTML - klucze do tworzenia inkluzywnego internetu!
Accessibility (w skrócie a11y - "a" + 11 liter + "y") to zapewnienie, że strony internetowe mogą być używane przez wszystkich, niezależnie od ich możliwości fizycznych lub technicznych.
Kto korzysta z dostępnych stron:
Analogia egipska: Jak hieroglify były zrozumiałe dla kapłanów, pisarzy i zwykłych ludzi na różnych poziomach, tak strona powinna być dostępna dla wszystkich użytkowników.
1<!-- ❌ ZŁE - divs bez znaczenia -->
2<div class="header">
3 <div class="nav">
4 <div class="nav-item">Home</div>
5 <div class="nav-item">About</div>
6 </div>
7</div>
8
9<div class="main-content">
10 <div class="article">
11 <div class="article-title">Tytuł artykułu</div>
12 <div class="article-text">Treść artykułu...</div>
13 </div>
14</div>
15
16<!-- ✅ DOBRE - semantyczne znaczniki -->
17<header>
18 <nav>
19 <a href="/">Home</a>
20 <a href="/about">About</a>
21 </nav>
22</header>
23
24<main>
25 <article>
26 <h1>Tytuł artykułu</h1>
27 <p>Treść artykułu...</p>
28 </article>
29</main>Dlaczego semantyczne znaczniki są lepsze:
1<!-- Struktura strony -->
2<header>Logo i nawigacja główna</header>
3<nav>Menu nawigacyjne</nav>
4<main>Główna treść strony (tylko jeden na stronie!)</main>
5<article>Samodzielna jednostka treści (post bloga, artykuł)</article>
6<section>Tematyczna sekcja dokumentu</section>
7<aside>Treść poboczna, powiązana z główną treścią</aside>
8<footer>Stopka sekcji lub strony</footer>
9
10<!-- Zawartość tekstowa -->
11<h1>, <h2>, <h3>, <h4>, <h5>, <h6>Nagłówki w hierarchii</h1>
12<p>Paragraf tekstu</p>
13<blockquote>Cytat</blockquote>
14<figure>Ilustracja z opisem</figure>
15<figcaption>Podpis do ilustracji</figcaption>
16
17<!-- Interaktywne elementy -->
18<button>Przycisk (do akcji)</button>
19<a href="#">Link (do nawigacji)</a>
20<form>Formularz</form>
21<input>, <select>, <textarea>Pola formularza</input>ARIA to zestaw atrybutów, które rozszerzają semantykę HTML i pomagają technologiom asystującym (czytniki ekranu) zrozumieć interfejs.
Złota zasada ARIA:
"Nie używaj ARIA, jeśli możesz użyć semantycznego HTML!"
Role mówią czytnikowi ekranu, czym jest dany element:
1<!-- Kiedy semantyczny HTML NIE wystarcza -->
2
3<!-- ❌ Bez role - nie jest jasne, co to jest -->
4<div class="navigation">
5 <a href="/">Home</a>
6 <a href="/products">Products</a>
7</div>
8
9<!-- ✅ Z role="navigation" -->
10<div role="navigation">
11 <a href="/">Home</a>
12 <a href="/products">Products</a>
13</div>
14
15<!-- ✅ NAJLEPSZE - semantyczny tag (nie potrzeba role!) -->
16<nav>
17 <a href="/">Home</a>
18 <a href="/products">Products</a>
19</nav>Najpopularniejsze ARIA roles:
1<!-- Nawigacja -->
2<div role="navigation">Menu</div>
3<!-- Lepiej: <nav> -->
4
5<!-- Główna treść -->
6<div role="main">Główna zawartość</div>
7<!-- Lepiej: <main> -->
8
9<!-- Przycisk -->
10<div role="button" tabindex="0">Kliknij</div>
11<!-- Lepiej: <button> -->
12
13<!-- Alert -->
14<div role="alert">Błąd! Wypełnij wszystkie pola.</div>
15
16<!-- Baner (header strony) -->
17<div role="banner">Logo i nawigacja</div>
18<!-- Lepiej: <header> -->
19
20<!-- Informacje dodatkowe -->
21<div role="complementary">Sidebar</div>
22<!-- Lepiej: <aside> -->
23
24<!-- Treść artykułu -->
25<div role="article">Post na blogu</div>
26<!-- Lepiej: <article> -->
27
28<!-- Wyszukiwarka -->
29<div role="search">
30 <form>
31 <input type="search" aria-label="Szukaj w serwisie">
32 <button>Szukaj</button>
33 </form>
34</div>
35
36<!-- Tab panel -->
37<div role="tabpanel" aria-labelledby="tab1">
38 Zawartość zakładki 1
39</div>UWAGA: Jeśli używasz role na divie, musisz też zadbać o:
tabindex)aria-label dodaje tekstowy opis elementu, który jest czytany przez czytniki ekranu:1<!-- Ikona bez tekstu -->
2<button aria-label="Zamknij okno">
3 <svg><!-- Ikona X --></svg>
4</button>
5
6<!-- Link do social media -->
7<a href="https://facebook.com" aria-label="Odwiedź nas na Facebooku">
8 <img src="fb-icon.svg" alt="">
9</a>
10
11<!-- Wyszukiwarka -->
12<input
13 type="search"
14 aria-label="Wyszukaj produkty w sklepie"
15 placeholder="Szukaj...">
16
17<!-- Przycisk hamburger menu -->
18<button
19 class="hamburger"
20 aria-label="Otwórz menu nawigacyjne"
21 aria-expanded="false">
22 <span></span>
23 <span></span>
24 <span></span>
25</button>
26
27<!-- Nawigacja stronnicowania -->
28<nav aria-label="Nawigacja między stronami">
29 <a href="?page=1">1</a>
30 <a href="?page=2" aria-current="page">2</a>
31 <a href="?page=3">3</a>
32</nav>Kiedy używać aria-label:
Kiedy NIE używać aria-label:
<label> w formularzualtaria-labelledby łączy element z innym elementem, który służy jako etykieta:1<!-- Modal dialog -->
2<div role="dialog" aria-labelledby="dialog-title" aria-describedby="dialog-desc">
3 <h2 id="dialog-title">Potwierdź usunięcie</h2>
4 <p id="dialog-desc">Czy na pewno chcesz usunąć ten element? Tej operacji nie można cofnąć.</p>
5 <button>Usuń</button>
6 <button>Anuluj</button>
7</div>
8
9<!-- Tabs -->
10<div role="tablist">
11 <button role="tab" id="tab1" aria-controls="panel1">Opis</button>
12 <button role="tab" id="tab2" aria-controls="panel2">Specyfikacja</button>
13</div>
14
15<div role="tabpanel" id="panel1" aria-labelledby="tab1">
16 Szczegółowy opis produktu...
17</div>
18
19<div role="tabpanel" id="panel2" aria-labelledby="tab2">
20 Specyfikacja techniczna...
21</div>
22
23<!-- Sekcja z nagłówkiem -->
24<section aria-labelledby="section-heading">
25 <h2 id="section-heading">Najnowsze artykuły</h2>
26 <article>...</article>
27 <article>...</article>
28</section>aria-describedby dodaje rozszerzony opis elementu:1<!-- Pole formularza z pomocą -->
2<label for="password">Hasło</label>
3<input
4 type="password"
5 id="password"
6 aria-describedby="password-requirements">
7<p id="password-requirements">
8 Hasło musi zawierać minimum 8 znaków, w tym wielką literę i cyfrę.
9</p>
10
11<!-- Przycisk z dodatkowym kontekstem -->
12<button aria-describedby="delete-warning">
13 Usuń konto
14</button>
15<p id="delete-warning">
16 Ta akcja jest nieodwracalna i usunie wszystkie Twoje dane.
17</p>
18
19<!-- Tooltip -->
20<button aria-describedby="tooltip1">
21 Zapisz
22</button>
23<span id="tooltip1" role="tooltip" hidden>
24 Zapisz zmiany w dokumencie (Ctrl+S)
25</span>Atrybut
alt to jeden z najważniejszych elementów dostępności. Opisuje obrazek dla osób, które go nie widzą.1<!-- ✅ DOBRE - opisowy alt -->
2<img
3 src="pyramids-giza.jpg"
4 alt="Trzy piramidy w Gizie o zachodzie słońca, z wielbłądami na pierwszym planie">
5
6<!-- ✅ DOBRE - funkcjonalny alt dla linku -->
7<a href="/products">
8 <img src="shop-icon.svg" alt="Przejdź do sklepu">
9</a>
10
11<!-- ✅ DOBRE - pusty alt dla obrazków dekoracyjnych -->
12<img src="decorative-line.svg" alt="">
13
14<!-- ❌ ZŁE - alt identyczny jak nazwa pliku -->
15<img src="img_001.jpg" alt="img_001">
16
17<!-- ❌ ZŁE - niepotrzebne "zdjęcie", "obrazek" -->
18<img src="cat.jpg" alt="Zdjęcie przedstawiające kota">
19<!-- Lepiej: alt="Kot śpiący na kanapie" -->
20
21<!-- ❌ ZŁE - brak alt -->
22<img src="important-chart.jpg">
23<!-- Czytnik ekranu przeczyta nazwę pliku! -->Zasady pisania dobrych alt:
alt=""aria-describedby lub <figcaption>1<!-- Obrazek dekoracyjny (CSS background byłby lepszy) -->
2<img src="divider.svg" alt="">
3
4<!-- Obrazek z tekstem -->
5<img src="sale-banner.jpg" alt="Wyprzedaż 50% - tylko dziś!">
6
7<!-- Złożony wykres -->
8<figure>
9 <img
10 src="sales-chart.jpg"
11 alt="Wykres sprzedaży 2024"
12 aria-describedby="chart-description">
13 <figcaption id="chart-description">
14 Wykres pokazuje wzrost sprzedaży z 10 000 w styczniu do 50 000 w grudniu 2024.
15 Największy skok nastąpił w listopadzie podczas Black Friday.
16 </figcaption>
17</figure>1<div class="button" onclick="submitForm()">
2 <img src="send-icon.svg">
3</div>
4
5<style>
6.button {
7 background: blue;
8 padding: 10px;
9 cursor: pointer;
10}
11</style>Problemy:
1<button
2 type="submit"
3 aria-label="Wyślij formularz">
4 <img src="send-icon.svg" alt="">
5</button>
6
7<style>
8button {
9 background: blue;
10 padding: 10px;
11 cursor: pointer;
12 border: none;
13 color: white;
14}
15
16button:focus {
17 outline: 3px solid orange;
18 outline-offset: 2px;
19}
20</style>Zalety:
<button> - automatyczna obsługa klawiaturyaria-label opisuje funkcjętype="submit" - jasna funkcjaKrok po kroku:
Lighthouse sprawdzi:
Wynik: Raport z oceną 0-100 i konkretnymi problemami do naprawienia.
Test ręczny:
Windows: NVDA (darmowy) Mac: VoiceOver (wbudowany - Cmd+F5) Chrome: ChromeVox (rozszerzenie)
Podstawowe komendy (NVDA):
Rozszerzenie do Chrome/Firefox, które automatycznie wykrywa problemy z dostępnością:
Online narzędzie: https://wave.webaim.org/
HTML i semantyka:
<header>, <nav>, <main>, <article>)<main>Obrazki:
altalt=""Formularze:
<label> lub aria-labelrequired lub aria-required="true")Nawigacja klawiaturą:
Kolory i kontrast:
ARIA:
role są poprawnie użytearia-liverole="dialog" i aria-labelledbyTesty:
Semantyczne HTML:
<button>, <nav>, <main>, <article> zamiast divówARIA roles:
role="navigation", role="main", role="button"ARIA labels:
aria-label - dodaje tekstowy opisaria-labelledby - łączy z istniejącym elementemaria-describedby - dodaje rozszerzony opisAlt w obrazkach:
alt="" dla dekoracjiTestowanie:
Pamiętaj: Dostępność to nie dodatkowa funkcja - to fundamentalna część tworzenia stron internetowych. Podobnie jak piramidy w Gizie były budowane dla wszystkich pokoleń, tak strony internetowe powinny być dostępne dla wszystkich użytkowników!