1. Zanim zaczniesz

Ułatwienia dostępu są kluczowym elementem programowania stron internetowych, ponieważ zapewniają użytkownikom możliwość postrzegania, rozumienia, poruszania się po aplikacjach i wchodzenia z nimi w interakcje. W Stanach Zjednoczonych 1 na 4 dorosłe osoby ma niepełnosprawność, która wpływa na ich główne czynności życiowe. Na całym świecie około 15% populacji, czyli ponad miliard osób, ma jakąś formę niepełnosprawności, a około 2–4% z nich doświadcza poważnych trudności.
Do najczęstszych problemów, które utrudniają korzystanie z internetu, należą ślepota lub słabe widzenie, głuchota lub niedosłuch, ograniczone zdolności motoryczne, niepełnosprawność intelektualna i daltonizm. To tylko częściowa lista.
W tym szkoleniu skrót a11y oznacza ułatwienia dostępu. Zwróć uwagę, że po literze a występuje 11 znaków i litera y.
Szczegółowe wprowadzenie do problemów i technik projektowania aplikacji z ułatwieniami dostępu znajdziesz w sekcji Ułatwienia dostępu.
Co utworzysz
- Stosowanie sprawdzonych metod i wbudowanych technik w celu rozwiązania typowych problemów z dostępnością w przykładowej aplikacji Dumpling Shop Angular
- Spełniać wszystkie wytyczne dotyczące dostępności, WCAG 2.0 i ARIA 1.2 oraz przechodzić audyty dostępności przeprowadzane przez narzędzia axe i Lighthouse.

Czego się nauczysz
Dowiesz się o 8 częstych problemach z ułatwieniami dostępu w aplikacjach Angular, które mają wpływ na użytkowników, jak je identyfikować i jak je rozwiązywać. W szczególności:
- Sprawdzanie ułatwień dostępu w aplikacji za pomocą Narzędzi deweloperskich w Chrome, Lighthouse i axe
- Unikaj problemów z aplikacjami jednostronicowymi (SPA) dzięki unikalnym tytułom stron
- Rozwiązywanie problemów z niskim kontrastem kolorów dla użytkowników niedowidzących
- Używaj semantycznego kodu HTML, aby czytniki ekranu prawidłowo poruszały się po stronie
- Używaj Angular Material i wyodrębniaj elementy sterujące, aby czytniki ekranu miały dostęp do wszystkich elementów sterujących.
- Dodawanie obsługi ARIA dla czytników ekranu
- Importowanie i używanie pakietu Angular CDK a11y
- Używanie FocusTrap do nawigacji czytnika ekranu w komponencie niestandardowym
- Odczytywanie powiadomień za pomocą komponentu CDK LiveAnnouncer
- Wykrywanie użytkowników korzystających z trybu wysokiego kontrastu i wdrażanie motywów o wysokim kontraście
Czego potrzebujesz
- Znajomość Angulara, SCSS, TypeScriptu, Gita i Narzędzi deweloperskich w Chrome.
2. Konfiguracja
Pobierz kod
Wszystko, czego potrzebujesz do tego projektu, znajduje się w repozytorium GitHub. Aby rozpocząć, sklonuj kod i otwórz go w ulubionym środowisku programistycznym.
Sklonuj repozytorium i udostępnij aplikację
VSCode lub lokalne IDE to zalecana metoda pracy z tym przewodnikiem.
- Otwórz nową kartę przeglądarki i wejdź na stronę https://github.com/googlecodelabs/angular-accessibility.
- Utwórz rozwidlenie i sklonuj repozytorium, a następnie
cd angular-accessibility/do repozytorium. - Sprawdź gałąź kodu startowego
git checkout get-started. - Otwórz kod w VSCode lub w ulubionym IDE.
- Uruchom
npm install, aby zainstalować zależności wymagane do uruchomienia serwera. - Aby uruchomić serwer, wpisz
ng serve. - Otwórz kartę przeglądarki z adresem http://localhost:4200.
3. Ustalenie wartości odniesienia
Jaki jest Twój punkt początkowy?
Punktem wyjścia jest podstawowa aplikacja restauracyjna zaprojektowana na potrzeby tego ćwiczenia. Kod został uproszczony, aby przedstawić koncepcje w tym laboratorium, i ma niewielką funkcjonalność.

Zobacz wersję demonstracyjną
Aby rozpocząć, zapoznaj się z 3 funkcjami aplikacji:
- Użyj paska nawigacyjnego, aby wyświetlić trasy Nasz sklep, Nasza historia i Znajdź nas oraz zobaczyć szczegóły dotyczące firmy produkującej pierogi.
- Zmień motywy, aby przełączać tryb jasny i ciemny.
- Dostosuj nadzienie, liczbę i kolor pierożków w zamówieniu.
- Aby zarejestrować w konsoli dostosowane zamówienie, kliknij Kup.
Rozwiązywanie typowych problemów z dostępnością stron internetowych za pomocą Angulara
W tym laboratorium skupisz się na ułatwieniach dostępu w istniejących funkcjach tej aplikacji. Zaczniesz od zidentyfikowania problemów z ułatwieniami dostępu w aplikacji, a następnie zamienisz 🛑 na ✅, wdrażając rozwiązanie.
Skąd wiesz, co należy naprawić?
Każdy przykład rozpocznij od rozpoznania problemu z ułatwieniami dostępu za pomocą testów ręcznych i automatycznych.
W obecnym stanie internetu ręczne testowanie ułatwień dostępu jest obowiązkowe.
Masz narzędzia, które mogą wykrywać problemy z ułatwieniami dostępu, ale żadne z nich nie może potwierdzić, że aplikacja jest w pełni dostępna. Testy ręczne zapewniają sprawdzenie szerokiego zakresu koncepcji dotyczących ułatwień dostępu, w tym logicznej kolejności treści i równoważności funkcji.
Testy ręczne
Aby ręcznie przetestować ułatwienia dostępu w tym kursie, włącz wbudowany czytnik ekranu na komputerze i poruszaj się po aplikacji za pomocą klawiatury. Więcej informacji znajdziesz w artykule Semantyka i czytniki ekranu.
Poćwicz, włączając czytnik ekranu i poruszając się po ekranie.
Możesz używać wbudowanego czytnika ekranu VoiceOver w systemie macOS. Kliknij Preferencje systemowe > Ułatwienia dostępu > VoiceOver > Włącz VoiceOver. Aby włączyć lub wyłączyć VoiceOver, szybko naciśnij 3 razy czytnik Touch ID, przytrzymując klawisz Command.
W tym kursie będziesz głównie testować problemy ręcznie i używać zautomatyzowanych narzędzi do sprawdzania określonych funkcji, które można zautomatyzować.
Testy automatyczne
Możesz też używać kilku narzędzi deweloperskich do automatyzacji i sprawdzania aplikacji. Umożliwiają one m.in. sprawdzenie, czy obraz ma tekst alternatywny, lub współczynnika kontrastu koloru tekstu. Można je traktować jako lintery. Potrafią one rozpoznać, że tekst alternatywny jest obecny, ale musisz ręcznie sprawdzić, czy jego treść jest logiczna i wartościowa.
Lighthouse i Narzędzia deweloperskie w Chrome
- Otwórz Narzędzia deweloperskie w Chrome.
- Kliknij kartę Lighthouse i zaznacz pole wyboru Ułatwienia dostępu.
- Aby przeprowadzić audyt Lighthouse dotyczący ułatwień dostępu, kliknij Wygeneruj raport.

Axe
- Zainstaluj rozszerzenie axe DevTools. Aby zobaczyć rozszerzenie, konieczne może być ponowne uruchomienie przeglądarki.
- Otwórz Narzędzia deweloperskie w Chrome.
- Wybierz kartę axe DevTools i kliknij Scan all of my page (Skanuj całą stronę), aby uruchomić skanowanie za pomocą narzędzia axe DevTools.
Lintowanie
Możesz używać reguł Angular ESLint do sprawdzania kodu pod kątem atrybutów ułatwień dostępu, które można zautomatyzować.
W pliku eslint.json dodaj te elementy, które dotyczą ułatwień dostępu:
"@angular-eslint/template/accessibility-alt-text": 2,
"@angular-eslint/template/accessibility-elements-content": 2,
"@angular-eslint/template/accessibility-label-for": 2,
"@angular-eslint/template/no-positive-tabindex": 2,
"@angular-eslint/template/accessibility-table-scope": 2,
"@angular-eslint/template/accessibility-valid-aria": 2,
"@angular-eslint/template/click-events-have-key-events": 2,
"@angular-eslint/template/mouse-events-have-key-events": 2,
"@angular-eslint/template/no-autofocus": 2,
"@angular-eslint/template/no-distracting-elements": 2
Więcej informacji znajdziesz w najnowszych regułach ESLint na GitHub.
Twój punkt początkowy
Korzystając z nowych metod testowania, możesz zidentyfikować w aplikacji te problemy za pomocą audytów Lighthouse i axe oraz ręcznego testowania za pomocą VoiceOver:

Kontrola ułatwień dostępu:
- 🛑 Wszystkie strony mają ten sam tytuł
- 🛑 Elementy muszą mieć wystarczający kontrast kolorów
- 🛑 HTML powinien mieć logiczną kolejność, nazwę i rolę
- 🛑 Zagnieżdżone pola wyboru nie są dostępne dla czytników ekranu
- 🛑 Czytnik ekranu nie odczytuje wartości suwaka
- 🛑 Czytnik ekranu wychodzi z okna wyboru koloru
- 🛑 Zmiany, błędy i powiadomienia nie są ogłaszane
- 🛑 Tryb wysokiego kontrastu nie jest włączony
4. Określanie unikalnych tytułów stron
Unikalne, zwięzłe tytuły stron pomagają użytkownikom korzystającym z usług ułatwień dostępu szybko zrozumieć treść i przeznaczenie strony internetowej. Tytuły stron są bardzo ważne dla użytkowników z wadami wzroku, ponieważ są pierwszym elementem strony odczytywanym przez oprogramowanie do czytania ekranu.
Angular to aplikacja jednostronicowa, więc większość przejść, np. na nową stronę, nie wymaga ponownego wczytania strony. Do niedawna oznaczało to, że każda strona miała identyczny tytuł, który nie dostarczał żadnych informacji o jej treści ani celu.
W Angularze w wersji 14 Router dodał wbudowaną metodę definiowania unikalnych tytułów stron. Upraszcza to proces zapewniania, że deweloperzy stosują sprawdzone metody dotyczące tytułów stron.
Po zakończeniu tej sekcji Twoja aplikacja przejdzie następujący audyt:
- 🛑 Wszystkie strony mają ten sam tytuł
Każdy z tych kroków znajdziesz pod komentarzem: TODO: #4. Define unique page titles.
Określenie problemu
Aby zidentyfikować ten problem, włącz czytnik ekranu i przejdź między kartami Nasz sklep, Nasza historia i Znajdź nas, aby zobaczyć tytuły stron:
- Włącz VoiceOver.
- Do przechodzenia między stronami używaj nawigacji za pomocą kart.
- Sprawdź, czy tytuł strony jest zawsze dostępny w Angularze.
Jest to problem, ponieważ tytuł strony musi być niepowtarzalny, aby użytkownik mógł szybko zrozumieć, o czym jest strona, bez konieczności jej przeglądania.

Dodawanie zrozumiałych tytułów stron
Jeśli strona lub widok ulegnie zmianie, musisz odpowiednio zarządzać tytułem strony. Aby to naprawić, użyj wbudowanej właściwości Router.title Angulara, aby zdefiniować unikalne tytuły każdej ze stron.
- Dodaj unikalny tytuł do każdej z 3 zdefiniowanych tras:
src/app/app-routing.module.ts
const routes: Routes = [
{ path: 'shop', component: ShopComponent, title: 'Our Shop – a11y in Angular' },
{ path: 'about', component: AboutComponent, title: 'Our Story - a11y in Angular' },
{ path: 'locate', component: LocationComponent, title: 'Find Us - a11y in Angular' },
{ path: '', redirectTo: '/shop', pathMatch: 'full' },
{ path: '**', component: ShopComponent },
];
Spowoduje to automatyczne zaimportowanie i użycie funkcji Router's Title Service, która zarządza zmianą tytułu strony podczas nawigacji, aby pasował do właściwości tytułu zdefiniowanej w naszych trasach. Możesz też zarządzać bardziej skomplikowanymi tytułami stron za pomocą niestandardowego TitleStrategy.
Weryfikowanie zmian
Ponownie włącz czytnik ekranu i sprawdź zmiany. Strony powinny teraz mieć unikalne tytuły.

Kontrola ułatwień dostępu:
- ✅ Wszystkie strony mają unikalne tytuły.
- 🛑 Elementy muszą mieć wystarczający kontrast kolorów
- 🛑 HTML powinien mieć logiczną kolejność, nazwę i rolę
- 🛑 Zagnieżdżone pola wyboru nie są dostępne dla czytników ekranu
- 🛑 Czytnik ekranu nie odczytuje wartości suwaka
- 🛑 Czytnik ekranu wychodzi z okna wyboru koloru
- 🛑 Zmiany, błędy i powiadomienia nie są ogłaszane
- 🛑 Tryb wysokiego kontrastu nie jest włączony
5. Zapewnij odpowiedni kontrast kolorów
Projekt może wydawać się atrakcyjny, ale nie jest, jeśli osoby z wadami wzroku, takimi jak ślepota barw, nie mogą odczytać Twoich treści. Wytyczne dotyczące dostępności treści internetowych (WCAG 2.0) określają szereg współczynników kontrastu kolorów, które zapewniają dostępność treści. W Angularze i internecie możesz zdefiniować palety kolorów, które zapewnią, że komponenty spełniają te standardy i są widoczne dla użytkowników niedowidzących i z daltonizmem.
Po zakończeniu tej sekcji Twoja aplikacja przejdzie następujący audyt:
- 🛑 Elementy muszą mieć wystarczający kontrast kolorów
Każdy z tych kroków znajdziesz w komentarzach: TODO: #5. Ensure adequate color contrast.
Identyfikowanie problemów z niskim kontrastem za pomocą Narzędzi deweloperskich w Chrome
Aby zidentyfikować ten problem, użyj Narzędzi deweloperskich w Chrome do sprawdzenia elementów w aplikacji.
- Użyj narzędzia do sprawdzania, aby wyświetlić przyciski ikon menu. Widzisz, że kontrast wynosi 1,85, czyli znacznie poniżej wymagań WCAG.

- Aby sprawdzić, czy występują problemy z kontrastem, uruchom audyt ułatwień dostępu w Lighthouse lub skanowanie za pomocą narzędzia axe.

Zmienianie koloru motywu Material
Schemat kolorów komponentu jest zdefiniowany w niestandardowym motywie Material. Zaktualizuj wartość motywu, aby była zgodna ze wskazówkami dotyczącymi współczynnika kontrastu kolorów.
Zaktualizuj motyw Material, aby używać ciemniejszego koloru tekstu, co zwiększy współczynnik kontrastu ikon:
src/styles.scss
$light-primary: mat.define-palette(mat.$pink-palette, $default: A100, $lighter: 100, $text: 900);
Możesz też użyć wbudowanych narzędzi ułatwień dostępu w Narzędziach deweloperskich w Chrome, aby znaleźć kolor spełniający standardy, lub zaktualizować poszczególne wartości kolorów w Sass.
Weryfikowanie zmian
Ponownie sprawdź elementy i zweryfikuj zmiany. Motyw powinien teraz mieć wystarczający kontrast kolorów.

Kontrola ułatwień dostępu
- ✅ Wszystkie strony mają unikalne tytuły.
- ✅ Kolory mają wystarczający współczynnik kontrastu
- 🛑 HTML powinien mieć logiczną kolejność, nazwę i rolę
- 🛑 Zagnieżdżone pola wyboru nie są dostępne dla czytników ekranu
- 🛑 Czytnik ekranu nie odczytuje wartości suwaka
- 🛑 Czytnik ekranu wychodzi z okna wyboru koloru
- 🛑 Zmiany, błędy i powiadomienia nie są ogłaszane
- 🛑 Tryb wysokiego kontrastu nie jest włączony
6. Używanie semantycznego kodu HTML
Natywne elementy HTML obejmują wiele standardowych wzorców interakcji, które są ważne z punktu widzenia ułatwień dostępu. Chociaż akapit można ostylować jako element span, a element div jako przycisk, semantyczny element HTML zapewnia, że czytniki ekranu i nawigacja za pomocą klawiatury rozumieją interakcje i elementy sterujące w kodzie HTML.
Podczas tworzenia komponentów Angulara w miarę możliwości używaj bezpośrednio tych elementów natywnych, zamiast ponownie implementować dobrze obsługiwane zachowania. Dzięki temu strona ma dobrą strukturę treści i naturalny przepływ treści, a karty są ułożone w logicznej kolejności, co ułatwia użytkownikom poruszanie się po witrynie za pomocą klawiatury.
Po zakończeniu tej sekcji Twoja aplikacja przejdzie następujący audyt:
- 🛑 HTML powinien mieć logiczną kolejność, nazwę i rolę
Każdy z tych kroków znajdziesz w komentarzach: TODO: #6. Use Semantic HTML.
Określenie problemu
- Włącz VoiceOver.
- Za pomocą klawisza Tab przejdź do karty Nasza historia.
- Zwróć uwagę, że kolejność kart nie jest sekwencyjna.
- Kliknij Purchas.
- Zauważ, że przycisk nie jest rozpoznawany jako przycisk.

Zmiana elementu <div> na <button>
Zastąp niestandardowy element <div> przyciskiem Material:
src/app/shop/shop.component.html
<button mat-flat-button
color="primary"
class="purchase-button"
(click)="fauxPurchase()">
Purchase
</button>
Używaj elementów nagłówka w odpowiedniej kolejności
Zmień kolejność tekstu, aby używać semantycznych znaczników HTML, i zastosuj style za pomocą typografii Angular Material:
src/app/about/about.component.html
<h2>Who are we?</h2>
<p class="mat-subheading-2">Have you ever thought, "wow, I love dumplings"?</p>
<p class="right mat-subheading-1">Who hasn't.</p>
<p class="center mat-subheading-1">We took it one step further and created Dumpling Dumpling,</p>
<p class="center mat-subheading-1">double the dumpling, double the fun.</p>
<div class="spacer"></div>
<h2>How are we different?</h2>
<p class="mat-subheading-2">Handmade in San Francisco, California, we craft fully customizable dumplings. Glitter? Rainbows? Vegan? We do it all.</p>
<p class="right mat-subheading-2">This shop is concept only.</p>
Weryfikowanie zmian
Ponownie włącz czytnik ekranu i sprawdź zmiany. VoiceOver rozpoznaje teraz przycisk, a tekst jest odczytywany w logicznej kolejności.
Kontrola ułatwień dostępu:
- ✅ Wszystkie strony mają unikalne tytuły.
- ✅ Kolory mają wystarczający współczynnik kontrastu
- ✅ Semantyczny kod HTML zapewnia logiczną interakcję
- 🛑 Zagnieżdżone pola wyboru nie są dostępne dla czytników ekranu
- 🛑 Czytnik ekranu nie odczytuje wartości suwaka
- 🛑 Czytnik ekranu wychodzi z okna wyboru koloru
- 🛑 Zmiany, błędy i powiadomienia nie są ogłaszane
- 🛑 Tryb wysokiego kontrastu nie jest włączony
7. Tworzenie elementów sterujących z możliwością wyboru za pomocą Angular Material
Jednym ze skomplikowanych wzorców interakcji w przypadku usług ułatwień dostępu są zagnieżdżone elementy sterujące. Pomyśl o elementach podrzędnych menu lub zagnieżdżonych polach wyboru. Jak poinformować użytkownika, że może wybrać podgrupę opcji lub przejść do elementu menu nadrzędnego?
W Angularze uprość menu i elementy sterujące, aby tworzyć komponenty, po których można się poruszać. W tym przykładzie użyjesz pola listy Angular Material, aby utworzyć jeden z przykładów tego wzorca interakcji.
Po zakończeniu tej sekcji Twoja aplikacja przejdzie następujący audyt:
- 🛑 Zagnieżdżone pola wyboru nie są dostępne dla czytników ekranu
Każdy z tych kroków znajdziesz w komentarzach: TODO: #7. Create selectable controls with Angular Material.
Określenie problemu
Aby zidentyfikować ten problem, włączymy czytnik ekranu i spróbujemy zaznaczyć zagnieżdżone pole wyboru.
- Włącz VoiceOver.
- Wybierz różne smaki nadzienia.
- Zwróć uwagę, że gdy VoiceOver odczytuje pola wyboru rodzica, nie podaje informacji o dzieciach. Skąd wiesz, że pole wyboru Vegan jest teraz odznaczone, skoro odznaczono pole wyboru Bok Choy?

Ułatwienia dostępu w Angular Material
Zastąp pole wyboru semantyczne polem wyboru Angular Material, które zawiera wbudowaną wiedzę o tym wzorcu interakcji. Pamiętaj, że zastąpienie komponentów komponentami Material nie gwarantuje dostępności. Podobnie jak w przypadku innych komponentów, musisz przeprowadzić test ręczny, ponieważ istnieje wiele sposobów na nieprawidłowe wdrożenie Material.
Zastępowanie pól wyboru polami wyboru Material Design
- Najpierw dodaj nową listę nadzień i zmienną do przechowywania wybranych smaków nadzienia:
src/app/shop/shop.component.ts
@Component(...)
export class ShopComponent implements OnInit {
fillings: string[] = ['Bok Choy & Chili Crunch', 'Tofu & Mushroom', 'Chicken & Ginger', 'Impossible Meat & Spinach'];
selectedFillings: string[] = [];
fauxPurchase(): void {
let flavor = '';
this.selectedFillings.forEach(filling => {
flavor = flavor + " " + filling
})
}
}
- Dodaj element
<mat-selection-list>, aby zastąpić tę nieuporządkowaną grupę pól wyboru HTML:
src/app/shop/shop.component.html
<mat-selection-list [(ngModel)]="selectedFillings"
aria-label="Dumpling fillings">
<mat-list-option *ngFor="let flavor of fillings"
[value]="flavor"
color="primary">
{{ flavor }}
</mat-list-option>
</mat-selection-list>
Twoje TODO komentarze wskazują też, gdzie możesz usunąć nieużywane elementy Sass w src/app/shop/shop.component.scss, aby uporządkować style.
Weryfikowanie zmian
Ponownie włącz czytnik ekranu i sprawdź zmiany. Pola wyboru można teraz zaznaczać i intuicyjnie poruszać się po nich za pomocą czytnika ekranu.

Kontrola ułatwień dostępu:
- ✅ Wszystkie strony mają unikalne tytuły.
- ✅ Kolory mają wystarczający współczynnik kontrastu
- ✅ Semantyczny kod HTML zapewnia logiczną interakcję
- ✅ Wszystkie elementy sterujące są dostępne dla czytników ekranu.
- 🛑 Czytnik ekranu nie odczytuje wartości suwaka
- 🛑 Czytnik ekranu wychodzi z okna wyboru koloru
- 🛑 Zmiany, błędy i powiadomienia nie są ogłaszane
- 🛑 Tryb wysokiego kontrastu nie jest włączony
8. Etykiety elementów sterujących z ARIA
Zmodyfikowano semantyczny kod HTML i komponenty Material w aplikacji Angular, ale niektóre komponenty wymagają określonych atrybutów, aby czytniki ekranu mogły w pełni po nich nawigować.
Specyfikacja Accessible Rich Internet Applications (ARIA) inicjatywy Web Accessibility Initiative (WAI-ARIA lub ARIA) pomaga rozwiązywać problemy, których nie można rozwiązać za pomocą natywnego kodu HTML. Umożliwia określanie atrybutów, które modyfikują sposób tłumaczenia elementu na drzewo ułatwień dostępu.
Po zakończeniu tej sekcji Twoja aplikacja przejdzie następujący audyt:
- 🛑 Czytnik ekranu nie odczytuje wartości suwaka
Każdy z tych kroków znajdziesz w komentarzach: TODO: #8. Provide control labels with ARIA.
Określenie problemu
Aby zidentyfikować ten problem, włącz czytnik ekranu i przesuń suwak:
- Włącz VoiceOver.
- Przejdź do suwaka ilości i zmień wartość.
- Zwróć uwagę, że brakuje etykiety wartości.

Używanie atrybutów ARIA
Sterowanie etykietą za pomocą zakresu od aria-label do <mat-slider>:
src/app/shop/shop.component.html
<mat-slider
aria-label="Dumpling order quantity slider"
id="quantity"
name="quantity"
color="primary"
class="quantity-slider"
[max]="13"
[min]="1"
[step]="1"
[tickInterval]="1"
thumbLabel
[(ngModel)]="quantity">
</mat-slider>
Weryfikowanie zmian
Ponownie włącz czytnik ekranu i sprawdź zmiany. Możesz teraz przesunąć suwak.

Kontrola ułatwień dostępu:
- ✅ Wszystkie strony mają unikalne tytuły.
- ✅ Kolory mają wystarczający współczynnik kontrastu
- ✅ Semantyczny kod HTML zapewnia logiczną interakcję
- ✅ Wszystkie elementy sterujące są dostępne dla czytników ekranu.
- ✅ Suwak używa atrybutów ARIA do podawania etykiety
- 🛑 Czytnik ekranu wychodzi z okna wyboru koloru
- 🛑 Zmiany, błędy i powiadomienia nie są ogłaszane
- 🛑 Tryb wysokiego kontrastu nie jest włączony
9. Dodaj moc @angular/cdk/a11y
Do tej pory do rozwiązywania typowych problemów z dostępnością używałeś(-aś) wbudowanych narzędzi Angulara. Teraz przyjrzyjmy się modułowi a11y CDK i sposobom, w jakie może on pomóc w rozwiązywaniu bardziej skomplikowanych problemów związanych z Angular.
Po zakończeniu tej sekcji będziesz kontynuować szkolenie z użyciem narzędzi modułu ułatwień dostępu Angular.
Te czynności znajdziesz w komentarzu: TODO: #9. Add the power of @angular/cdk/a11y.
Importowanie modułu
Dodaj moduł do aplikacji:
src/app/app.module.ts
import { A11yModule } from '@angular/cdk/a11y';
@NgModule({
declarations: [...],
imports: [
A11yModule
],
providers: [...],
bootstrap: [...]
})
Co robi '@angular/cdk/a11y' ?
Moduł a11y udostępnia wiele narzędzi do poprawy dostępności i jest szczególnie przydatny dla autorów komponentów.
W kolejnych sekcjach dodasz 3 popularne usługi: FocusTrap, LiveAnnouncer i HighContrast.
Więcej informacji o innych usługach świadczonych przez @angular/cdk/a11y znajdziesz w sekcji Ułatwienia dostępu.
10. Kontrolowanie ostrości za pomocą FocusTrap
Gdy okno lub modal jest otwarty, użytkownik może wchodzić w interakcję tylko z jego zawartością. Pozwolenie na przeniesienie fokusu poza okno dialogowe powoduje pomieszanie kontekstów i utworzenie stanu, w którym użytkownik nie wie, w którym miejscu strony się znajduje.
W Angularze dyrektywa cdkTrapFocus przechwytuje tab-fokus klawiatury w elemencie. To ustawienie jest przeznaczone do tworzenia środowisk dostępnych dla komponentów takich jak okna modalne, w których fokus musi być ograniczony.
Po zakończeniu tej sekcji Twoja aplikacja przejdzie następujący audyt:
- 🛑 Czytnik ekranu wychodzi z okna wyboru koloru
Te czynności znajdziesz w komentarzach: TODO: #10. Control focus with FocusTrap.
Określenie problemu
Aby zidentyfikować ten problem, włącz czytnik ekranu i otwórz okno wyboru koloru.
- Włącz VoiceOver.
- Aby zmienić kolor, użyj nawigacji za pomocą klawisza Tab.
- Sprawdź intuicyjną kolejność zaznaczania i blokowanie zaznaczania w selektorze kolorów.

Dodawanie elementu FocusTrap
cdkFocusTrap można używać do przechwytywania i kontrolowania kolejności zaznaczania w komponentach niestandardowych. Użycie mat-dialog-content wystarczy, aby rozwiązać większość problemów, ponieważ fokus zostanie przeniesiony do okna. Dodaj atrybut cdkFocusInitial, aby zdefiniować początkowy region ostrości na kolorze ciasta na pierogi <mat-selection-list> w oknie selektora kolorów.
src/app/shop/color-picker/color-picker-dialog/color-picker-dialog.component.html
<mat-selection-list #colors aria-label="Dumpling wrapper color" multiple="false" cdkFocusInitial>
...
</mat-selection-list>
Weryfikowanie zmian
Ponownie włącz czytnik ekranu i sprawdź zmiany. Początkowo fokus jest ustawiony na opcję Zmień kolor w oknie.
Kontrola ułatwień dostępu:
- ✅ Wszystkie strony mają unikalne tytuły.
- ✅ Kolory mają wystarczający współczynnik kontrastu
- ✅ Semantyczny kod HTML zapewnia logiczną interakcję
- ✅ Wszystkie elementy sterujące są dostępne dla czytników ekranu.
- ✅ Suwak używa atrybutów ARIA do podawania etykiety
- ✅ Selektor kolorów ma prawidłowe przechwytywanie fokusu
- 🛑 Zmiany, błędy i powiadomienia nie są ogłaszane
- 🛑 Tryb wysokiego kontrastu nie jest włączony
11. Ogłaszanie zmian za pomocą funkcji LiveAnnouncer
Czytniki ekranu muszą być powiadamiane o zmianach na stronie. Wyobraź sobie, że próbujesz przesłać formularz lub dokonać zakupu, ale nie wiesz, że pojawił się błąd, który uniemożliwia przesłanie formularza. To frustrujące.
LiveAnnouncer służy do odczytywania wiadomości użytkownikom czytników ekranu za pomocą regionu aria-live, aby czytniki ekranu były powiadamiane o powiadomieniach i zmianach na stronie na żywo. Więcej informacji o regionach aria-live znajdziesz w WAI-ARIA od W3C. W Angularze wywoływanie LiveAnnouncer jako usługi jest łatwiejszym do przetestowania rozwiązaniem niż atrybuty aria-live.
Po zakończeniu tej sekcji Twoja aplikacja przejdzie następujący audyt:
- 🛑 Zmiany, błędy i powiadomienia nie są ogłaszane
Te czynności znajdziesz w komentarzach: TODO: #11. Announce changes with LiveAnnouncer.
Określenie problemu
Aby zidentyfikować ten problem, włącz czytnik ekranu i kliknij Kup bez wypełniania pól formularza:
- Włącz VoiceOver.
- Użyj nawigacji za pomocą klawisza Tab, aby zmienić kolor i dokonać fałszywego zakupu.
- Zwróć uwagę, że po zamknięciu okna dialogowego nie ma informacji o wybranym kolorze, a zakup nie jest odczytywany.

Dodaj do kodu element LiveAnnouncer
Dodaj LiveAnnouncer i ogłoś zarówno wybór koloru, jak i fałszywy zakup jako ciąg znaków. W rzeczywistym wdrożeniu może to być odczytywane podczas przechodzenia do systemu płatności innej firmy lub w przypadku błędów w formularzu.
- Dodaj komunikat, gdy zostanie wybrany kolor:
src/app/shop/color-picker/color-picker-dialog/color-picker-dialog.component.ts
import { LiveAnnouncer } from '@angular/cdk/a11y';
@Component(...)
export class ColorPickerDialogComponent implements OnInit {
constructor(
public dialogRef: MatDialogRef<ColorPickerDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: ColorDialogData,
private liveAnnouncer: LiveAnnouncer) { }
public changeColor(color: string): void {
this.liveAnnouncer.announce(`Select color: ${color}`);
this.dialogRef.close();
}
}
- Dodaj ogłoszenie, gdy zostanie dokonany fałszywy zakup:
src/app/shop/shop.component.ts
import { LiveAnnouncer } from '@angular/cdk/a11y';
@Component(...)
export class ShopComponent implements OnInit {
constructor(private liveAnnouncer: LiveAnnouncer) { }
fauxPurchase(): void {
let flavor = '...';
const fakePurchase = `Purchase ${this.quantity} ${flavor}dumplings in the color ${this.color}!`;
this.liveAnnouncer.announce(fakePurchase);
}
}
Weryfikowanie zmian
Ponownie włącz czytnik ekranu i sprawdź zmiany. Teraz będziesz otrzymywać powiadomienia o błędach.
Kontrola ułatwień dostępu:
- ✅ Wszystkie strony mają unikalne tytuły.
- ✅ Kolory mają wystarczający współczynnik kontrastu
- ✅ Semantyczny kod HTML zapewnia logiczną interakcję
- ✅ Wszystkie elementy sterujące są dostępne dla czytników ekranu.
- ✅ Suwak używa atrybutów ARIA do podawania etykiety
- ✅ Selektor kolorów ma prawidłowe przechwytywanie fokusu
- ✅ Ogłaszanie zmian, błędów i powiadomień
- 🛑 Tryb wysokiego kontrastu nie jest włączony
12. Włączanie trybu wysokiego kontrastu
System Microsoft Windows obsługuje funkcję ułatwień dostępu o nazwie Tryb wysokiego kontrastu. Ten tryb zmienia wygląd wszystkich aplikacji, w tym aplikacji internetowych, aby znacznie zwiększyć kontrast. W Angularze chcesz uwzględniać preferencje użytkownika w aplikacji.
Właściwość HighContrastModeDetector pozwala określić, czy przeglądarka jest obecnie w środowisku trybu wysokiego kontrastu.
Ten tryb jest obsługiwany w przeglądarkach Internet Explorer, Microsoft Edge i Firefox. Google Chrome nie obsługuje trybu wysokiego kontrastu w systemie Windows. Ta usługa nie wykrywa trybu wysokiego kontrastu dodanego przez rozszerzenie przeglądarki Chrome o nazwie Wysoki kontrast.
Po zakończeniu tej sekcji Twoja aplikacja przejdzie następujący audyt:
- 🛑 Tryb wysokiego kontrastu nie jest włączony
Te czynności znajdziesz w komentarzach: TODO: #12. Enable HighContrast mode.
Określenie problemu
Aby zidentyfikować ten problem, otwórz aplikację w przeglądarce Internet Explorer, Microsoft Edge lub Firefox, włącz tryb wysokiego kontrastu i zwróć uwagę na brak zmian:
- Otwórz aplikację w przeglądarce Internet Explorer, Microsoft Edge lub Firefox.
- Włącz tryb wysokiego kontrastu.
- Zwróć uwagę, że aplikacja nie uległa zmianie.
Dodawanie obsługi trybu wysokiego kontrastu
W styles.scss użyj miksu cdk-high-contrast z @angular/cdk/a11y, aby dodać obramowanie przycisków w trybie wysokiego kontrastu:
src/app/shop/shop.component.scss
@use '@angular/cdk';
.purchase-button {
border-radius: 5px;
background-color: mat.get-color-from-palette(mat.$pink-palette, A100);
@include cdk-high-contrast {
outline: solid 1px;
background-color: mat.get-color-from-palette(mat.$pink-palette, 50);
}
}
:host-context(.dark-theme) {
.purchase-button {
background-color: mat.get-color-from-palette(mat.$light-green-palette, A100);
@include cdk-high-contrast {
outline: solid 1px;
background-color: mat.get-color-from-palette(mat.$light-green-palette, 50);
}
}
}
Weryfikowanie zmian
Odśwież aplikację i sprawdź zmiany. W trybie wysokiego kontrastu przycisk ma kontur.

Kontrola ułatwień dostępu:
- ✅ Wszystkie strony mają unikalne tytuły.
- ✅ Kolory mają wystarczający współczynnik kontrastu
- ✅ Semantyczny kod HTML zapewnia logiczną interakcję
- ✅ Wszystkie elementy sterujące są dostępne dla czytników ekranu.
- ✅ Suwak używa atrybutów ARIA do podawania etykiety
- ✅ Selektor kolorów ma prawidłowe przechwytywanie fokusu
- ✅ Ogłaszanie zmian, błędów i powiadomień
- ✅ Tryb wysokiego kontrastu jest włączony.
13. Gratulacje!
Gratulacje! Udało Ci się rozwiązać typowe problemy z dostępnością w aplikacji Angular. 🎉
Aby zobaczyć wszystkie rozwiązania, zapoznaj się z main gałęzią.

Znasz już najważniejsze kroki, które pozwolą Ci uniknąć 8 częstych problemów z dostępnością w aplikacji Angular.
Więcej informacji
Zapoznaj się z tymi ćwiczeniami:
- Tworzenie aplikacji internetowej za pomocą Angulara i Firebase
- Wykrywanie i naprawianie tekstu o niskim kontraście za pomocą Narzędzi deweloperskich w Chrome
Zapoznaj się z tymi materiałami: