Et indblik
Braille
Webtilgængelighed
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
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
"...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
Understandable (forståelig)
Perceivable (opfattelig)
Operable (anvendelig)
Robust
Tilgængelighedsprincipper
Understandable (forståelig)
Perceivable (opfattelig)
Operable (anvendelig)
Robust
Tilgængelighedsprincipper
at billeder gøres opfattelige for skærmlæserprogrammer ved at tekstliggøre billederne
Understandable (forståelig)
Perceivable (opfattelig)
Operable (anvendelig)
Robust
Tilgængelighedsprincipper
at webstedet er anvendeligt for brugere, der bruger tastatur og ikke mus
Understandable (forståelig)
Perceivable (opfattelig)
Operable (anvendelig)
Robust
Tilgængelighedsprincipper
at webstedet er anvendeligt for brugere, der bruger tastatur og ikke mus
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
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
Dokumentation
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
Grupper
Kan alle betjene det — og se hvor de er?
Gå frem: ⇥ (Tab)
Gå tilbage: ⇧⇥ (Shift+Tab)
Aktivér: ↵ (Enter)
Tastatur og fokus
Hvilke udfordringer støder du på?
Gå frem: ⇥ (Tab)
Gå tilbage: ⇧⇥ (Shift+Tab)
Aktivér: ↵ (Enter)
Tastatur og fokus
Hvilke udfordringer støder du på?
Tab order
Skip links
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?
Kontrast
:focus-visible {
outline: 3px solid black;
box-shadow: 0 0 0 6px white;
}Hvad kan fokuseres?
<a href=""></a>
<input>
<select></select>
<textarea></textarea>
<button></button>
<iframe></iframe>
<div tabindex="0"></div> <!-- > 0 -->
<div style="overflow: auto;"></div> <!-- Måske --><div class="button" tabindex="0">Træls knap</div>Hvad kan fokuseres?
Tab-rækkefølgen
Firefox
Spring navigationen over
Spring navigationen over
<a href="#main" class="skip-links">Skip to main content</a>
<main id="main">…</main>Krav
mandatory
Omkring 20-30%
axe Accessibility Linter
DevTools
HTML elementer
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
Skærmlæsere kommunikerer via accessibility API (accessibility tree).
Der er tre typer ARIA attributter.
Role
Siger noget om elementets tilstand fx aria-checked, aria-pressed, aria-expanded.
State
Siger noget om en egenskab ved elementet fx aria-label, aria-labelledby, aria-haspopup, aria-level.
Property
<button
aria-expanded="false"
aria-controls="widget1">
Toggle widget
</button>fortæller om noget er åbent
fortæller, hvad der åbnes/lukkes
button.addEventListener("click", () => {
panel.hidden = !panel.hidden;
button.ariaExpanded = !panel.hidden;
});Toggle state
<button
command="show-modal"
commandfor=".."
interestfor="...">
Åben popover
</button>
<details>
<summary>Åben</summary>
...
</details>
Overskrifter, landmarks og komponenter
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>
Hierarki
Øvelse
Hierarki
span
Hierarki
Overskrifthierarki
Svar: Moderne webudvikling
function ProductCard({ product }) {
return (
<article>
<h2>{product.name}</h2>
<p>{product.price}</p>
</article>
);
}
<main>
<h1>Søgeresultater</h1>
<ProductCard product={vomero} />
</main>
✅
function ProductCard({ product }) {
return (
<article>
<h2>{product.name}</h2>
<p>{product.price}</p>
</article>
);
}
<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>
);
}
<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>
);
}
context
<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
sections mere semantiske end div'er?<body>
<main>
<section> <!-- er jeg semantisk? -->
</section>
</main>
</body>
Navigation via regioner
Typer af regioner
bannernavigationsearchmainregioncomplementaryformcontentinfoIndbygget i HTML-elementer
bannernavigationsearchmainregioncomplementaryformcontentinfo<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)
Indbygget i HTML-elementer
banner
complementary
main
region / form
contentinfo
navigation
sections semantiske?<body>
<main>
<section aria-label="Min region"> <!-- Nu er jeg -->
<h2>Overskrift</h2>
</section>
</main>
</body>
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!
<nav></nav>
Navngiv vigtige landmarks
Hvilken navigation?
<nav aria-label="Hovedmenu"></nav>
<nav aria-labelledby="breadcrumb">
<h2 id="breadcrumb">Brødkrumme</h2>
...
</nav>
Navngiv vigtige landmarks
"Hovedmenu navigation"
"Brødkrumme navigation"
Åbn "Opgave" fra repo og lav første del:
Headings, landmarks og disclosure-knap
Øvelse
Det synlige interface er ikke hele interfacet
Øvelse
.visually-hidden
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
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>✅
❌
Analyse
<p role="status"></p>Lav anden del:
Accessible names, states, billedalternativer og status
Øvelse
* Assistive technologies, såsom skærmlæsere
HTML
ul {
list-style: none;
}
<button
aria-expanded="true"
aria-controls="panel">
Open
</button>
<div role="button">
Open
</div>