Kurs HTML i CSS · Moduł 10: Dostępność (a11y)
Dostępne obrazy i multimedia
W tej lekcji7
Na stronie muzeum wisi zdjęcie złotej maski Tutanchamona. Osoba widząca ogląda je przez sekundę, a czytnik ekranowy odczyta nazwę pliku "IMG_0042.jpg" - albo nic. Obraz bez opisu jest dla niewidomego pielgrzyma pustą ścianą. W Starożytnym Egipcie każda rzeźba, malowidło i relief na ścianie świątyni miały swój opis - często wyryty obok w formie hieroglifów. Dziś musimy robić to samo dla treści wizualnych w internecie, aby osoby niewidome i słabowidzące mogły zrozumieć, co przedstawiają nasze obrazy i multimedia.
Tekst alternatywny (alt)
Atrybut alt to najważniejszy element dostępności obrazów. Czytnik ekranowy odczyta go zamiast pokazywać obraz, przeglądarka wyświetli go, gdy plik się nie załaduje, a wyszukiwarki używają go, by zrozumieć, co przedstawia grafika.
Zasady pisania alt
Zanim cokolwiek napiszesz, zdecyduj: czy ten obraz niesie informację, czy jest tylko dekoracją? Dobry alt informacyjnego obrazu odpowiada na pytanie, co ważnego obraz przekazuje w tym miejscu strony:
1<!-- 1. Opisuj CO jest na obrazku, nie JAK wygląda plik -->
2<!-- ŹLE -->
3<img src="IMG_0042.jpg" alt="IMG_0042.jpg">
4<img src="piramida.jpg" alt="piramida">
5
6<!-- DOBRZE -->
7<img src="piramida.jpg"
8 alt="Wielka Piramida w Gizie na tle zachodzącego słońca">
9
10<!-- 2. Bądź zwięzły - 1-2 zdania -->
11<!-- ŹLE - za długi -->
12<img src="mask.jpg"
13 alt="Na zdjęciu widzimy złotą maskę pośmiertną młodego
14 faraona Tutanchamona, która została odkryta przez Howarda
15 Cartera w 1922 roku w Dolinie Królów i waży około 11 kg
16 czystego złota z inkrustacjami z lapis lazuli i turkusu">
17
18<!-- DOBRZE -->
19<img src="mask.jpg"
20 alt="Złota maska pośmiertna faraona Tutanchamona z inkrustacjami z lapis lazuli">Nazwa pliku i jedno słowo "piramida" nic nie mówią, a esej o historii maski męczy słuchacza, bo czytnik odczytuje alt jednym ciągiem. Nie zaczynaj też od "Zdjęcie przedstawia" - czytnik sam zapowie, że to grafika.
Kiedy alt powinien być pusty?
Obrazy dekoracyjne, które nie niosą treści informacyjnej, powinny mieć pusty atrybut alt. Zobacz trzy typowe sytuacje:
1<!-- Dekoracyjna linia oddzielająca -->
2<img src="border-pattern.png" alt="">
3
4<!-- Ikona obok tekstu, który ją opisuje -->
5<button>
6 <img src="search-icon.png" alt="">
7 Szukaj
8</button>
9<!-- Tekst "Szukaj" już opisuje funkcję, ikona jest dekoracyjna -->
10
11<!-- Tło dekoracyjne - lepiej używać CSS -->
12<div style="background-image: url('papyrus-bg.jpg')">
13 <p>Treść artykułu...</p>
14</div>Pusty alt="" to sygnał "pomiń mnie". To co innego niż brak atrybutu: bez alt wiele czytników odczyta nazwę pliku. Tło z CSS czytnik pomija w ogóle, więc to dobre miejsce na dekoracje. Gdy przycisk zawiera wyłącznie ikonę, jej alt staje się nazwą przycisku i musi opisywać akcję (alt="Szukaj"), a nie wygląd (alt="lupa"). Najprościej jednak dodać widoczny tekst, jak w przykładzie - i to polecam.
Element figure i figcaption
Gdy obraz potrzebuje widocznego podpisu - daty, autora albo kontekstu - otocz go elementem <figure> i dodaj <figcaption>:
1<figure>
2 <img src="rosetta-stone.jpg"
3 alt="Kamień z Rosetty z trzema rodzajami pisma: hieroglifami, pismem demotycznym i greckim">
4 <figcaption>
5 Kamień z Rosetty (196 p.n.e.) - klucz do odczytania hieroglifów,
6 odkryty w 1799 roku przez żołnierzy Napoleona
7 </figcaption>
8</figure><figcaption> to podpis widoczny dla wszystkich użytkowników, a alt to opis przeznaczony specjalnie dla tych, którzy obrazu nie widzą. Nie powtarzaj w nich tego samego: alt mówi, co widać na kamieniu, a podpis dodaje historię. Kolejność pracy jest więc stała: decyzja, alt, a na końcu opcjonalnie <figure> z podpisem.
Dostępne wideo
Napisy (Captions)
Film bez napisów wyklucza osoby niesłyszące, ale też każdego, kto ogląda go w tramwaju bez słuchawek. Napisy dodajesz elementem <track> wewnątrz <video>:
1<video controls>
2 <source src="exhibition-tour.mp4" type="video/mp4">
3
4 <!-- Napisy dla osób niesłyszących -->
5 <track kind="captions" src="captions-pl.vtt"
6 srclang="pl" label="Polski" default>
7
8 <!-- Napisy w innym języku -->
9 <track kind="subtitles" src="subtitles-en.vtt"
10 srclang="en" label="English">
11
12 Twoja przeglądarka nie wspiera elementu video.
13</video>Atrybut kind określa rodzaj ścieżki, srclang jej język, a label nazwę w menu odtwarzacza. default włącza ścieżkę automatycznie i może go mieć tylko jeden <track>. Tekst przed </video> zobaczą jedynie przeglądarki bez obsługi wideo.
Różnica między captions a subtitles:
- Captions - napisy dla osób niesłyszących, zawierają też opisy dźwięków:
[muzyka w tle],[dźwięk kroków] - Subtitles - tłumaczenie dialogów na inny język
Format WebVTT
Same napisy zapisujesz w zwykłym pliku tekstowym w formacie WebVTT, z rozszerzeniem .vtt. Taki plik wygląda następująco:
1WEBVTT
2
300:00:01.000 --> 00:00:04.000
4Witamy w Muzeum Starożytnego Egiptu.
5
600:00:04.500 --> 00:00:08.000
7Rozpoczynamy naszą podróż od Sali Głównej.
8
900:00:08.500 --> 00:00:12.000
10[dźwięki kroków na marmurowej podłodze]Plik zaczyna się od słowa WEBVTT, a każdy fragment to czas początku i końca (godziny:minuty:sekundy.milisekundy) oraz tekst. Opis dźwięku w nawiasach kwadratowych to właśnie to, co odróżnia captions od zwykłego tłumaczenia.
Dostępne audio
Nagranie audio nie ma obrazu, na którym dałoby się wyświetlić napisy, dlatego osobom niesłyszącym dajesz transkrypcję, czyli pełny zapis tekstu:
1<figure>
2 <figcaption>
3 <h3>Audiobook: Historia Kleopatry</h3>
4 </figcaption>
5 <audio controls>
6 <source src="cleopatra.mp3" type="audio/mpeg">
7 Twoja przeglądarka nie wspiera elementu audio.
8 </audio>
9 <!-- Transkrypcja dla osób niesłyszących -->
10 <details>
11 <summary>Transkrypcja nagrania</summary>
12 <p>Kleopatra VII Filopator, ostatnia władczyni
13 dynastii Ptolemeuszy...</p>
14 </details>
15</figure>Element <details> chowa długą transkrypcję pod przyciskiem <summary>, więc nie zaśmieca strony, a działa z klawiatury bez jednej linijki JavaScriptu.
SVG dostępny
Grafika SVG to kod, a nie plik z atrybutem alt, dlatego opis dodajesz inaczej - zależnie od tego, czy grafika niesie informację:
1<!-- SVG jako obraz informacyjny -->
2<svg role="img" aria-labelledby="chart-title chart-desc">
3 <title id="chart-title">Liczba odwiedzających muzeum</title>
4 <desc id="chart-desc">
5 Wykres słupkowy pokazujący wzrost odwiedzających
6 z 50 000 w 2020 do 120 000 w 2024.
7 </desc>
8 <!-- elementy SVG -->
9</svg>
10
11<!-- SVG dekoracyjny -->
12<svg aria-hidden="true" focusable="false">
13 <!-- dekoracyjna grafika -->
14</svg>role="img" każe traktować SVG jak jeden obraz, a aria-labelledby składa jego opis z <title> i <desc>. aria-hidden="true" ukrywa dekorację tylko przed czytnikiem - na ekranie nadal ją widać. focusable="false" chroni przed starym Internet Explorerem, który potrafił ustawić focus na SVG.
Prefers-reduced-motion
Niektórzy użytkownicy są wrażliwi na animacje - mogą one powodować zawroty głowy lub nudności. Media query prefers-reduced-motion sprawdza, czy ktoś włączył w systemie ograniczenie ruchu:
1/* Domyślna animacja */
2.slide-in {
3 animation: slideIn 0.5s ease-in-out;
4}
5
6/* Wyłączenie animacji dla użytkowników, którzy tego wolą */
7@media (prefers-reduced-motion: reduce) {
8 .slide-in {
9 animation: none;
10 }
11
12 * {
13 transition-duration: 0.01ms !important;
14 animation-duration: 0.01ms !important;
15 }
16}Animacja zostaje dla tych, którzy jej chcą, i znika tylko u osób, które o to poprosiły. Czas 0.01ms zamiast zera sprawia, że elementy od razu trafiają do stanu końcowego, a skrypty czekające na koniec animacji dalej działają.
Dostępne multimedia to jak napisy przy egipskich reliefach - pozwalają każdemu zrozumieć przekaz, niezależnie od tego, czy "widzi" oryginał, czy korzysta z opisu. W następnej lekcji zajmiemy się kolorem i kontrastem.
Praktyka
W edytorze poniżej znajdziesz obrazy, wideo i SVG. Sprawdź, które z nich są informacyjne, a które dekoracyjne, i czy mają właściwy opis:
Kod do tej lekcji: index.html
1<!DOCTYPE html>
2<html lang="pl">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>Dostepne obrazy i multimedia</title>
7 <link rel="stylesheet" href="style.css">
8</head>
9<body>
10 <h1>Dostepne obrazy i multimedia</h1>
11
12 <!-- Obraz informacyjny z alt -->
13 <section>
14 <h2>Obraz informacyjny</h2>
15 <figure>
16 <img src="https://placehold.co/500x300/d4af37/1a1a2e?text=Kamien+z+Rosetty"
17 alt="Kamien z Rosetty z trzema rodzajami pisma: hieroglifami, demotycznym i greckim">
18 <figcaption>
19 Kamien z Rosetty (196 p.n.e.) - klucz do odczytania hieroglifow
20 </figcaption>
21 </figure>
22 </section>
23
24 <!-- Obraz dekoracyjny -->
25 <section>
26 <h2>Obraz dekoracyjny</h2>
27 <img src="https://placehold.co/600x4/d4af37/d4af37" alt="">
28 <p>Powyzszy ornament jest dekoracyjny - ma pusty alt=""</p>
29 </section>
30
31 <!-- SVG dostepny -->
32 <section>
33 <h2>Dostepny SVG</h2>
34 <svg role="img" aria-labelledby="svg-title svg-desc"
35 width="200" height="200" viewBox="0 0 200 200">
36 <title id="svg-title">Statystyki odwiedzin</title>
37 <desc id="svg-desc">Wykres slupkowy: 2022: 50tys, 2023: 80tys, 2024: 120tys</desc>
38 <rect x="20" y="120" width="40" height="60" fill="#d4af37"/>
39 <rect x="80" y="80" width="40" height="100" fill="#8b6914"/>
40 <rect x="140" y="20" width="40" height="160" fill="#3d2914"/>
41 <text x="30" y="195" font-size="12" fill="#1a1a2e">2022</text>
42 <text x="90" y="195" font-size="12" fill="#1a1a2e">2023</text>
43 <text x="150" y="195" font-size="12" fill="#1a1a2e">2024</text>
44 </svg>
45 </section>
46
47 <!-- Video z napisami -->
48 <section>
49 <h2>Wideo z napisami</h2>
50 <video controls width="500" poster="https://placehold.co/500x300/1a1a2e/d4af37?text=Wideo+Muzeum">
51 <track kind="captions" srclang="pl" label="Polski" default>
52 Twoja przegladarka nie wspiera elementu video.
53 </video>
54 <p><em>Przyklad elementu video z elementem track dla napisow.</em></p>
55 </section>
56
57 <!-- Audio z transkrypcja -->
58 <section>
59 <h2>Audio z transkrypcja</h2>
60 <figure>
61 <figcaption><strong>Audiobook: Historia Kleopatry</strong></figcaption>
62 <audio controls>
63 Twoja przegladarka nie wspiera elementu audio.
64 </audio>
65 </figure>
66 <details>
67 <summary>Transkrypcja nagrania</summary>
68 <p>Kleopatra VII Filopator, ostatnia wladczyni dynastii
69 Ptolemeuszow, panowala w Egipcie od 51 do 30 roku p.n.e.
70 Znana z inteligencji i charyzmy, mowila w wielu jezykach...</p>
71 </details>
72 </section>
73</body>
74</html>Pamiętaj: alt, napisy i transkrypcja to hieroglify wyryte obok reliefu - opowiadają tę samą historię tym, którzy nie mogą jej zobaczyć ani usłyszeć.
Widzisz błąd w tej lekcji?
Sprawdź się
Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.
1. Kiedy obraz powinien mieć pusty atrybut alt=""?
2. Kiedy należy używać atrybutu aria-hidden="true"?
To 2 z 3 pytań do tej lekcji. Pozostałe rozwiążesz w grze.
Zadania praktyczne w grze
- Układanie w pionie
Ułóż etapy dodawania dostępnego obrazu od początku:
- Edytor kodu
Dodaj alt do informacyjnego obrazu z figcaption, alt="" do dekoracyjnego, tekst do przycisku-ikony, i role="img" z title/desc do SVG.
- Edytor kodu
Dodaj video z napisami (track), audio z transkrypcją w details, i CSS @media (prefers-reduced-motion: reduce) wyłączające animacje.
- Układanie w poziomie
Ułóż poprawny element track do napisów w wideo: