De fyra ingenjörspraktikerna som gör verklig skillnad
Åsiktsstarka. Inte uttömmande. Mönstren som, när de följs, eliminerar de flesta tillgänglighetsregressioner innan code review.
Semantisk HTML först, ARIA i andra hand
När inbyggd HTML kan göra jobbet, använd den. <button>
har tangentbordshantering, fokus, roll och Enter/Space-aktivering inbyggt;
<label> binder ett kontrollElement till sin beskrivning;
<dialog> levereras med fokusfällans och inert-rest-of-page-beteende
som du annars skulle behöva skriva för hand; <details> är
en disclosure-widget utan JavaScript alls. ARIA är nödutgången — användbar när
det inte finns något inbyggt element för jobbet, skadlig när den läggs ovanpå
ett som redan fungerar. Referens:
WCAG 2.2:s framgångskriterier och
W3C ARIA Authoring Practices Guide.
Tangentbordsstöd är inte en kryssruta
Varje interaktivt element måste fungera med enbart tangentbordet. Tab
och Shift+Tab för att förflytta sig; Enter eller Space för att aktivera; Esc för att
stänga en tillfällig yta (modal, popover, meny). Fokus måste vara synligt —
aldrig outline: none; utan ersättning. Fokus
måste flytta logiskt — när ett modal öppnas går fokus in i det; när
modalen stängs återvänder fokus till elementet som öppnade det.
Testa med tangentbordet innan du testar med musen;
musen döljer buggar som tangentbordet omedelbart avslöjar.
Tillgängliga namn och beskrivningar
Inte aria-label-strösslingar. Det tillgängliga namnet kommer
från elementets textinnehåll som standard; aria-labelledby
refererar en annan nods text; aria-label åsidosätter
allt med en hårdkodad sträng (och bör vara din sista utväg eftersom den
kringgår översättning och tenderar att driva ifrån den synliga labeln). Den
tillgängliga beskrivningen är separat —
aria-describedby refererar hjälptextnoden eller
felmeddelande-noden. Verifiera i DevTools tillgänglighetsträd
vad skärmläsaren faktiskt tar emot — antaganden och
verklighet stämmer ofta inte överens.
Testa i din riktiga CI-miljö, inte bara lokalt
En lokal axe-kontroll är ett förnuftstest. En grön CI är en
regressionsgrind. Koppla eslint-plugin-jsx-a11y till varje PR;
lägg till axe-core-påståenden i enhets- och e2e-tester; kör
AT-driver-flöden på representativa sidor så att en riktig skärmläsare
väger in. Undersökningen av
skärmläsartestverktyg
täcker vad som är värt att automatisera och vad som fortfarande kräver manuell genomgång.
Verktygskedjan — 13 kurerade verktyg och bibliotek
Varje post kopplas till en livscykelfas — lint, enhetstest, e2e, runtime, övervakning eller manuell granskning — så att du kan koppla rätt verktyg till rätt grind.
-
Runtime
axe-core
Testmotorn för tillgänglighet som driver det mesta av verktygen nedan. Integrera den i enhetstester, e2e-sviter eller koppla den till din DOM-miljö under utveckling för kontroller vid körning.
-
E2E
axe DevTools
Webbläsartillägg med integrationer för Playwright, Cypress, Jest och Selenium. Standardgränssnittet för utvecklare ovanpå axe-core.
-
Statiska lint-regler för React JSX. Fångar de enkla misstagen (saknad alt, ogiltiga roller, onClick på div) innan code review.
-
Runtime
vue-axe
Tillgänglighetskontroll vid körning för Vue — visar axe-core-överträdelser i webbläsarkonsolen under utveckling.
-
Enhetstest
@testing-library/jest-dom
Tillgänglighetsfokuserade query-matchare för enhetstester. Uppmuntrar dig att hitta noder på det sätt en skärmläsare skulle göra (via roll + tillgängligt namn) snarare än via klass.
-
End-to-end-webbläsarautomatisering med förstklassig axe-core-integration. Kör tillgänglighetspåståenden mot riktiga webbläsare i CI.
github.com/dequelabs/axe-core-npm/tree/develop/packages/playwright ↗
-
Enhetstest
Storybook a11y addon
axe-core-skanning per komponent i ditt designsystem. Fångar överträdelser innan de når produktionskoden.
-
Övervakning
Pa11y
CLI-skanner som omsluter axe-core och HTML CodeSniffer. Det rätta primitiva verktyget för en CI-grind som misslyckas med bygget vid regressioner.
-
Övervakning
Lighthouse CI
Google-drivet, inkluderar en tillgänglighetsgranskning (axe-core under huven) plus prestanda- och god-praxis-poäng. Användbart för att följa trender.
-
Manuell
WebAIM WAVE
Visuell skanner som lägger problem som ett lager ovanpå den levande sidan. Bra för designer och innehållsförfattare som inte vill gå igenom JSON-rapporter.
-
Enhetstest
Wallaby + axe-core integration
IDE-feedbackloop — kör axe-core-påståenden bredvid din testmarkör. Snabbar upp utvecklarens iterationstakt när man kopplar ihop en ny komponent.
-
W3C-inkuberad standard för att styra riktiga skärmläsare från automatiserade tester. Fronten för automatiserad tillgänglighetstestning — äntligen bortom axe-liknande statiska kontroller.
-
Manuell
NVDA + JAWS + VoiceOver
De faktiska skärmläsare dina användare använder. Ingen automatisering ersätter manuell skärmläsargranskning för de 30–40% av WCAG-problemen som automatisering inte kan fånga.
Ramverksspecifika guider
Tillgänglighetsfall som tar olika form i olika ekosystem — och den djupare täckningen för vart och ett.
React
Nycklar i listor (felaktigt nyckelförsedda listor förvirrar skärmläsare när
objekt ordnas om). Fokushantering vid ruttbyte (utan det stannar fokus på
länken som utlöste navigeringen och den nya sidan är osynlig för AT-användare).
Portaler och fokusfällor — ett modal renderat i document.body måste
ändå hålla fokus inom sig. Hydreringsmissmatchningar som ändrar DOM-strukturen
mellan SSR och klient kan tyst bryta ARIA-relationer. Vår djupdykning om
aria-live-regioner i moderna ramverk
täcker live-regionens annonseringsmönster som Reacts reconciliation tenderar att bryta.
Vue / Svelte / Solid
Liknande mönster; reaktiva tillståndsändringar utlöser inte
live-regionsuppdateringar som standard. Varje ramverks reaktivitetsmodell har
en annan definition av "DOM har ändrats", och skärmläsare ser den resulterande
noduppdateringen — eller inte — på subtilt olika sätt. Vues v-if
kontra v-show, Sveltes reaktiva deklarationer och Solids
finkorniga reaktivitet producerar alla olika tillgänglighetsträdsuppdateringar
för vad som ser ut som samma kod.
Nativ mobil (iOS + Android)
En helt annan API-yta. iOS exponerar UIAccessibility
(och SwiftUI:s .accessibilityLabel() /
.accessibilityHint()) till VoiceOver; Android exponerar
AccessibilityNodeInfo till TalkBack. Webbaserad ARIA översätts inte.
Artikeln om
nativa mobila tillgänglighets-API:er
kartlägger webbkoncepten mot deras inbyggda motsvarigheter så att
webbutbildade ingenjörer kan sluta gissa.
Komponentbibliotek
Headless-bibliotek (Radix UI, Headless UI, React Aria) hanterar de svåra delarna — fokushantering, tangentbordshantering, ARIA-koppling — och lämnar det visuella designen helt till dig. Fullfjädrade bibliotek (Material UI, Chakra, Ant) levereras med åsiktsstarka visuella val men varierar kraftigt i tillgänglighetskvalitet, och "tillgänglig som standard" innebär sällan "granskad mot riktiga skärmläsare". Vår undersökning av tillgängliga komponentbibliotek betygsätter de viktigaste alternativen mot faktisk AT-testning.
PR-granskningschecklista för tillgänglighet
Skriv ut, klistra in i din PR-mall eller automatisera i en bot. Det minimum varje granskare bör titta på.
- Interaktiva element fungerar med enbart tangentbordet (Tab + Enter + Space + Esc).
- Fokusindikator synlig på varje interaktivt element.
- Formulärfält har en associerad
<label>. - Felmeddelanden är associerade med sina fält (
aria-describedbyeller angränsande text). - Dynamiska innehållsändringar annonseras via
aria-livenär det är lämpligt. - Modala dialoger fångar fokus och återställer det till öppnaren vid stängning.
- Bilder har meningsfull alternativtext; dekorativa bilder bär
alt="". - Listor använder
<ul>/<ol>/<dl>— inte<div>-sallad. - Rubrikhierarkin är logisk (inga hoppade nivåer).
- Lint + axe-tester klarar CI innan sammanslagning.
Vanliga ingenjörsmässiga antimönster
Mönster som klarar code review och sedan går sönder i produktion. Fånga dem tidigare.
- "Overlay-widgeten" — tredjepartsJavaScript som påstår sig lägga till tillgänglighet på en befintlig webbplats. Det gör det inte, det bryter ofta hjälpmedelslagret, och det har genererat sin egen våg av rättstvister. Bakgrund: overlay-leverantörer.
-
role="button"på ett<div>— lägger till rollannonseringen utan tangentbordsbeteendet (Enter, Space) eller fokusdeltagande. Använd<button>. -
aria-hidden="true"på fokuserbara element — skapar en fokusfälla där tangentbordsanvändare kan tabba till ett element som skärmläsaren instrueras att ignorera. Antingen ta bort elementet från tabbordningen medtabindex="-1"eller ta bortaria-hidden. - Anpassad rullgardinsmeny utan tangentbordshantering — en
<div>-baserad combobox som öppnas vid klick men ignorerar piltangenter, Home/End, förifyllning och Esc. Undersökningen av tillgängliga komponentbibliotek täcker de bibliotek som hanterar detta rätt direkt ur lådan. - Toast-notiser som inte annonseras — en
tillfällig yta renderad utan
role="status"(polite) ellerrole="alert"(assertive). Seende användare ser den; skärmläsaranvändare gör det inte. - Genererat DOM som bryter tillgänglighetsträdet
— tunga omslutningar runt ett input (en anpassad select byggd av
tolv nästlade
<div>) döljer ofta det faktiska kontrollElementet från AT. Testa vad AT ser, inte bara vad användaren ser.
Toolkit och övervakningspipelinen
De flesta team vill ha tre saker i följd: en engångstriage-skanning när något ser trasigt ut, en ingenjörsreferens när de vill förstå de underliggande mönstren, och ett kontinuerligt övervakningslager när tillgänglighet väl är med i produktionsplanen. Vår kostnadsfria WCAG 2.2-skanner täcker det första — klistra in en offentlig URL, få en axe-driven rapport i en ny flik. Ingenjörstäckningen på artikelredaktionen täcker det andra — inklusive tillgänglighetsskuld-som-teknisk-skuld och tillgänglighetsincidenter-SRE-postmortem-analyser för team som hanterar tillgänglighet i stor skala.
För det kontinuerliga lagret är köpguiden för övervakningsverktyg den mest åsiktsstarka texten på webbplatsen. Den betygsätter axe Monitor, Siteimprove, Level Access och Qualibooth — det sista som integrerar övervakning med en manuell granskningsöverlämning, den saknade pusselbiten i de flesta rent automatiserade stackar — mot täckningsbredd, falskt-positivt-frekvenser och hur rent data kopplar in i ingenjörsarbetsflöden. Hela poängen med övervakning är att se till att de åtgärder du levererar idag inte regrederar nästa sprint.
Vanliga ingenjörsfrågor
Frågorna som dyker upp vid varje tillgänglighetskickoff. Speglade i FAQPage-strukturdata.
- Är
aria-labelbättre än synliga textlablar? -
Nej. Synlig text är nästan alltid bättre — den gynnar seende
användare, seende användare med kognitiva funktionsnedsättningar,
röststyrningsanvändare (som säger vad de ser) och översättningsverktyg.
Använd
aria-labelbara när det inte finns någon synlig text att associera (knappar med enbart ikon) eller när den synliga texten genuint inte är det tillgängliga namn du vill ha. - Ska jag använda ARIA-roller för allt?
-
Nej. Den första regeln för ARIA är "do not use ARIA". Inbyggda HTML-element
levereras med rätt roll, rätt tangentbordsbeteende
och rätt semantik i tillgänglighetsträdet. Använd ARIA
bara när (och bara när) det inte finns något inbyggt element som passar —
till exempel en tablista, ett träd eller en anpassad dialog där du inte kan
använda
<dialog>. - Hur testar jag tillgänglighet i CI?
-
Tre lager, ordnade efter kostnad. (1) Lint:
eslint-plugin-jsx-a11ypå varje PR. (2) Enhetstester:@testing-library/jest-domplusjest-axe(eller@axe-core/react) på varje komponent. (3) End-to-end:@axe-core/playwrightpå representativa användarflöden. Lägg till en Pa11y- eller Lighthouse CI-grind på staging för att fånga den drift de lägre lagren missar. - Är axe-core och Lighthouse samma sak?
- Lighthouse använder axe-core under huven för sin tillgänglighetsgranskning, men kör en kurerad delmängd av reglerna och presenterar dem inom en bredare prestanda- / SEO- / god-praxis-rapport. axe-core är motorn — när du vill ha hela regeluppsättningen eller vill utöka den använder du axe-core direkt. För de flesta team: använd Lighthouse för trendspårning, axe-core för den faktiska grinden.
- Vad är den minimala tillgänglighetstestuppsättningen för ett React-projekt?
-
Lägg till
eslint-plugin-jsx-a11yi den befintliga ESLint- konfigurationen (den levereras med create-react-app och Next.js som standard). Lägg till@testing-library/jest-domochjest-axei din enhetstestuppsättning och anropaexpect(await axe(container)).toHaveNoViolations()i minst ett test per komponent. Det är golvet — det fångar ungefär 40% av verkliga WCAG-problem mot ett par timmars konfiguration. - Behöver jag testa med riktiga skärmläsare?
- Ja, för varje produktfunktion som en hjälpmedelsanvändare faktiskt kommer att använda. Automatiserade verktyg fångar strukturella fel (saknade lablar, kontrast, rollmissmatchningar) men inte upplevelsemässiga (fokus som hoppar till sidfoten, live-regioner som inte annonserar, ett "tillgängligt" modal som fångar fokus i fel delträd). Planera in minst en manuell genomgång per större release med NVDA på Windows och VoiceOver på macOS / iOS.
Nästa steg
Kör en snabb kontroll mot den kostnadsfria WCAG 2.2-skannern om du triagerar en specifik sida. Läs undersökningen av skärmläsartestverktyg innan du kopplar AT-driver till CI. Och om tillgänglighet är på väg att gå från "engångsgranskning" till "löpande produktionsfråga" är köpguiden för övervakningsverktyg den mest konkreta texten på webbplatsen för att välja leverantör.