A11y

Et indblik

Braille

Webtilgængelighed

Hvad forbinder du med A11Y?

Tre stikord

Sum med sidemakkeren

Webtilgængelighed er ofte fejlopfattet som separat disciplin eller en eftertanke

Compliance-bestræbelser fører til tjeklistementalitet

Jakoba Mulderhuis i Amsterdam

Bygningen opfylder DS/ISO 21542-standarden for tilgængelighed

Lovgivning

Lov om tilgængelighed af offentlige organers websteder og mobilapplikationer

Lov om tilgængelighedskrav for produkter og tjenester

juni 2021

juni 2025

Lov om tilgængelighedskrav for produkter og tjenester

Påvirker produkter, der leveres fra 28. juni 2025

Påvirker alle produkter fra 28. juni 2030

Lov om tilgængelighedskrav for produkter og tjenester

Produkter og tjenester må kun bringes i omsætning eller leveres, hvis de opfylder de relevante tilgængelighedskrav

tjeklistementalitet

Tilgængelighedskrav

"...mere end én sensorisk kanal"

Understandable (forståelig)

Perceivable (opfattelig)

Operable (anvendelig)

Robust

"...hensyn til forventede anvendelsesforhold"

"...på en forståelig måde"

"...som brugerne kan opfatte"

LOV nr 801

Det kan løst oversættes til retningslinjerne for WCAG 2.1

Tilgængelighedskrav

Understandable (forståelig)

Perceivable (opfattelig)

Operable (anvendelig)

Robust

Tilgængelighedsprincipper

Tilgængelighedskrav

Understandable (forståelig)

Perceivable (opfattelig)

Operable (anvendelig)

Robust

Tilgængelighedsprincipper

at billeder gøres opfattelige for skærmlæserprogrammer ved at tekstliggøre billederne

Tilgængelighedskrav

Understandable (forståelig)

Perceivable (opfattelig)

Operable (anvendelig)

Robust

Tilgængelighedsprincipper

at webstedet er anvendeligt for brugere, der bruger tastatur og ikke mus

Tilgængelighedskrav

Understandable (forståelig)

Perceivable (opfattelig)

Operable (anvendelig)

Robust

Tilgængelighedsprincipper

at webstedet er anvendeligt for brugere, der bruger tastatur og ikke mus

Tilgængelighedskrav

Understandable (forståelig)

Perceivable (opfattelig)

Operable (anvendelig)

Robust

Tilgængelighedsprincipper

at en digital selvbetjeningsløsning er forståelig ved at tilbyde fejlforslag og instruktioner ved indtastning af fejl

Tilgængelighedskrav

Understandable (forståelig)

Perceivable (opfattelig)

Operable (anvendelig)

Robust

Tilgængelighedsprincipper

at webstedet er robust ved at benytte kodning korrekt, så brugerens værktøjer kan fortolke dem ensartet

Tilgængelighedskrav

Dokumentation

A11Y handler om brugssituationer

Kan interfacet opfattes, betjenes og forstås?

Tilgængelighed

Tilgængelighed

Inclusive design

Tilgængelighed

Inclusive design

Usability design

Compliance

Fra “Practical Accessibility af Sara Soueidan

Tilgængelighed

Grupper

Tilgængelig for alle

og brugervenlig

compliance ≠ brugervenlig

Tastatur og fokus

Kan alle betjene det — og se hvor de er?

Gå frem:  (Tab)

Gå tilbage: ⇧ (Shift+Tab)

Aktivér: ↵ (Enter)

Øvelse 1: Tivoli

  1. Gå til https://shop.tivoli.dk/
  2. Kun ved hjælp af tastaturet, naviger til “Forny dit Tivolikort”
  3. Find ud af, hvordan man finder sit kortnummer

Tastatur og fokus

Hvilke udfordringer støder du på?

Gå frem:  (Tab)

Gå tilbage: ⇧ (Shift+Tab)

Aktivér: ↵ (Enter)

Øvelse 2: Tivoli

  1. Gå fra “Køb billetter“-siden til “Turpas”-siden
  2. Vælg datoen for i morgen
  3. Accepter dags dato og vælg 2 antal Turpas
  4. Læg i kurv
  5. Vælg “Shop videre”

Tastatur og fokus

Hvilke udfordringer støder du på?

Tastatur-brugere

  • Focus styles
  • Tab order

  • Skip links

Focus styles

Kontrast

:focus-visible {
  outline: 3px solid black;
  box-shadow: 0 0 0 6px white;
}

Focus-styles skal være tydeligt synlige ved tastaturnavigation, have mindst 3:1 kontrast, svare til mindst arealet af en 2 CSS-px ramme og ikke være skjult.

Fjern aldrig outline uden en tilgængelig erstatning!

Universel?

Focus styles

Kontrast

:focus-visible {
  outline: 3px solid black;
  box-shadow: 0 0 0 6px white;
}

Hvad kan fokuseres?

Focus styles

<a href=""></a>
<input>
<select></select>
<textarea></textarea>
<button></button>
<iframe></iframe>
<div tabindex="0"></div> <!-- > 0 -->
<div style="overflow: auto;"></div> <!-- Måske -->
  • tabindex=”-1”: Gør elementer fokuserbare, men inkluderer ikke i tab-rækkefølge
  • tabindex=”0”: Inddrager element i tab-rækkefølgen
  • tabindex=”5”: Overskriver tab-rækkefølgen
<div class="button" tabindex="0">Træls knap</div>

Hvad kan fokuseres?

Focus styles

Tab-rækkefølgen

Tab order

Firefox

Spring navigationen over

Skip links

Spring navigationen over

Skip links

<a href="#main" class="skip-links">Skip to main content</a>
<main id="main">…</main>
  • Alt skal kunne betjenes fra tastaturet. Så brugere, der ikke kan bruge musen også har en chance.
  • Der skal være synligt tastaturfokus. Så vi kan se, hvor vi er, når vi navigerer med tastaturet.
  • Tilbyd mulighed for at springe over menuer/indhold. Så brugeren ikke får ondt i tungen.
  • Undgå tastaturfæller. Så man ikke som tastaturbruger hænger fast uden at kunne komme tilbage, videre eller væk.

Tastatur-brugere

Krav

mandatory

Omkring 20-30%

Begrænsninger ved automatiserede tests

  • Fokustilstande
  • Test af interaktioner (dropdownmenuer og modaler)
  • Trykflader (24x24)
  • 200%-400% zoom
  • Reduced motion-animationer
  • End-to-end-tests

Extensions & Tools

axe Accessibility Linter

DevTools

  • button
  • link
  • heading
  • list
  • navigation
  • osv.

Roller

  • toolbar
  • tablist
  • tab
  • tabpanel
  • status
  • osv

HTML elementer

ARIA

WAI-ARIA

Med ARIA kan vi formidle mere komplekse elementer, som vi kender fra operativsystem-grænsefladen men som ikke er en standard del af html.

Accessible Rich Internet Applications

WAI-ARIA

Skærmlæsere kommunikerer via accessibility API (accessibility tree).

  • ARIA opdaterer role, state og property i accessibility tree.
  • ARIA ændrer ikke på browserens opførsel.

WAI-ARIA

Der er tre typer ARIA attributter.

  • Role
  • State
  • Property

WAI-ARIA

  • Siger hvad et element er (button, dialog, radiogroup).
  • Et element må ikke dynamisk skifte rolle.
  • Nogle roller er afhængige af andre, fx listitem i list.
  • Nogle roller er landmarks, nav, main, search.

Role

WAI-ARIA

Siger noget om elementets tilstand fx aria-checked, aria-pressed, aria-expanded.

State

WAI-ARIA

Siger noget om en egenskab ved elementet fx aria-label, aria-labelledby, aria-haspopup, aria-level.

Property

State

<button
  aria-expanded="false"
  aria-controls="widget1">
  Toggle widget
</button>

fortæller om noget er åbent

fortæller, hvad der åbnes/lukkes

State

button.addEventListener("click", () => {
  panel.hidden = !panel.hidden;
  button.ariaExpanded = !panel.hidden;
});

Toggle state

Invokers i HTML

"Gratis" tilgængelighed

<button
  command="show-modal"
  commandfor=".."
  interestfor="...">
  Åben popover
</button>
<details>
  <summary>Åben</summary>
  ...
</details>

Skærm-
læser

Siden som navigerbar struktur

Overskrifter, landmarks og komponenter

Overskrifter

Hierarki

<body>
  <main>
    <h1>I describe the page's primary topic</h1>
    
    <section>
      <h2>A child section</h2>
      
    	<section>
          <h3>A sub-section of the child section</h3>
      	</section>
      
    </section>
    
  </main>
</body>

Overskrifter

Hierarki

Øvelse

  1. Installér HeadingsMap.
  2. Besøg BBC Travel
  3. Aktivér HeadingsMap
  4. Tal med sidemakkeren om overskrifthierarkiet
  5. Vi samler op

Overskrifter

Hierarki

span

Overskrifter

Hierarki

Hvorfor er det udfordrende?

Overskrifthierarki

Svar: Moderne webudvikling

function ProductCard({ product }) {
  return (
    <article>
      <h2>{product.name}</h2>
      <p>{product.price}</p>
    </article>
  );
}

Moderne webudvikling

<main>
  <h1>Søgeresultater</h1>

  <ProductCard product={vomero} />
</main>

function ProductCard({ product }) {
  return (
    <article>
      <h2>{product.name}</h2>
      <p>{product.price}</p>
    </article>
  );
}

Moderne webudvikling

<main>
  <h1>Sneakers</h1>

  <section>
    <h2>Populære lige nu</h2>

    <ProductCard product={vomero} />
  </section>
</main>

🚫

h1 Sneakers
├── h2 Populære lige nu
└── h2 Nike Zoom Vomero 5
function ProductCard({headingLevel, title, children}) {
  const Heading = `h${headingLevel}`;

  return (
    <article>
      <Heading>{title}</Heading>
      {children}
    </article>
  );
}

Manuelt

<ProductCard
  headingLevel={3}
  title="Nike Zoom Vomero 5">
  <p>1.299 kr.</p>
</ProductCard>

props

const HeadingLevelContext = createContext(1);

function Section({ title, children }) {
  const parentLevel = useContext(HeadingLevelContext);
  const level = parentLevel + 1;
  const Heading = `h${level}`;

  if (level > 6) {
    throw new Error("Indholdsstrukturen er mere end seks niveauer dyb");
  }

  return (
    <section>
      <Heading>{title}</Heading>

      <HeadingLevelContext.Provider value={level}>
        {children}
      </HeadingLevelContext.Provider>
    </section>
  );
}

Automatiseret

context

Nær fremtid

<body>
  <main>
    <h1>I describe the page's primary topic</h1>
    
    <section headingoffset="1">
      <h1>A child section</h1>
      
    	<section headingoffset="1">
          <h1>A sub-section of the child section</h1>
      	</section>
      
    </section>
    
  </main>
</body>

headingoffset

:heading(1) { ... }
:heading(2) { ... }
:heading(3) { ... }
/* ... */

Kobler til de rigtige aria-roller

Er sections mere semantiske end div'er?

<body>
  <main>
    
    <section> <!-- er jeg semantisk? -->
      
    </section>
    
  </main>
</body>

Landmarks

Navigation via regioner

Landmarks

Typer af regioner

  • banner
  • navigation
  • search
  • main
  • region
  • complementary
  • form
  • contentinfo

Landmarks

Indbygget i HTML-elementer

  • banner
  • navigation
  • search
  • main
  • region
  • complementary
  • form
  • contentinfo

<header> (direkte barn af body)

<nav>

<search>

<main>

<section> (hvis den har et navn)

<aside>

<form> (hvis den har et navn)

<footer> (direkte barn af body)

Landmarks

Indbygget i HTML-elementer

banner

complementary

main

region / form

contentinfo

navigation

Er sections semantiske?

<body>
  <main>
    
    <section aria-label="Min region"> <!-- Nu er jeg -->
      <h2>Overskrift</h2>
    </section>
    
  </main>
</body>

Er sections semantiske?

<body>
  <main>
    
    <section aria-labelledby="region-title"> <!-- Nu er jeg -->
      <h2 id="region-title">Overskrift</h2>
    </section>
    
  </main>
</body>

Men ikke alle bør ikke være det!

Hvornår bør en section være et region landmark?

<nav></nav>

Landmarks

Navngiv vigtige landmarks

Hvilken navigation?

<nav aria-label="Hovedmenu"></nav>
<nav aria-labelledby="breadcrumb">
  <h2 id="breadcrumb">Brødkrumme</h2>
  ...
</nav>

Landmarks

Navngiv vigtige landmarks

"Hovedmenu navigation"

"Brødkrumme navigation"

Åbn "Opgave" fra repo og lav første del:
Headings, landmarks og disclosure-knap

Opgave, del 1

Øvelse

Hvad hedder knappen?

Det synlige interface er ikke hele interfacet

  1. Gå til IKEA
  2. Find ud af, hvor navnet kommer fra

Øvelse

.visually-hidden

Overskrifter

Hvad ser I?

.visually-hidden

.visually-hidden {
  border: 0;
  clip-path: inset(50%);
  height: 1px;
  margin: 0;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}

.visually-hidden

.visually-hidden {
  border: 0;
  clip-path: inset(50%);
  height: 1px;
  margin: 0;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}
<button>
  <span class="fa fa-tweet" aria-hidden="true"></span>
  <span class="label"> Tweet </span>
</button>

aria-hidden="true"

Skjul for UI

Skjul for Skærmlæser

Hvad hedder knappen?

accName

<button>
	Add <span class="visually-hidden">[ PRODUCT_NAME ]</span> to Cart
</button>
<button>
	Add to Cart <span class="visually-hidden">, [ PRODUCT_NAME ]</span>
</button>

<a href="/path/to/article-title/">Læs mere</a>



<a href="/path/to/article-title/">
  Læs mere <span class="visually-hidden">om [ ARTIKELNAVN ]</span>
</a>

Sammensatte navne

Hvornår er noget dekorativt?

Analyse

Live-opdateringer

<p role="status"></p>

Lav anden del:

Accessible names, states, billedalternativer og status

Opgave, del 2

Øvelse

IT-hjælpemidler* er afhængige af semantik for at præsentere information samt for at skabe en grænseflade til navigation for brugeren.

* Assistive technologies, såsom skærmlæsere

HTML

At vælge semantiske HTML-elementer er ikke altid nok...

Og CSS kan endda påvirke semantikken...

ul {
  list-style: none;
}

HTML-semantik påvirkes også af
ARIA-attributter

<button
  aria-expanded="true"
  aria-controls="panel">
  Open
</button>

Og kan tilføre semantik til generiske elementer, såsom div og span

<div role="button">
  Open
</div>

Hvordan et element annonceres af en skærmlæser afhænger af den browser, platform og skærmlæserkombination, som brugeren anvender.