Focus Visibility

Standardizing Focus Styles

2.4.7: Focus Visible (AA) — keyboard operable interfaces must have visible focus indicators.

2.4.13: Focus Appearance (AAA) — criteria for developing clearly distinguishable focus indicators, requiring an indicator of at least 2px thick around the perimeter of the focused element with a 3:1 contrast ratio with the same pixels in the unfocused state.

The demo shows a technique to standardize and set consistent :focus-visible styles with customizable flexibility using custom properties.

Learn more about this technique (showing a slightly older technique, but explains the concepts behind the custom property setup).

CSS for "Focus Visibility"
:focus-visible {
  --outline-size: max(2px, 0.15em);

  outline: var(--outline-width, var(--outline-size)) var(--outline-style, solid)
    var(--outline-color, currentColor);
  outline-offset: var(--outline-offset, var(--outline-size));
}

.btn {
  --outline-color: purple;
  --outline-offset: 0.15em;
}

Default link

Handling "Focus Not Obscured"

2.4.11: Focus Not Obscured (Minimum) (AA) — when a UI component receives focus, the component is not entirely hidden due to author-created content.

2.4.12: Focus Not Obscured (Enhanced) (AAA) — when a UI component receives focus, no part of the component is hidden due to author-created content.

These techniques alter the scroll position for targeted or focused elements, which can help alleviate concerns for these criteria.

Using scroll-margin and scroll-padding properties, you can adjust the scroll position in relation to elements. The "padding" or "margin" space does not affect the layout, just the offset of the scroll position.

Scroll allowance above :target elements

In this rule, the :target selector matches when an element is a target of an anchor link, also known as a "document fragment." The scroll-margin-block-start will allow for room between the target and the top of the viewport.

:target {
  scroll-margin-block-start: 2rem;
}

Scroll allowance below :focus elements

The use of scroll-margin-block-end in this next rule allows for room between a focused element and the bottom of the viewport, which helps with tracking visible focus position.

:focus {
  scroll-margin-block-end: 8vb;
}

Use of the vb unit keeps the space contextual to the available viewport block size, aka it’s height.

While the browser will adjust the position and ultimately has the last word here, this alleviates the times that the adjustment by the browser still leaves the element snug against the bottom edge.

Resources on accessible focus styles

Check out my web app to learn more about creating accessible button color palettes, and to generate an accessible button palette.