Przycisk roli ARIA: Guía Completa y Práctica
Rola ARIA button sprawia, że technologie asystujące ogłaszają generyczny kontener jako przycisk, ale nie zapewnia ona żadnego zachowania: należy dodać tabindex="0", obsłużyć klawisze Enter i Spacja oraz odzwierciedlić stan za pomocą aria-pressed lub aria-disabled. Specyfikacja WAI-ARIA 1.2 definiuje tę rolę w kategorii widgetów, a pierwsza zasada ARIA zaleca używanie natywnego elementu <button>, gdy tylko jest to możliwe.
Rola ARIA button należy do taksonomii ról WAI-ARIA – standardu W3C opisującego semantykę dostępności dla interfejsów webowych. Gdy element otrzyma role="button", drzewo dostępności budowane przez czytniki ekranu (NVDA, JAWS, VoiceOver, Narrator) przestaje traktować go jako generyczny div lub span i prezentuje go jako kontrolkę interaktywną. Różnica jest ogromna dla osoby korzystającej z czytnika ekranu: bez tej roli użytkownik słyszy „grupa” lub po prostu tekst; z tą rolą słyszy „przycisk” i wie, że może go aktywować.
Częstym błędem jest przekonanie, że role="button" zamienia div w funkcjonalny przycisk. Tak nie jest. Rola zmienia jedynie ogłaszaną semantykę; zachowanie – otrzymywanie fokusu, reakcja na klawiaturę, wyzwalanie akcji – pozostaje w gestii programisty. Ten rozdział między semantyką a zachowaniem jest źródłem większości błędów popełnianych przy tej roli.
WAI-ARIA została opublikowana jako rekomendacja W3C, a wersja 1.2 jest aktualnym punktem odniesienia dla ról, stanów i właściwości. Rola button jest jedną z najstarszych i najstabilniejszych ról widgetów w specyfikacji, obecną już od wersji ARIA 1.0.
Kiedy używać role=“button”, a kiedy nie
Pierwsza zasada ARIA, zawarta w praktykach autorskich WAI-ARIA (WAI-ARIA Authoring Practices), jest jednoznaczna: jeśli istnieje natywny element HTML o semantyce i zachowaniu, którego potrzebujesz, użyj go. <button> posiada już domyślną rolę, fokus klawiatury, aktywację klawiszami Enter i Spacja oraz stan wyłączony. Ponowne implementowanie tego wszystkiego za pomocą role="button" to dodatkowa praca i źródło błędów.
Istnieją jednak uzasadnione scenariusze użycia tej roli. Najczęstszym jest sytuacja, gdy kod jest narzucony przez framework lub CMS i nie można wprowadzić elementu <button> bez zepsucia układu lub istniejącego JavaScriptu. Innym przypadkiem są komponenty, które muszą zachowywać się jak przycisk, ale których struktura wewnętrzna wymaga specyficznego kontenera, jak niektóre widgety zewnętrznych dostawców.
Powiązane: — Superposición de IA que promete cumplimiento WCAG w 48 godzinach.
Trzeci scenariusz, bardziej dyskusyjny, dotyczy elementów, które mają już inną natywną rolę, a muszą być prezentowane jako przycisk. W takim przypadku warto zadać sobie pytanie, czy projekt nie wymusza błędnej semantyki. Jeśli coś wygląda jak przycisk, ale w rzeczywistości prowadzi do innej strony, właściwym rozwiązaniem jest link <a>, a nie przycisk.
| Sytuacja | Rekomendowane rozwiązanie | Powód |
|---|---|---|
| Akcja w formularzu lub interfejsie | natywny <button> | Rola, fokus i klawiatura w zestawie |
| Nawigacja do innego adresu URL | <a href> | Poprawna semantyka linku |
| Kontener niemodyfikowalny | role="button" + klawiatura + stany | Jedyny przypadek, gdy rola pomaga |
| Przycisk przełącznika (on/off) | <button aria-pressed> | Stan udostępniony natywnie |
| Przycisk wyłączony | <button disabled> | Zarządzanie stanem i fokusem |
Jak poprawnie zaimplementować przycisk z role=“button”
Przycisk oparty na role="button" musi obejmować cztery aspekty: fokus, klawiaturę, stan i dostępną nazwę. Pominięcie któregokolwiek z nich tworzy kontrolkę, która „wydaje się” dostępna, ale zawodzi w rzeczywistych testach.
Fokus aktywuje się za pomocą tabindex="0", co wstawia element do naturalnego porządku tabulacji. Nigdy nie używaj tabindex z wartościami dodatnimi: zmieniają one kolejność tabulacji na całej stronie i powodują nieprzewidywalne skoki. Wartość 0 jest poprawna dla niestandardowych elementów interaktywnych.
Warto zobaczyć: — Accesibilidad gestionada: automatización cobinada con revisión humana.
Klawiatura wymaga obsługi dwóch klawiszy: Enter i Spacja. Natywny <button> reaguje na oba, ale div z rolą ARIA przycisku nie robi tego automatycznie. Należy nasłuchiwać zdarzenia keydown i wykonywać akcję, gdy klawisz to Enter lub Space, zapobiegając jednocześnie przewijaniu strony, które domyślnie wywołuje Spacja. Ten szczegół jest często pomijany, co skutkuje przyciskami działającymi tylko z myszką.
Stan komunikuje się za pomocą atrybutów ARIA. Przycisk przełącznika używa aria-pressed="true" lub "false", aby wskazać, czy jest aktywny. Przycisk wyłączony używa aria-disabled="true", co ogłasza stan, ale samo w sobie nie blokuje interakcji: akcję należy zablokować w kodzie. Różnica między aria-disabled a natywnym atrybutem disabled jest istotna, ponieważ ten pierwszy utrzymuje element w fokusu, a drugi usuwa go z kolejki tabulacji.
Dostępna nazwa jest tworzona z widocznego tekstu elementu lub, jeśli tekstu brak, za pomocą aria-label lub aria-labelledby. Przycisk bez dostępnej nazwy zostanie ogłoszony przez czytnik ekranu po prostu jako „przycisk”, bez żadnej wskazówki, co on robi.
<div
role="button"
tabindex="0"
aria-pressed="false"
id="btn-modo"
>
Modo oscuro
</div>
<script>
const btn = document.getElementById('btn-modo');
function toggle() {
const activo = btn.getAttribute('aria-pressed') === 'true';
btn.setAttribute('aria-pressed', String(!activo));
}
btn.addEventListener('click', toggle);
btn.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
toggle();
}
});
</script>
Powyższy przykład obejmuje fokus, klawiaturę, stan i nazwę. Jest to absolutne minimum, aby kontrolka była użyteczna z czytnikiem ekranu i klawiaturą.
Częste błędy i sposób ich wykrywania
El error más Extendido es aplicar role="button" sin tabindex, lo que produce un botón inalcanzable por teclado. Las herramientas automáticas lo Detectan como „elemento con rol interactiveivo no enfocable”, una de las violaciones más reportadas en Auditorías de accesibilidad.
Drugi błąd nie jest gestionar el teclado. Un div con un aria role de botón y tabindex pero sin manejadores de tecla recibe foco y no responde a Enter ni Espacio. El usuario de teclado queda atrapado: puede enfocar el botón pero no activarlo.
Powiązane: — La certificación profesional que acredita tu experiencia en accesibilidad.
W przypadku wystąpienia błędu role="button" sobre un enlace. Esto rompe la semántica de navegación y confunde a los lectores de pantalla, que anuncian „botón” cuando el usuario espera un enlace. Si el elemento navega, debe ser un enlace.
El cuarto error es olvidar el estado en botones de alternancia. Un botón que cambia entre dos modos sin aria-pressed deja al usuario sin saber en qué estado se encuentra. El atributo es la única forma de comunicar ese estado de forma programática.
Para Detectar estos problemas, las herramientas automáticas como axe, Lighthouse o WAVE señalan las violaciones de rol y foco, pero no validan el comportamiento de teclado ni la lógica de estado. Esa parte exige prueba manual: navegar con Tab, aktywuj con Enter y Espacio, y escuchar la salida del lector de pantalla. La Combinación de Auditoría automatica y prueba manual es la única forma fiable de validar un botón personalizado.
Cómo probar un botón con role=“button”
La prueba empieza por el teclado. Recorre la página con Tab y comprueba que el botón con el aria Rola Przycisk Recibe Foco widoczny. Pulsa Enter y Espacio por separado: ambos deben disparar la acción. Si Espacio desplaza la página en lugar de activar el botón, falta el preventDefault.
La segunda prueba es con lector de pantalla. NVDA w Windows, VoiceOver w macOS i Narrator w Windows to más referencje. Al enfocar el botón, el lector debe anunciar el rol („botón”), el nombre accessible y el estado si lo tiene. Si anuncia „grupo” o no menciona el estado, algo falla.
La tercera prueba es de orden de foco. El botón debe aparecer en el orden lógico de tabulación, ni antes ni después de donde korespondent wizualny. Los tabindex positivos rompen este orden y son un indicador claro de mala implementación.
La cuarta prueba es de kontraste y foco widoczne. El indicador de foco no debe eliminarse con outline: none sin sustituirlo por una alternativa widoczny. Un botón que recibe foco pero no lo muestra deja al usuario de teclado sin referencia de dónde está.
Alternatywy nowoczesne jako przycisk rolkowy
El elemento <button> nativo sigue siendo la mejor opción en 2024 y en cualquier proyecto nuevo. Aporta rol, foco, teclado y estados sin código adicional, y los navegadores lo tratan de forma spójna.
Los elementy niestandardowe lub komponenty sieciowe dostępne za pośrednictwem. Ten komponent może rozszerzyć HTMLElement, który może być encapsular el comportamiento de botón y exponerlo con la semantic Correcta, aunque wymaga gestionar manualmente el foco y el teclado igual que con role="button". La ventaja es la reutilización; la desventaja, la misma responsabilidad de implementación.
Las ARIA w HTML (reglas que zdefiniowane qué role ARIA se pozwalają na sobre cada elemento HTML) desaconsejan sobrescribir role nativos. Dodaj rolę role="button" do <button> es redundante; aplicarlo a un <a> con href es contraproducente. La recomendación general es reservar el rol para contenedores sin semántica propia.
Kluczowe wnioski
role="button"cambia solo la semántica anunciada; el foco, el teclado y el estado hay que implementarlos a mano.- La primera regla de ARIA recomienda usar
<przycisk>nativo siempre que el marcado lo zezwolenie. - Przycisk z rolą arii wymaga
tabindex="0", manejo de Enter i Espacio, nombre accessible y stado conaria-pressedlubaria-disabled. - Las herramientas automáticas Detectan la falta de foco, pero el comportamiento de teclado y estado exige prueba manual con lector de pantalla.
- Nunca używa
tabindexpositivo ni apliquesrole="button"sobre enlaces que navegan.
Często zadawane pytania
¿Cuál es la diference entre role=“button” y el elemento przycisk?
El elemento <button> nativo incluye el rol implícito, el foco port teclado, la activación con Enter y Espacio y el stado deshabilitado sin codigo adicional. El atributo role="button" solo aporta la semántica anunciada; el resto del comportamiento debe programarse. Por eso la primera regla de ARIA recomienda el elemento nativo siempre que sea posible.
¿Konieczny jest tabindex z rolą=“przycisk”?
Si. Un div o span z role="button" nie jest możliwe do wykonania przez defekt, ponieważ jest to tabindex="0" queda fuera del orden de tabulación y es inalcanzable con teclado. El valor Correcto es 0; los valores positivos alteran el orden de tabulación de toda la página y deben evitarse.
¿Cómo hago que un div con role=“button” odpowiedz na Enter y Espacio?
Hay que escuchar el evento keydown y ejecutar la acción cuando la tecla es Enter lub Space. En el caso de Espacio conviene llamar a preventDefault para evitar el desplazamiento de página. Sin estos manejadores, el botón recibe foco pero no se activa con teclado.
¿Cómo indico que un botón está activo o deshabilitado?
Para un botón de alternancia usa aria-pressed="true" lub "false" según el estado. Para un botón deshabilitado usa aria-disabled="true", que anuncia el estado pero no bloquea la interacción por sí solo: hay que impedir la acción en el código. El atributo nativo disabled to preferowane cuando se usa un <przycisk>.
¿Czy można w praktyce używać roli=“przycisku” w enlace?
Sí, cuando el enlace navega inny adres URL. Sobrescribir el rol de un <a href> con role="button" rompe la semántica de navegación y confunde a los lectores de pantalla, que anuncian “botón” cuando el usuario espera un enlace. Si el elemento navega, debe conservar su rol de enlace.
¿Qué herramientas wykryć błędy związane z rolą=“przycisk”?
Herramientas automáticas como axe, Lighthouse lub WAVE señalan violaciones como la falta de foco en elementos con role interactiveivo. W przypadku embargo nie można potwierdzić zgodności teclado ni la lógica de stado, a następnie zweryfikować kompatybilną kombinację audytorów automatycznych z instrukcją obsługi za pomocą NVDA, VoiceOver lub Narrator.
Añade accesibilidad w 5 minut
Widżet umożliwiający dostęp do planu za darmo dla każdego użytkownika