Anatomia dobrego przycisku - HTML

10 czerwca 2026·3 min czytania

Dostępność przycisków brzmi prosto: użyj odpowiedniego tagu, daj mu nazwę, zadbaj o kontrast i focus W praktyce masz kilka narzędzi do wyboru i każde z nich zachowuje się inaczej. Nie ma jednego złotego środka - jest za to kilka dobrze zdefiniowanych przypadków, które warto poznać.

W pierwszej części skupimy się na anatomii z punktu widzenia HTML.

Poniżej wspominam o klasiesr-only. O tym, czym ona jest, przeczytasz więcej na https://www.dostepny-frontend.pl/blog/sr-only


Skąd bierze się "dostępna nazwa"?

Przeglądarka oblicza tzw. accessible name - nazwę, którą usłyszy użytkownik czytnika ekranu lub wypowie do Voice Control. Dla przycisku przegląda kilka źródeł po kolei i zatrzymuje się na pierwszym, które coś zwraca:

  1. aria-labelledby
  2. aria-label
  3. Treść tekstowa elementu (łącznie z dziećmi)
  4. title

Kluczowa rzecz: aria-labelledby i aria-label nadpisują treść. Nie uzupełniają - zastępują.


Trzy scenariusze i co z nimi zrobić

1. Przycisk z widoczną etykietą

<button>Usuń komentarz</button>

Treść jest dostępną nazwą. Nie trzeba nic dodawać. Dodawanie aria-label z identyczną wartością to redundancja - nieszkodliwa, ale bezcelowa. Jedna z naczelnych zasad, jakie usłyszysz na szkoleniu z dostępności cyfrowej brzmi: używaj aria-*tylko tam, gdzie jest to niezbędne.


2. Przycisk tylko z ikoną

Dobry przykład
<button>
    <svg aria-hidden="true">...</svg>
</button>

SVG jest ukryte przed czytnikiem przez aria-hidden- w 99% przypadków to element dekoracyjny. Przycisk nie ma żadnej dostępnej nazwy - to poważny błąd na poziomie A.

Rozwiązanie A: sr-only span

Dobry przykład
<button>
    <svg aria-hidden="true">...</svg>
    <span class="sr-only">Usuń komentarz</span>
</button>

Rozwiązanie B: aria-label

Dobry przykład
<button aria-label="Usuń komentarz">
    <svg aria-hidden="true">...</svg>
</button>

Które wybrać?

Oba są poprawne. Preferuj jednak rozwiązanie A (sr-only span) tam, gdzie to możliwe, zgodnie z zasadą, aby używać aria-* dopiero w ostateczności.


3. Przycisk z widoczną etykietą, który potrzebuje kontekstu

To najciekawszy przypadek. Masz listę elementów i przycisk „Usuń" przy każdym z nich. Wizualnie kontekst jest jasny - ale dla czytnika ekranu lista samych „Usuń" to pułapka.

Rozwiązanie A: sr-only span

Dobry przykład
<button>
  Usuń
  <span class="sr-only">komentarz</span>
</button>

Rozwiązanie B: aria-label

Dobry przykład
<button aria-label="Usuń komentarz">Usuń</button>

Którą wybrać?

Tutaj również oba rozwiązania są poprawne, lecz preferuj rozwiązanie A oparte o sr-only.

Różnica jest mechaniczna: aria-label zastępuje całą dostępną nazwę, sr-only rozszerza treść tekstową elementu. Gdy widoczny tekst zmieni się podczas refaktoru i ktoś zapomni zaktualizować aria-label - masz naruszenie kryterium WCAG niewidoczne w code review. Z sr-only ten błąd jest strukturalnie niemożliwy: widoczny tekst zawsze wchodzi w skład nazwy.


Czy trzy powyższe przykłady to jedyne możliwości?

Nie, to przykłady podstawowe, najprostsze dla zobrazowania, jak niewiele potrzeba, aby z punktu widzenia HTML mieć poprawny przycisk. Nie opisałem tutaj wspomnianego wyżej aria-labelledby, nie wspominam przycisków tworzonych za pomocą div[role="button"], linkach, które wyglądają i działają jak przyciski i innych niestandardowych rzeczach. Tak tworzone "przyciski" też mogą być dostępne, ale o tym napiszę kiedy indziej.


Podsumowanie - rekomendowany pattern

Masz ikonę w przycisku? Na 99% chcesz ją ukryć za pomocą aria-hidden="true".

Etykieta - nie musi być widoczna, ale musi być. Użytkownicy posługujący się na przykład czytnikami ekranu potrzebują informacji, czym jest ten przycisk i do czego służy. sr-onlyjest prawidłowym rozwiązaniem.

A aria-label? To rozwiązanie też jest ok, jeśli sprawisz, że taki przycisk będzie dostępny - cel będzie osiągnięty.

Udostępnij:

Newsletter

Nowe artykuły o dostępności (jakości) prosto na Twoją skrzynkę. Bez spamu. Polityka prywatności.