With the outline set to none on :focus, a mouse click draws nothing but a Tab key leaves no ring, failing WCAG 2.2 criterion 2.4.7. With :focus-visible and a 2px outline offset, the click skips the ring and a Tab key press shows it.

focus vs focus-visible in CSS: the rules, the ring, and :focus-within

The ring that flashes on every click and the ring that vanishes for keyboard users have one cause. The browser already decides when focus should show, and the right selector lets you follow that choice.

Focus vs focus-visible in CSS: what is the actual difference?#

:focus matches every focused element, while :focus-visible matches only when the browser decides a focus indicator would help, so a mouse click on a button skips the ring.

The W3C Selectors Level 4 draft of 22 January 2026 says it plainly. While :focus always matches, "UAs only sometimes visibly indicate focus" and use heuristics to show it when it helps. In CSS focus vs focus-visible terms, the second matches the same element in those moments only. As a result, you change how the ring looks without changing when it appears. That is the whole difference between focus and focus-visible.

:focus against :focus-visible: when each matches. Source: W3C Selectors Level 4, 22 January 2026.

Pseudo-classWhen it matchesA mouse click on a button
:focusEvery focused elementMatches
:focus-visibleOnly when the browser decides a focus indicator would helpSkips the ring

What does getting the focus ring wrong cost a product?#

A ring styled on :focus flashes after every mouse click, and removing it to stop the flash leaves keyboard users unable to see where they are.

The second outcome is the expensive one. WCAG 2.2 success criterion 2.4.7, Focus Visible, is Level AA. The rule is one line on W3C's Understanding page. "Any keyboard operable user interface has a mode of operation where the keyboard focus indicator is visible." So a stylesheet that removes the outline on :focus fails a criterion that audits test.

In practice, the fix for a cosmetic complaint blocks people who move by keyboard. So the selector decides whether they can finish a task at all.

DiagramHow removing a flashing :focus ring becomes a WCAG 2.2 SC 2.4.7 Level AA failure. Source: W3C WAI, Understanding SC 2.4.7 Focus Visible, WCAG 2.2.

When does a browser decide focus should be visible?#

Browsers show focus for keyboard navigation, for any control that takes typed text, and for script focus that follows a visible focus, and they hide it after a pointer click.

The rules come from the non-normative list in W3C's Selectors Level 4 draft of 22 January 2026. First, a user preference to always see focus wins over everything. Second, an element that takes keyboard input, such as a text field, shows focus even after a click. Then a pointer click on a button does not show it. If focus showed and a script moves it, the draft says to "indicate focus on the newly focused element".

The event-by-pseudo-class matrix. Source: W3C Selectors Level 4, 22 January 2026.

Event:focus:focus-visible:focus-within on the parent:active
Tab keyMatchesMatchesMatchesNo
Mouse click on a buttonMatchesNoMatchesDuring the press
Mouse click into a text inputMatchesMatchesMatchesDuring the press
Script focus after a visible focusMatchesMatchesMatchesNo
Script focus after a hidden focusMatchesNoMatchesNo
A dialog button that gains focus on openMatchesMatchesMatchesNo

The MDN :focus-visible page, updated 10 September 2026, shows the split in a demo. Click a button styled on :focus and the ring appears, but the same click on :focus-visible draws nothing. Also, the draft asks browsers to "use :focus-visible to specify the default focus style". So you need not disable a default :focus ring.

What does :focus-within match, and how is it different from :focus?#

:focus-within matches an element when it or any descendant has focus, so a form group or a menu can restyle itself while focus sits on a child control.

It exists because of one rule in Selectors Level 4: "the :focus pseudo-class must not automatically propagate to the parent element". So a fieldset never matches :focus when its input does. That is the whole answer to CSS focus vs focus-within. In short, :focus sits on the focused element, and :focus-within sits on it and on every ancestor.

For example, the MDN :focus-within page, updated 10 September 2026, colours a whole form when its input takes focus. The same pattern lights up a card or a dropdown menu while you move through its items. However, :focus-within ignores how focus arrived. A mouse click into a field lights the group just as a Tab key does.

Show data table
first versions with :focus-within, Can I use, October 2026
Item Value
Chrome 60
Edge 79
Firefox 52
Safari 10.1

:focus-within shipped in Chrome 60, Edge 79, Firefox 52 and Safari 10.1.

First version with :focus-within first versions with :focus-within, Can I use, October 2026 Can I use, October 2026

Should a form group use :focus-within or :has(:focus-visible)?#

:focus-within reacts to any focus inside the group, mouse clicks included, while :has(:focus-visible) reacts only when the focused child shows a ring.

No :focus-visible-within selector exists. A CSS Working Group issue, number 3080, asks "Do we need :focus-visible-within" and is still open. Meanwhile, :has(:focus-visible) does the job today. It matches the group only when a child matches :focus-visible, so a click on a button leaves the group plain.

That choice has a cost. The MDN :has() page, updated 11 August 2026, warns that browsers "must re-evaluate :has() selectors when the DOM changes". So anchor it to a small container class, never to body or :root. Use :focus-within when any focus should light the group, and :has(:focus-visible) when only keyboard focus should.

DiagramChoosing between :focus-within and :has(:focus-visible) for a container. Source: W3C Selectors Level 4, 22 January 2026; MDN :has(), 11 August 2026.
Show data table
first versions with :has(), Can I use, October 2026
Item Value
Chrome 105
Edge 105
Firefox 121
Safari 15.4

:has() shipped in Chrome 105, Edge 105, Firefox 121 and Safari 15.4.

First version with :has() first versions with :has(), Can I use, October 2026 Can I use, October 2026

How is :focus different from :active in CSS?#

:active applies only while a pointer is held down or a link is being triggered, while :focus stays on the element after release until focus moves elsewhere.

W3C's Selectors Level 4 times :active "between the time the user presses the primary mouse button and releases it". By contrast, :focus applies while the element "accepts keyboard or other forms of input". So in the focus vs active CSS question, a clicked button matches both during the press, and then only :focus.

Because a style on :active vanishes on release, it cannot mark a selected item. So use :active for a pressed look, and :focus-visible for a ring.

  1. Press the primary mouse button on a button.

    :active matches between the time the user presses the primary mouse button and releases it, and :focus matches too.

  2. Release it.

    :active stops matching, and :focus stays on the button.

  3. Click elsewhere.

    Focus moves to another element, so :focus leaves the button as well.

Which references should the focus styles be built from?#

Build from MDN's :focus-visible page first, then its :focus-within page, then its :has() page for the keyboard-only group variant.

  1. :focus-visible on MDN: the global ring rule and the outline-offset example.
  2. :focus-within on MDN: the container rule for a form group.
  3. :has() on MDN: the keyboard-only group variant and its performance notes.

Then keep the Selectors Level 4 draft open, since it defines every rule the three pages use.

What is the smallest focus ring CSS that works in every engine?#

Style :focus-visible with a solid outline and an offset, never remove the outline on :focus, and add a :focus-within rule for groups that should light up.

css
/* Step 1 and 2: one ring colour, one ring rule for every control */
:root {
  --focus-ring: #1d4ed8;
}

:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

/* Step 3: a form group that lights up while any field inside has focus */
.field-group:focus-within {
  background-color: #eef2ff;
}

/* Step 4: a menu that lights up only when its focused item shows a ring */
.menu:has(:focus-visible) {
  outline: 2px solid var(--focus-ring);
}

This focus-visible CSS runs as written, with no build step. Note what it leaves out: no :focus rule and no outline set to none. Since the browser already draws its default ring with :focus-visible, a rule on :focus only brings the click flash back.

How large does a focus ring have to be under WCAG 2.2?#

W3C's WCAG 2.2 Focus Appearance guidance, accessed October 2026, sets a minimum area of a 2 CSS pixel perimeter, which is 480 square pixels on a 90 by 30 button.

That criterion, 2.4.13, is Level AAA, so it is a target rather than an audit floor. The Understanding page gives the area for a rectangle as 4h + 4w. It also asks for a 3:1 contrast change in those pixels. So the ring grows with the control, and a thin line can fail on a wide input.

Min area4h4w
Show data table
arithmetic from the 4h + 4w formula, W3C WAI, Understanding SC 2.4.13, WCAG 2.2
Item Value
90 by 30 button (W3C example) 480
120 by 40 button 640
200 by 48 button 992
320 by 48 text input 1,472

The minimum area grows with the control, so a wide input needs more ring than a small button.

Minimum focus indicator area, square CSS pixels arithmetic from the 4h + 4w formula, W3C WAI, Understanding SC 2.4.13, WCAG 2.2 W3C WAI, Understanding SC 2.4.13 Focus Appearance, WCAG 2.2

Here is a worked example on that button. A 2px outline drawn flush outside it covers 94 by 34 minus 90 by 30. That illustrative total is 496 square pixels, so it passes. But a 1px outline covers 92 by 32 minus 90 by 30. That illustrative total is 244 square pixels, so it fails.

Does your outline cover the WCAG 2.2 minimum area?

Enter a control's width and height and the outline width to compare the area a solid outline covers with the 4h + 4w minimum.

Your control and its ring

an assumption, change it

Assumes a solid rectangular outline drawn flush outside the control; SC 2.4.13 also asks for a 3:1 contrast change in those pixels.

Outline area minus the minimum (zero or more passes)

16

W3C minimum area, 4h + 4w (square CSS px)
480
Area the outline covers (square CSS px)
496

Defaults: W3C's 90 by 30 button with a 2px outline, from Understanding SC 2.4.13, WCAG 2.2. Modelled, not measured.

Also check criterion 2.4.11, which is Level AA. The Focus Not Obscured page requires that the focused component "is not entirely hidden due to author-created content". A sticky header is the usual culprit.

Is :focus-visible safe to use without a fallback?#

Can I use, accessed October 2026, lists :focus-visible support from Chrome 86, Firefox 85 and Safari 15.4, so the selector needs no fallback today.

The release notes agree. Chrome 86 shipped it in October 2020, then Firefox 85 in January 2021 and Safari 15.4 in March 2022. So :focus-visible is now a native feature in every engine, not a polyfill.

Show data table
first versions with :focus-visible, Can I use, October 2026
Item Value
Chrome 86
Edge 86
Firefox 85
Safari 15.4

:focus-visible shipped in Chrome 86, Edge 86, Firefox 85 and Safari 15.4.

First version with :focus-visible first versions with :focus-visible, Can I use, October 2026 Can I use, October 2026

That retires an old pattern, since the Chrome 86 notes paired a :focus rule with :focus:not(:focus-visible) to undo the ring. Today that pair adds selectors and no benefit, so delete it.

When is :focus-visible the wrong tool?#

:focus-visible is the wrong tool for a container, for a state that must persist after a click, and for styling that must follow every focus, where :focus-within, a class or :focus fits.

First, a container never matches :focus-visible itself, so a form group needs :focus-within or :has(:focus-visible). Second, a selected tab must stay marked after the click. Only a class or an ARIA state such as aria-selected does that. Finally, some styling should follow every focus, such as hint text in a search field. Use :focus there, since a hint that hides on click fails the person who clicked. But keep the ring itself on :focus-visible.

Where :focus-visible is the wrong tool, and what fits instead. Source: W3C Selectors Level 4, 22 January 2026; MDN :focus-within.

CaseWhy :focus-visible missesWhat fits instead
A container such as a form groupA container never matches :focus-visible itself:focus-within or :has(:focus-visible)
A selected tabIt must stay marked after the clickA class or an ARIA state such as aria-selected
Hint text in a search fieldIt should follow every focus, a click included:focus

Where does focus work go after the ring is right?#

A correct ring is one half of keyboard access, and the other half is where focus moves, which the keyboard navigation guide covers next.

The keyboard navigation and focus management guide covers tab order, focus traps and focus after a route change. Then the colour contrast guide explains the 3:1 contrast a ring needs. And the accessible forms guide builds the fields a focus group wraps. For a full audit, see WCAG and ADA compliance work. For focus tokens shared across a product, see design systems. Still, the spec and the three MDN pages are enough on their own.

Questions this post answers

What is the difference between focus vs focus-visible in CSS?
:focus matches any focused element, while :focus-visible matches it only when the browser shows focus. A Tab key press shows it, and a click on a button does not.
What is the difference between :focus and :focus-within?
:focus matches only the focused element itself. But :focus-within matches that element and every ancestor, so a form can style itself while a child has focus.
Is :focus the same as :active in CSS?
No, because :active lasts only while a pointer is pressed. But :focus lasts until focus moves to another element.
Does :focus-visible work in Safari?
Yes, Safari has supported :focus-visible since version 15.4, released in March 2022, as WebKit's release notes record.

Keep reading