Tilgængelighed starter i dine piletaster
Jeg kan stadig huske første gang jeg “testede” tilgængelighed på et projekt. Jeg slog Lighthouse til, kørte en audit, fik 92 i “Accessibility” og tænkte: fedt, videre. Ugen efter fik vi en brugerhenvendelse fra en, der ikke kunne gennemføre en simpel formular med keyboard. Fokus forsvandt hver gang der kom en fejl.
Det pinlige? Jeg havde aldrig prøvet at bruge siden med andet end mus.
Hvis du kan genkende den energi, så er du ikke alene. De fleste udviklere starter deres WCAG-rejse i toppen med regler og tjeklister. Min erfaring er, at du får meget mere ud af at starte helt nede i hverdagen: keyboard, fokus, formularer. Det er de ting, der stopper folk helt fra at bruge din side.
Den 10-minutters test der afslører det meste
Før vi snakker WCAG for udviklere, ARIA-attributter og flotte begreber: prøv dit site som en bruger der kun har et keyboard.
Step 1: Sluk for musen (bogstaveligt talt)
Vælg en enkelt side i din app, gerne en lidt “rigtig” en: forsiden med navigation, en login-side eller en checkout. Læg musen væk.
Brug kun:
- Tab for at gå frem
- Shift + Tab for at gå tilbage
- Enter for klik
- Piletaster i dropdowns, radioknapper osv.
Og så laver du en mini-brugerrejse: åbn menu, gå til en underside, udfyld en formular, send den, ret en fejl.
Hvad du skal kigge efter
Når du tabber rundt, så læg mærke til:
- Kan du se, hvor fokus er hele tiden?
- Springer fokus rundt i en underlig rækkefølge?
- Sidder fokus fast i en komponent (f.eks. en modal eller menu)?
- Hvad sker der efter en handling, f.eks. form submit eller modal luk?
- Får du fejlbeskeder, når du taster noget forkert?
Skriv dine fund ned, helt kort: “Login: fokus forsvinder efter fejl”, “Menu: kan ikke nå undersider med Tab”. Det er din lille backlog.
Hvis du er helt ny til tilgængelighed, giver det mening at læse lidt generelt om HTML og CSS og semantik, for stort set alt i WCAG bygger oven på det.
Fokus-styles der faktisk kan ses
En af de mest udbredte “jeg vidste ikke det var slemt”-ting er den her:
button {
outline: none;
}
Den er født af et godt sted: vi vil gerne slippe for den blå, lidt grimme browser-outline. Problemet er bare, at hvis du ikke giver et alternativ, har keyboard-brugere ingen idé om, hvor de er.
Et simpelt fokus-system
En god strategi er:
- Behold outline som default mens du udvikler
- Erstat den først, når du har en gennemtænkt fokus-style
Eksempel:
/* Fælles fokus-style til interaktive elementer */
:where(a, button, input, textarea, select, [role="button"]):focus-visible {
outline: 2px solid #0f766e;
outline-offset: 2px;
border-radius: 4px;
}
Bemærk :focus-visible: den viser kun fokus, når det giver mening (typisk ved keyboard). Så får du ikke mærkelige outlines, når folk klikker med mus.
Typisk fejl: fokus forsvinder i custom komponenter
Når du bygger “pæne” knapper af divs, ikoner og spans, glemmer du ofte at de ikke er fokuserbare.
<div class="button">Gem</div>
Gør i stedet:
<button class="button">Gem</button>
eller hvis du
<div role="button" tabindex="0">Gem</div>
Men ærligt: brug rigtige HTML-elementer, når du kan. Du gør livet lettere for både dig selv og brugerne. Jeg skriver mere om præcis den pointe i artiklen om HTML-semantik.
Keyboard-navigation uden kaos
WCAG siger ikke at Tab-rækkefølgen skal være perfekt, men brugere forventer, at ting følger den visuelle rækkefølge. Hver gang fokus hopper “tilbage” på skærmen, føles det som et glitch.
Tab-rækkefølge: lad DOM’en bestemme
Regel nummer 1: brug tabindex så lidt som muligt.
- Standard interaktive elementer (links, knapper, inputs) har automatisk
tabindex=0 tabindex="-1"betyder, at du kan flytte fokus med JavaScript, men ikke via Tabtabindex="0"på et element gør det fokuserbart i normal rækkefølge- Undgå positive værdier (1, 2, 3 …) næsten altid
Hvis Tab-rækkefølgen føles forkert, er det ofte et tegn på, at din HTML-struktur ikke matcher layoutet. Så er løsningen som regel at ændre strukturen, ikke at plastre tabindex ovenpå.
Skip link: spring direkte til indhold
Hvis du har en navigation før dit hovedindhold (og det har du), så er et “skip to content”-link en billig stor gevinst.
<a href="#main" class="skip-link">Spring til indhold</a>
<nav>...</nav>
<main id="main" tabindex="-1">
...
</main>
Og lidt CSS:
.skip-link {
position: absolute;
left: -999px;
}
.skip-link:focus {
left: 1rem;
top: 1rem;
background: #0f766e;
color: white;
padding: 0.5rem 1rem;
}
Pointen: keyboard-brugere kan hoppe direkte forbi navigationen til det primære indhold.
Roving tabindex i menuer og carousels
Roving tabindex er et mønster, hvor kun ét element i en gruppe har tabindex="0" ad gangen, og resten har -1. Du tabber ind i gruppen én gang og bruger piletaster inde i den.
Det giver mening i f.eks.:
- Tabs-komponenter
- Carousels
- Komplekse menuer
Men du behøver ikke det mønster til en simpel vertikal navigation. Tit er det nok bare at lade links være links.
Formularer der forklarer sig selv
Formularer er der, hvor brugere enten elsker eller hader din side. WCAG handler her meget om tre ting: labels, hjælpetekst og fejlbeskeder.
Labels: klikbare og koblet til feltet
Klassisk fejl:
<input type="email" placeholder="Din email">
Det ser fint ud, men placeholder er ikke en label. Skærmlæsere læser den ikke nødvendigvis som navn på feltet, og teksten forsvinder, når du begynder at skrive.
Gør i stedet:
<label for="email">Email</label>
<input id="email" type="email" name="email">
Så kan du style labelen, som du vil, men nu har feltet et navn i koden.
Hjælpetekst og aria-describedby
Hvis du har ekstra forklaring, så bind den eksplicit til feltet:
<label for="password">Kodeord</label>
<p id="password-help">Mindst 8 tegn, gerne med tal.</p>
<input id="password" type="password" aria-describedby="password-help">
Nu bliver hjælpeteksten læst, når feltet får fokus i en skærmlæser.
Fejlbeskeder der hænger sammen med felter
Forestil dig at du submitter en formular, og der sker tre ting:
- Der kommer en rød tekst et eller andet sted på siden
- Feltet får en rød kant
- Fokus står stadig på submit-knappen
Det er svært nok for seende brugere. For en skærmlæser-bruger er det ren gæt.
Et bedre mønster:
<form id="signup" novalidate>
<div class="field">
<label for="email">Email</label>
<input id="email" name="email" type="email" aria-describedby="email-error">
<p id="email-error" class="error" aria-live="polite"></p>
</div>
<button type="submit">Tilmeld</button>
</form>
Og JavaScript:
const form = document.getElementById('signup');
const emailInput = document.getElementById('email');
const emailError = document.getElementById('email-error');
form.addEventListener('submit', (event) => {
event.preventDefault();
const value = emailInput.value.trim();
if (!value) {
emailError.textContent = 'Skriv din email.';
emailInput.setAttribute('aria-invalid', 'true');
emailInput.focus();
return;
}
emailError.textContent = '';
emailInput.removeAttribute('aria-invalid');
// send data
});
Her sker der noget vigtigt:
- Fejlbeskeden ligger lige ved feltet
aria-describedbybinder fejlteksten til feltetaria-live="polite"gør at ændringen bliver læst højt- Fokus flyttes tilbage til det første felt med fejl
Det føles meget mere “sammenhængende”, både med og uden skærmlæser.
Modals, dropdowns og dialogs uden fokus-fælder
Interaktive komponenter som modals og dropdowns er klassiske WCAG-fælder. Hvis fokus ikke styres tydeligt, kan brugeren ende “bag” modal-vinduet eller tabbe ud af dropdownen ved et uheld.
Modal: tre ting du skal styre
En god modal gør tre ting:
- Flytter fokus ind i modalen, når den åbnes
- Holder fokus inde i modalen, mens den er åben (fokus-trap)
- Sender fokus tilbage til knappen, der åbnede den, når den lukkes
HTML-skelet:
<button id="open-modal">Åbn dialog</button>
<div id="modal" role="dialog" aria-modal="true" aria-labelledby="modal-title" hidden>
<h2 id="modal-title">Bekræft handling</h2>
<p>Er du sikker på at du vil fortsætte?</p>
<button id="confirm">Ja</button>
<button id="close-modal">Annuller</button>
</div>
JavaScript i simpleste form:
const openBtn = document.getElementById('open-modal');
const modal = document.getElementById('modal');
const closeBtn = document.getElementById('close-modal');
const confirmBtn = document.getElementById('confirm');
let lastFocusedElement = null;
openBtn.addEventListener('click', () => {
lastFocusedElement = document.activeElement;
modal.hidden = false;
confirmBtn.focus();
});
closeBtn.addEventListener('click', closeModal);
function closeModal() {
modal.hidden = true;
if (lastFocusedElement) {
lastFocusedElement.focus();
}
}
// Luk med Escape
window.addEventListener('keydown', (event) => {
if (event.key === 'Escape' && !modal.hidden) {
closeModal();
}
});
En rigtig fokus-trap kræver lidt mere kode (find alle fokuserbare elementer i modalen, hop tilbage til første/sidste ved Tab / Shift+Tab), men selv det her er en stor forbedring i forhold til at lade fokus sejle.
Dropdowns og menuer
For dropdowns er mønstret:
- Udvidet: pil ned åbner, pil op/ned flytter valg
- Enter eller Space vælger
- Escape lukker
- Tab lukker og går videre til næste fokuspunkt
Du behøver ikke bygge alt selv. Men hvis du laver custom komponenter, så kig på, hvordan native <select> opfører sig og læn dig op ad det.
Testværktøjer: Lighthouse, axe og dine egne hænder
Automatiske tools er gode, men de løser ikke alt for dig. Specielt ikke focus management og keyboard-navigation. Her er en realistisk måde at kombinere dem på.
Lighthouse: hurtig baseline
Chrome DevTools → Lighthouse → Accessibility. Det finder typisk:
- Manglende alt-tekster
- Dårlig farvekontrast
- Manglende labels på inputs
Jeg bruger det som en hurtig “er vi helt væk?” test, ikke som facitliste.
axe: mere detaljeret dev-tool
Installer axe DevTools som browser-extension. Den er god til at:
- Forklare hvorfor noget er et problem
- Linke til WCAG-kriterier
- Gruppere fejl per komponent
En fin lille workflow er:
- Vælg én side
- Kør axe
- Ret 3-5 fejl
- Kør igen
Så har du en håndterbar feedback-loop i stedet for 50 røde advarsler på én gang.
Manuel test: det der fanger de sidste 20 %
Keyboard-testen fra starten af artiklen kommer igen her. Ingen automatisk scanner opdager, at fokus står tilbage på “Gem” efter en fejl, eller at din modal føles mærkelig at tabbe rundt i.
WCAG for udviklere er i høj grad netop den kombination: et par værktøjer til at finde de åbenlyse ting og så dine egne hænder til resten.
Mini-checklister du kan genbruge
For at gøre det her operationelt, er det fedt at have små tjeklister per komponent. Ikke 40 punkter, bare det vigtigste.
Navigation / header
- Kan du nå alle links med Tab alene?
- Har du et skip-link til hovedindhold?
- Har burger-menu både visuel og tekstlig label?
- Åbner/lukker menu med Enter/Space, og lukker den med Escape?
Formular
- Har alle felter en label, der er koblet med
forogid? - Er hjælpetekster bundet via
aria-describedby, hvor det giver mening? - Flytter du fokus til den første fejl ved submit?
- Bliver fejl og succes-beskeder annonceret via
aria-live?
Modal / dialog
- Får modalen fokus, når den åbner?
- Er baggrunden utilgængelig mens modal er åben (ingen Tab derude)?
- Lukker Escape altid modal?
- Kommer fokus tilbage til det element, der åbnede modalen?
Du kan endda lave en lille README eller intern docs-side i dit projekt, hvor du samler de her tjeklister. Det gør WCAG-arbejdet til en del af din normale test- og kvalitetsrutine i stedet for et særskilt “compliance”-projekt.
Sådan viser du WCAG-arbejde i din portefølje
Hvis du er på vej mod første job, er tilgængelighed en ret undervurderet måde at skille sig ud som frontend- eller full stack-udvikler. Ikke ved at skrive “jeg kan WCAG” øverst, men ved at dokumentere små, konkrete valg.
Eksempel: kort beskrivelse i README
I stedet for:
Accessibility: WCAG compliant
så skriv noget i stil med:
Tilgaengelighed
- Navigation kan bruges fuldt ud med keyboard (Tab, Shift+Tab, Enter, Escape)
- Alle formularfelter har labels og fejlbeskeder bundet med aria-describedby
- Modals flytter fokus ind, trapper fokus og sender fokus tilbage ved luk
- Testet med Lighthouse og axe DevTools
Det er meget nemmere for en reviewer at tage seriøst. Det viser, at du ved, hvad du faktisk har gjort, ikke bare hvad der lyder pænt.
Små noter i kode og commits
Hvis du allerede bruger Git aktivt (hvis ikke, så er artiklen om at overleve Git uden overkill et fint sted at starte), kan du skrive beskeder som:
feat: add skip link and focus handling to main nav
fix: connect form errors with aria-describedby
Det er små ting, men det gør din tilgang til tilgængelighed synlig.
En lille gentagelig WCAG-rutine
Hvis jeg skulle sammenfatte en realistisk proces, du kan køre på et projekt på 1-2 timer, ville den se sådan her:
- Vælg én repræsentativ side (nav + formular + måske en modal)
- Brug 10 minutter på ren keyboard-test og skriv fund ned
- Kør Lighthouse og axe for at fange de low-hanging-fruits
- Ret fokus-styles og åbenlyse label/kontrast-fejl
- Implementer korrekt fejl-håndtering på én formular
- Test igen med keyboard og evt. en skærmlæser (NVDA / VoiceOver)
Det lyder måske som meget, men når du har gjort det et par gange, bliver det bare endnu en del af måden, du bygger komponenter på. Lidt ligesom da du første gang fik styr på dit build-setup og ikke har lyst til at gå tilbage til “bare en script-tag”-tiden.
Jeg er ret sikker på, at de næste par år bliver dem, hvor “WCAG for udviklere” går fra at være noget man siger til jobsamtaler til noget der faktisk bliver testet i kode-review. Spørgsmålet er bare: vil du først opdage det, når nogen beder dig om at forklare din fokus-håndtering, eller vil du allerede have en lille, veltestet rutine klar?







Send kommentar
Du skal være logget ind for at skrive en kommentar.