Tilgængelige formularer uden hovedpine

Tilgængelige formularer uden hovedpine

Det meste a11y sidder i de små ting

De fleste tilgængelighedsproblemer i små webprojekter handler ikke om vilde ARIA-tricks, men om helt basale ting som labels, knapper og fokus-styles. Fixer du dem, er du allerede foran en stor del af internettet.

Jeg opdagede det første gang, da jeg prøvede at tabbe mig igennem min egen side og forsvandt ind i et sort hul mellem to formularfelter. Siden så fin ud med mus, men den var ærligt talt ubrugelig uden.

80/20 tilgængelighed i små projekter

Hvis du bygger personlige projekter, behøver du ikke kunne hele WCAG udenad. Du har brug for en lille kerne af vaner, der gør dine ting brugbare for langt de fleste.

For typiske portfolio-sider, små værktøjer og skolesites giver det her mest effekt:

  • Formularer med rigtige <label>, name og meningsfulde fejlbeskeder
  • Korrekt brug af <button> vs. <a>
  • God tastaturnavigation og tydelige fokus-states
  • Kun lidt, men velplaceret ARIA, når HTML ikke rækker

Resten kan du bygge på senere. Lidt som at lære akkorder før jazz-improvisation.

Formularer der giver mening for flere end dig

En formular er ikke bare inputfelter og en send-knap. Den er en lille dialog mellem brugeren og siden. Hvis den dialog kun fungerer visuelt, falder mange fra.

Så vi starter med tre ting, der næsten altid er galt i begyndersider: labels, name-attributter og autocomplete.

Label og input der faktisk hænger sammen

Typisk fejl: man skriver placeholder-tekst og glemmer labels. Det ser pænt ud, lige indtil placeholderen forsvinder, og brugeren ikke kan huske, hvad feltet var til.

Det her er den gode, gamle, kedelige, men rigtige måde:

<label for="email">Email</label>
<input 
  type="email" 
  id="email" 
  name="email" 
  autocomplete="email" 
/>

Nøglen er for på label og id på input, der matcher. Screen readers og tastaturbrugere ved nu, hvad feltet betyder, og du kan klikke på label og fokusere feltet.

Hvis du vil style med label inde i feltet, så brug hellere CSS end at droppe label helt. Du kan f.eks. bruge position: absolute; på label og flytte den.

name og autocomplete der faktisk hjælper

name bruges til at sende data til serveren, men det hjælper også browseren med at huske felter. Uden name er feltet nærmest anonymt.

Et fornuftigt login-udsnit kunne se sådan her ud:

<label for="user-email">Email</label>
<input 
  type="email" 
  id="user-email" 
  name="email" 
  autocomplete="email" 
/>

<label for="password">Adgangskode</label>
<input 
  type="password" 
  id="password" 
  name="password" 
  autocomplete="current-password" 
/>

autocomplete gør to ting: hjælper brugeren med autofill og hjælper password managers med at forstå, hvad feltet er. Det gør oplevelsen lettere for alle, ikke kun “tilgængelighedsbrugere”.

Validering: vis fejl på en måde alle kan forstå

Den mest klassiske aften-jeg-troede-jeg-havde-ødelagt-alt-fejl jeg selv har lavet, var en formular, der “ikke gjorde noget”. I virkeligheden fejlede den bare, uden jeg viste det nogen steder.

En god fejlbesked skal:

  • Være tæt på feltet, den handler om
  • Være tekst, ikke kun farve
  • Kunne findes af screen readers

Her er et lille mønster, du kan genbruge:

<label for="age">Alder</label>
<input 
  type="number" 
  id="age" 
  name="age" 
  aria-describedby="age-error" 
  aria-invalid="true" 
/>
<p id="age-error" class="error">
  Skriv din alder som et tal mellem 1 og 120.
</p>

aria-invalid="true" fortæller hjælpemidler, at feltet er i fejltilstand. aria-describedby binder fejlteksten til feltet. Brugeren får både visuel tekst og teknisk sammenhæng.

Hvis du vil se mere om, hvorfor semantik og tilgængelighed hænger sammen, så giver denne artikel på Coding Class om semantiske tags et godt udgangspunkt.

Knapper og links uden forvirring

Mange UI-fejl starter med én ting: alt er blevet lavet som et link. Eller alt er en <div> med en click-handler.

Det gør siden svær at bruge uden mus og forvirrer screen readers.

Hvornår er det en knap, og hvornår er det et link?

Tom regel:

  • Noget, der ændrer siden (åbner modal, sender formular, toggler menu) er typisk en <button>
  • Noget, der går til en anden side eller URL, er et <a>

Sådan her:

<!-- Korrekt: knap der åbner en menu -->
<button type="button">Åbn menu</button>

<!-- Korrekt: link til en anden side -->
<a href="/profil">Gå til din profil</a>

Hvis du styler dine knapper som links eller omvendt, er det helt fint. Bare brug de rigtige HTML-tags under overfladen.

Klikbare divs og spans, der ikke opfører sig som klik

Hvis du laver noget som det her, får tastaturbrugere det svært:

<div class="btn" onclick="openModal()">
  Åbn modal
</div>

Divs kan ikke fokuseres med tastatur som standard, og de annonceres ikke som klikbare. Så man ved ikke, at der “sker noget”.

Løsningen er egentlig kedelig:

<button type="button" onclick="openModal()">
  Åbn modal
</button>

Hvis du skal bruge en div af stil-grunde, skal du selv opfinde hele knap-adfærden med tabindex og keydown-handlers, og så er det hurtigere at bruge en rigtig knap.

Tastatur: tab-rækkefølge og fokus-styles

En hurtig test jeg altid laver på nye sider: jeg lægger musen væk og prøver at bruge siden med kun tab, enter og space. Hvis jeg farer vild eller mister fokus, er der noget galt.

Den naturlige tab-rækkefølge

Browsere følger DOM-rækkefølgen, når du tabber. Du behøver sjældent sætte tabindex, hvis din HTML er skrevet i en fornuftig rækkefølge.

Undgå især tabindex="-1" på ting, der burde være fokuserbare, og tabindex="0" på alt muligt pynt.

Hvis du bruger mange CSS-tricks til layout, så hold HTML-strukturen nogenlunde i den rækkefølge, du forventer, at brugeren læser siden. Flex og grid kan flytte ting visuelt, men tab følger stadig HTML.

Focus states i CSS: gør dem tydelige, ikke usynlige

En af de største “UX-kriminelle handlinger” er at fjerne fokus-outline uden at erstatte den:

button, a {
  outline: none;
}

Hvis du gør det, har tastaturbrugeren ingen idé om, hvor hun er. Du må gerne style fokus selv, men giv den noget synligt.

F.eks. sådan her:

button:focus-visible,
a:focus-visible,
input:focus-visible,
textarea:focus-visible {
  outline: 2px solid #2563eb; /* blå */
  outline-offset: 2px;
}

:focus-visible viser typisk kun fokus, når brugeren faktisk bruger tastatur, ikke ved mus-klik. Det føles mindre “støjende”, men hjælper der, hvor det skal.

Et lille “skip to content”-mønster

En nem ting, der scorer mange point hos screen reader- og tastaturbrugere, er et “spring til indhold”-link øverst.

Mønstret ser sådan her ud:

<a href="#main" class="skip-link">
  Spring til hovedindhold
</a>

<header>...</header>

<main id="main">
  ... dit indhold ...
</main>

Og CSS:

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: #111;
  color: #fff;
  padding: 0.5rem 1rem;
  z-index: 1000;
}

.skip-link:focus-visible {
  left: 0.5rem;
  top: 0.5rem;
}

Så kan man tabbe én gang, trykke enter og hoppe forbi navigation til det vigtige indhold. En lille ting, men det føles markant bedre i brug.

ARIA uden panik: fem små regler

ARIA er det sted, hvor mange begynder at stå af. Jeg gjorde det samme og tænkte “det her lærer jeg senere”. Tricket er at starte lavt: du behøver ikke kunne alt.

Hvis du følger de her fem regler, er du allerede godt kørende:

  • 1. Brug semantisk HTML før ARIA. En rigtig <button> er bedre end role="button" på en div.
  • 2. Brug ARIA til at forbinde ting. F.eks. aria-describedby mellem input og fejltekst.
  • 3. Markér tilstande. F.eks. aria-expanded="true" på en menu-knap, når menuen er åben.
  • 4. Undgå at overskrive native roller, hvis du ikke skal. Du behøver sjældent sætte role="button" på en <button>.
  • 5. Hvis du ikke ved, hvad et ARIA-attribut gør, så google det, før du bruger det. Gættet ARIA er værre end ingen ARIA.

Et simpelt eksempel med en fold-ud-sektion:

<button 
  type="button" 
  aria-expanded="false" 
  aria-controls="faq-1" 
  id="faq-toggle-1"
>
  Vis svar
</button>

<div id="faq-1" hidden>
  <p>Her er svaret på spørgsmålet.</p>
</div>

Din JavaScript kan så skifte aria-expanded mellem true og false og toggler hidden på div’en. Ingen kæmpe ARIA-orkester, bare lidt tydeligere state.

Mini-øvelse: fix 10 a11y-fejl

Nu til den del, hvor du rent faktisk lærer noget: ret fejl. Det er seriøst den hurtigste måde at få tilgængelighed ind under huden.

Lav en lille HTML-side med f.eks.:

  • En navigation med tre links
  • En kontaktformular med navn, email, besked og en send-knap
  • En “åbn modal”-knap, der bare viser en boks med lidt tekst

Smid så med vilje følgende fejl ind:

  • Brug kun placeholders, ingen <label>
  • Drop name på alle inputs
  • Gør send-knappen til en <div> med click-handler
  • Fjern alle fokus-styles i CSS
  • Lav “åbn modal” som et <a> uden href
  • Vis fejlmeddelelser kun med farve (f.eks. rød kant)
  • Lav ingen sammenhæng mellem input og fejltekst
  • Glem autocomplete
  • Ingen “skip to content”-link
  • Lad modalens lukkeknap være et lille kryds i et <span>

Og så: gå dem igennem én for én og fix dem med de mønstre, vi har talt om. Test bagefter med tastatur og, hvis du kan, en screen reader eller f.eks. Chrome’s “Screen Reader” extension.

Hvis du vil kombinere det med semantik, kan du snuppe noget af strukturen fra artiklen om section vs article vs div og bygge oven på den.

Tilgængelighed tjekliste til dit næste portfolio-projekt

Jeg har efterhånden en lille mental tjekliste, jeg kører igennem, hver gang jeg laver en ny side med formularer eller knapper. Du kan stjæle den direkte.

Formularer

  • Har alle felter en synlig label, der hænger sammen via for/id?
  • Har alle felter et meningsfuldt name?
  • Bruger jeg passende type (email, number, password osv.)?
  • Er relevante felter forsynet med autocomplete?
  • Har jeg tekst-fejlbeskeder, der er forbundet via aria-describedby, når der er fejl?

Knapper og links

  • Bruger jeg <button> til handlinger og <a> til navigation?
  • Findes der nogen klikbare divs/spans, der burde være knapper eller links?
  • Har alle links et href, der giver mening?

Tastatur og fokus

  • Kan jeg nå alle interaktive elementer med Tab?
  • Har jeg tydelige fokus-styles (gerne med :focus-visible)?
  • Har jeg et “spring til indhold”-link øverst, der virker?

ARIA

  • Bruger jeg primært semantisk HTML i stedet for at lappe med ARIA?
  • Hvis jeg bruger ARIA, ved jeg så hvad det konkrete attribut gør?
  • Har dynamiske elementer (som fold-ud, modal, dropdown) en klar state, f.eks. med aria-expanded?

Hvis du har svært ved at huske det hele, så skriv den her liste i din projekt-README eller lav et lille internt “a11y.md” i repoet. Det føles lidt nørdet, men på den gode måde.

Til sidst: det her er en vane, ikke en feature

Jeg ser tilgængelighed som noget, der skal med fra første prototype, ikke som en bonusrunde. Lidt ligesom at gemme ofte, så du ikke mister din tegning, når katten går hen over tastaturet.

Og ja, du kommer til at glemme noget ind imellem, men hver gang du opdager en ny lille a11y-ting og får den rettet, bliver alle dine fremtidige projekter en tand bedre. Det synes jeg faktisk er ret tilfredsstillende.

Ida Balslev er den type ven, der pludselig dukker op i din messenger med et link til en lille web-app, hun lige har bygget for sjov – og bagefter gerne viser dig, hvordan du selv kan lave den. Hendes passion for kodning startede med en hjemmebygget hjemmeside til en hestestald og er langsomt vokset gennem aftener med tutorials, fejlmeldinger og små, hjemmelavede projekter.

På Codingclass.dk deler Ida den viden, hun selv manglede i starten: konkrete eksempler, tydelige forklaringer og ærlige historier om, hvad der typisk går galt første, anden og tredje gang. Hun elsker at tage et abstrakt begreb som fx "API" eller "asynkron JavaScript" og koge det ned til noget, du kan se, klikke på og lege med i browseren. For hende handler kodning ikke om at være perfekt, men om at turde prøve, bryde ting og bygge dem op igen.

Ida skriver især om webudvikling med HTML, CSS og JavaScript, små Python-scripts og grundlæggende koncepter som debugging, versionsstyring og struktur i din kode. Hun tænker altid i næste skridt: når du først forstår idéen, viser hun dig, hvordan du kan udvide det med en ekstra funktion, lidt pænere styling eller en smartere måde at tænke din kode på.

Gennem sine artikler på Codingclass.dk vil Ida gerne give dig følelsen af, at du ikke sidder alene med koden – men at der faktisk er en, der har kæmpet med de samme fejlmeddelelser og nu gerne vil vise dig en vej igennem dem, i et tempo hvor alle kan være med.

Send kommentar

You May Have Missed