18.1 Keyboard accessibility: Designing accessible focus indicators

Eine Navigation mit dem Keyboard ohne richtigen Fokus ist wie Surfen ohne Maus: das funktioniert überhaupt nicht. Man sieht nicht, wo man ist, und wenn zufällig ein Widget bei :hover aufgeht, weiß man nicht, wo es dazugehört.

Was genau ist ein Focus-Indicator?

Keyboard-User (und das beinhaltet alle User, die ein Keyboard auch nur indirekt nutzen) surfen mit der Tab-Taste durch die Seite. So können sie von einem interaktiven Element zum nächsten springen. Sie müssen aber, genauso wie Mausbenutzer, sehen, wo sie sich befinden, ansonsten können sie nicht mit interaktiven Elementen interagieren. Ein Focus-Indicator hebt das aktuell fokussierte Element hervor, standardmäßig mit einer Outline.
Browser liefern normalerweise eine Fokusanzeige mit. Es ist aber meistens sinnvoll, diese Anzeige zu überschreiben. Um barrierfrei zu sein, muss diese deutlich sichtbar sein, und manchmal schlägt sich die vom Browser mitgelieferte Anzeige mit dem Design.

WCAG 2.1 and 2.2 focus indicator accessibility requirements

Relevante Success Criteria

SC 2.4.7 Focus Visible (Level AA)
Any keyboard operable user interface has a mode of operation where the keyboard focus indicator is visible.
Niemals einen Focus Indicator verstecken!
SC 1.4.11 Non-text Contrast (Level AA)
The visual presentation of the following have a contrast ratio of at least 3:1 against adjacent color(s):
User Interface Components: Visual information required to identify user interface components and states, ...
SC 2.4.11 Focus Not Obscured (Minimum) (Level AA)
When a user interface component receives keyboard focus, the component is not entirely hidden due to author-created content.
SC 2.4.12 Focus Not Obscured (Enhances) (Level AAA)
When a user interface component receives keyboard focus, no part of the component is hidden by author-created content.
SC 2.4.13 Focus Appearance (Level AAA)
When the keyboard focus indicator is visible, an area of the focus indicator meets all the following:
  • is at least as large as the area of a 2 CSS pixel thick perimeter of the unfocused component or subcomponent, and
  • has a contrast ratio of at least 3:1 between the same pixels in the focused and unfocused states
...

1. The Focus indication area and the contrasting area

Wenn eine Komponente einen Focus Indicator erhält, bedeutet dieser Wechsel immer einen messbaren Wechsel des Farbkontrastes.
Die focus indication area entspricht der Fläche in Quadrat-CSS-Pixeln, wo der Farbwechsel zwischen unfokussiert und fokussiert passiert (bedeutet die Fläche unter dem Fokusring).
Die Fläche der focus indication area, die einen Minimalkontrast von 3:1 zwischen fokussiert und unfokussiert aufweist, ist die contrasting area. Beide können sich überlappen. Auch wenn ein Outline-Offset gesetzt wird, gilt dieselbe Regel.
Wenn ein Fokus durch einen Gradient-Drop-Shadow angezeigt wird, gilt nur die Fläche als contrasting area, die den nötigen Kontrast aufweist. Diese ist dann kleiner als die focus indication area.

2. The minimum contrasting area

Je größer die sichtbare Änderung bei Fokus ist, desto leichter ist sie zu sehen. Daher gibt es eine Mindestgröße für die contrasting area: mindestens so groß wie die Fläche eines 2 CSS Pixel Umkreises um das unfokussierte Element. Der einfachste Weg ist, eine 2 Pixel starke, durchgehende Outline direkt um die Komponente zu legen. Eine 2 Pixel starke, dashed oder dottet Outline ist zuwenig. Eine 3 Pixel starke, durchgehende inner outline passt wieder.
Berechnung: 4 x Höhe + 4 x Breite

3. Minimum contrast against adjacent colors

Benachbarte Farben sind immer die, die an die Outline angrenzen. Wenn die Outline mit einem Offset außerhalb der Komponente liegt, ist die benachbarte Farbe die Farbe, die die Komponente umgibt. Wenn die Outline innerhalb der Komponente liegt, ist die benachbarte Farbe die Hintergrundfarbe der Komponente. Wenn die Outline die Komponente umschließt, grenzen zwei Farben an die Outline an (Hintergrund, auf dem die Komponente liegt und Hintergrund der Komponente selbst).

4. The focused element cannot be obscured

SC 42.4.11 (Fokus teilweise überdeckt) sollte im Sinne einer guten Usability vermieden werden und nur SC 42.4.12 (Fokus nicht überdeckt) berücksichtigt werden.

Standard-Fokusanzeige im Browser

Interessanterweise werden die standardmäßigen Fokusanzeigen in den verschiedenen Browsern als gültig eingestuft, selbst wenn sie die Kriterien bezüglich Kontrast gar nicht erfüllen. Darüber hinaus können diese vom User verändert werden, somit geht die Kontrolle völlig verloren. Das ist ein weiteres Beispiel für WCAG conformance does not guarantee usability.

Eine universelle Fokus-Anzeige

Eine Kombination aus zwei Outlines – eine weiß, eine schwarz – funktioniert bei allen Farbkombinationen. Eine davon passt immer. Zwei Outlines können wir (noch?) nicht kombinieren, daher behelfen wir uns mit einem Box-Shadow (Outlines überschreiben box-shadow):

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

Wenn die fokussierbaren Komponenten auf der Website hauptsächlich dunkel sind, können Outline und Shadow-Farbe auch getauscht werden. Die weiße Outline kontrastiert somit noch besser mit der Komponente.

Oreo-Outline

:focus-visible {
  outline: 0.375rem double black;
  box-shadow: 0 0 0 0.25rem white;
  border-radius: 0.125rem;
}

Fokusanzeige nur für Keyboard-User

Browser machen das heute by default, wir machen das mit dem :focus-visible-Selektor. Für die bestmögliche Rückwärtskompatibilität geht's noch besser (Patrick Lauke):

:focus {
/* some exciting button focus styles */
}
:focus:not(:focus-visible) {
/* undo all the above focused button styles */
/* if the button has focus but the browser wouldn't normally
show default focus styles */
}
:focus-visible {
/* some even *more* exciting button focus styles */
}

»Wenn der Button Fokus erhält der nicht focus-visible ist - d.h., wenn der Button einen Fokus erhält, der kein Keyboard-Fokus ist – dann wirf alle Fokus-Styles weg und wende nur Keyboard-only Fokus Styles an.«
Das funktioniert auch in Browsern, die :focus-visible nicht unterstützen, weil sie den Part mit :focus-visible nicht verstehen und daher einfach ignorieren.

Links