Repository navigation
Web HIG tip #10: Keep focus visible #25
frozonfreak
started this conversation in
General
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Press Tab on your own site. If you can't tell where you are after two or three presses, neither can anyone who navigates by keyboard. Somewhere in the CSS, a focus ring was switched off and nothing replaced it.
Web HIG tip #10 (Quick #72 / HIG-A11Y-006): Focus must be visible on every interactive element — never
outline: nonewithout a custom ring.Why it matters
The focus ring is the keyboard user's cursor:
outline: noneis often added to stop the ring showing on mouse clicks, and that also hides it from everyone who needs itThe full HIG (§5.3, Keyboard Focus & Interaction) requires an explicit, high-contrast indicator on every interactive control. The ring must contrast with what's next to it and must not be hidden by other elements. §5.1 sets the contrast floor for focus indicators at 3:1, the figure from WCAG 1.4.11 Non-text Contrast (AA); Quick #62 is the companion rule. On the WCAG side, this builds on 2.4.7 Focus Visible and 2.4.11 Focus Not Obscured (Minimum), both Level AA in WCAG 2.2. WCAG's minimum only asks that the focused element isn't completely hidden; the HIG asks for more and keeps the ring itself uncovered.
The rule of thumb
Ask: if I unplug the mouse, can I always see where I am?
If you removed the default ring, put a better one back.
Delete the
outline: nonerule rather than adding a ring next to it.button:focusis more specific than:focus-visibleand will still win.:focus-visiblelets the browser decide when a ring helps. It shows for keyboard focus and usually not for a mouse click on a button, which is what most people wanted fromoutline: nonein the first place. Text fields still show it on click, because you need to know where you're typing.If a sticky header covers whatever is focused, leave room for it:
Match it to the header's real height (a custom property helps), and use
scroll-padding-bottomfor bottom bars and cookie banners.Do this instead
outline: noneandoutline: 0unless a visible ring still applies on keyboard focus (for example, suppress only with:focus:not(:focus-visible)and style:focus-visible).:focus-visiblewith one shared focus-ring color (a CSS custom property works well), so it's contrast-checked once, in light and dark modeoutlinetobox-shadowfor the ring: Windows high-contrast (forced colors) mode drops box shadows, so a shadow-only ring can vanish. If you keep a box-shadow ring, addoutline: 2px solid transparentas well. Forced colors mode repaints it in a visible system color.outline-offsetso the ring isn't lost against a button's own border or backgroundQuick check for your app
Put the mouse aside and Tab through a whole page, including a menu, a dialog, and a form. At every stop, you should see where focus is without hunting for it, and, as the HIG asks, nothing should sit on top of the ring. Then repeat in dark mode. A tool can find
outline: nonein your CSS, but only tabbing through tells you whether people can actually see where they are.The Web HIG is an open set of guidelines for how the web should behave, not a component library. Design systems define how it looks. The Web HIG defines how it behaves.
All reactions