Focus indicator checker

Check whether your focus ring passes WCAG, and fix it in one click.

Does your focus ring pass?

Measuring…

Across 6 controls on 4 backgrounds.

Passes AAthe usual target · WCAG 2.4.7, 1.4.11
Visible on every control, and at least 3:1 against what sits next to it.
Meets AAAenhanced · WCAG 2.4.13
Big and strong enough everywhere: at least 0% of the area WCAG asks for.

Nothing to fix. One rule for every link, button and field, ready to paste.

Button on Light#ffffff

Measuring…

Background

Your ring

Start from

Dark ring inside a white halo at 10:1, so one band contrasts with any solid background (WCAG technique C40).

Style

The two colours are 10.35:1 apart. That is enough for one of them to stand out on any plain background.

Below 0 draws it inside.

Test it further

In short

The answer comes first: whether your ring passes AA and AAA on six real controls over light, dark, brand and image backgrounds, with the reason taken from the worst case. Each control is painted unfocused and focused, and the pixels that change are measured: the area that changes by 3:1 or more against the 2 CSS pixel perimeter WCAG 2.4.13 asks for (AAA), and the ring against its neighbours for 1.4.11 (AA). If it fails, Fix it for me pairs your colour with a second one at 9:1 and thickens it if needed. Copy the CSS from the bar at the bottom: it uses :focus-visible and keeps the ring in Windows forced colours mode.

What focus indicator is

WCAG defines it as the pixels that change to show which control has keyboard focus — usually a ring drawn with outline or box-shadow. This tool designs one and measures it the way WCAG 2.2 measures it: the area that changes by at least 3:1 against a 2 CSS pixel perimeter (2.4.13), and the contrast with its neighbours (1.4.11).

What this tool does that others do not

  • The levels stated correctly

    Focus Appearance is 2.4.13 and Level AAA. Level AA rests on 2.4.7 Focus Visible and 1.4.11 Non-text Contrast, and 2.4.11 is Focus Not Obscured, which is about the control rather than the ring. Every result is labelled with the criterion and level it actually belongs to.

    “2.4.11 Focus Appearance (Minimum), AA, 1px perimeter or 4px shortest side” is the May 2021 working draft. The criterion became 2.4.13, AAA, in the candidate draft of 17 May 2023.

  • Change contrast measured on the same pixels

    2.4.13 compares each pixel before and after focus, not the ring against the page. The tool paints every control unfocused and focused over its real background and counts the area that changes by 3:1 or more, so a ring inside a filled button and a translucent ring are judged on what actually changes.

    A black border turning #555 on focus fails 2.4.13 with a 2.82:1 change, although #555 is 7.46:1 against white.

  • Six real controls on four backgrounds at once

    A button, a link, a text field, a checkbox, a card and a visually hidden input whose ring is drawn on its label are measured on light, dark, brand and image backgrounds, with their real sizes and radii read from the page. A two-colour ring that clears 9:1 between its colours passes on any solid background.

    Radix Themes’ default ring, #8da4ef, measures 2.42:1 on white: it fails 1.4.11 and 2.4.13 as shipped.

  • Forced colours and clipping checked, not assumed

    Box-shadow computes to none in forced colours mode, so every export carries a forced-colours rule, and the readout measures the ring that survives. A parent with overflow: hidden is detected from the page, and the ring it cuts off is subtracted before the verdict.

    Tailwind’s focus:ring utilities draw nothing in forced colours mode; the export’s outline keeps the full area.

How to use it

  1. Start from a ring

    Pick the two-colour ring, a solid outline, or load a design system’s ring to see how it measures. Every result updates as you change the ring.

  2. Read the answer

    The top of the tool says whether the ring passes AA and AAA on every control and background, with one line per level giving the reason from the worst case; "Show me" points the large preview at it. "Every control on every background" has each result, the area, the change contrast and the formula behind it.

  3. Fix the weakest background

    Press "Fix it for me" to pair the ring with a second colour at 9:1, thickened if it still fails anywhere, and Undo if you prefer your own. Or change Thickness and Gap until the area clears. Two colours guarantee nothing over a photo, which is why the image background is measured too.

  4. Set the page’s conditions, then export

    Under "Your page", add a clipping parent or a sticky header if your layout has them, then press Copy CSS or Tailwind in the bar at the bottom. "All code formats" has the one-class and custom-property versions.

Worked examples

Real input, real figures.

A design system ring on a 120 × 40 button

You give it

Primer’s 2px #0969da outline at offset −2px, on a dark button over white.

You get

601 px² changes by 3:1 against 613 px² for the perimeter formula. That is above the 600 px² of a 2px band flush inside the edge, which W3C’s own Figure 4 counts as passing, so the tool reports it as passing on the figure and under the formula.

One blue ring for a light and a dark theme

You give it

A 3px #1d4ed8 outline, 2px offset, on white and on #0f172a.

You get

On white the change is 6.70:1 and the area is 161% of what 2.4.13 needs. On #0f172a it is 2.66:1, so no pixel counts and AA fails too. With a white halo the same ring passes on both.

Against a typical focus-ring guide or colour checker

AspectdsynA typical guide or checker
What is measuredChanged pixels before and after focus, their area against the 2px perimeter, and adjacent contrastThe ring colour against one background
WCAG levels2.4.13 as AAA; AA as 2.4.7 plus 1.4.11Often the withdrawn 2.4.11 draft, called AA
BackgroundsLight, dark, brand and an image, at onceOne
Forced coloursFallback in every export, and measuredNot mentioned, or box-shadow only
ExportGlobal rule, one class, custom properties, Tailwind v4A snippet

Guide

What it will not do

  • It measures this page’s controls with your ring, not your site. Your own components can differ in size, radius and fill; set the backgrounds to yours and check the closest control.
  • Anti-aliased edges are ignored, as Note 3 of 2.4.13 allows, so a browser screenshot can count a few more or fewer pixels at rounded corners.
  • Focus Not Obscured (2.4.11) depends on your layout. The tool works out the scroll padding for a sticky header but cannot see your page’s other fixed layers.
  • Forced colours is simulated with one dark contrast theme. Windows lets people choose their own colours, so a system colour is used rather than a fixed one.

What WCAG 2.2 actually asks of a focus ring

Five success criteria touch focus, and they are often misquoted. Only one, 2.4.13, sets a size and a contrast figure for the indicator itself, and it is Level AAA. At Level AA a ring has to be visible (2.4.7) and reach 3:1 against what is next to it (1.4.11).

CriterionLevelWhat it requires
2.4.7 Focus VisibleAASome indicator is visible while a control has keyboard focus. No size or figure.
1.4.11 Non-text ContrastAAThe indicator reaches 3:1 against its adjacent colours: the background for a ring outside the control, the control for one inside.
2.4.11 Focus Not Obscured (Minimum)AAThe focused control is not entirely hidden by author content such as a sticky header. It tests the control, not the ring.
2.4.12 Focus Not Obscured (Enhanced)AAANo part of the focused control is hidden.
2.4.13 Focus AppearanceAAAAn area of the indicator as large as a 2 CSS px perimeter of the control changes by at least 3:1 between unfocused and focused.

The figures many guides still give — “2.4.11 Focus Appearance (Minimum)”, a 1 pixel perimeter or a 4 pixel shortest side, 4.5:1 for AAA — come from the May 2021 working draft. Focus Appearance was moved to 2.4.13 and Level AAA in the candidate draft of 17 May 2023, and WCAG 2.2 was published that October without the older text.

Change contrast is not ring contrast

2.4.13 compares each pixel with itself: its colour before the control took focus against its colour after. WCAG defines the focus indicator as the pixels that change, whatever CSS changed them. A checker that compares the ring’s colour with the page background is measuring 1.4.11 instead, and the two disagree whenever the ring sits inside a control, replaces a border or is translucent. A black border that turns #555 on focus is 7.46:1 against white, yet the pixels change by only 2.82:1, so it fails 2.4.13.

The area is a perimeter 2 CSS pixels thick: 4w + 4h for a rectangle, 4w + 4h − (16 − 4π)r for rounded corners, 480 px² for a 90 × 30 button. Only pixels that change by 3:1 count towards it. W3C’s own Understanding document also accepts a 2px line just inside the edge, which falls 16 px² short of the formula on square corners; where a ring lands in that gap, the tool says so rather than choosing a reading for you.

Design systems’ rings, measured

Each system’s published ring on a 120 × 40 button with an 8px radius: a dark button on a white page, and a light button on #0f172a. The figure is the strongest change any ring pixel makes. Values and versions are listed under “Design systems’ rings” in the tool, which loads each one; computed by the tool when this page was built.

SystemOn whiteOn #0f172aForced colours, as shipped
W3C C40AA pass · AAA pass · 13.38:1AA pass · AAA pass · 16.96:1Outline kept
PrimerAA pass · AAA on Fig. 4 · 3.44:1AA pass · AAA on Fig. 4 · 4.96:1Outline kept
CarbonAA pass · AAA on Fig. 4 · 3.57:1AA pass · AAA on Fig. 4 · 4.78:1Outline kept
MaterialAA pass · AAA pass · 6.45:1AA fail · AAA fail · 2.77:1Outline kept
RadixAA fail · AAA fail · 2.42:1AA pass · AAA pass · 7.39:1Outline kept
TailwindAA pass · AAA pass · 3.76:1AA pass · AAA pass · 17.85:1Nothing drawn

“AAA on Fig. 4” marks Primer’s and Carbon’s inset rings: they change slightly less than the formula’s area but more than the flush 2px line the Understanding document draws as passing.

outline, box-shadow and forced colours

Draw the ring with outline. It follows border-radius in every current browser (Chrome and Edge 94, Firefox 88, Safari 16.4), it is never clipped by its own box, and in forced colours mode — Windows contrast themes — the browser keeps it and recolours it. box-shadow computes to none there, so a shadow-only ring, including Tailwind’s ring utilities, leaves keyboard users with nothing. If you need a shadow for a second colour, keep an outline as well, or add outline: 2px solid transparent, which forced colours turns visible.

Use :focus-visible rather than :focus: it shows the ring for keyboard focus and for fields that take typing, and not on every mouse click. It has worked in Chrome since 86, Firefox since 85 and Safari since 15.4. Any parent with overflow hidden, auto or scroll cuts off a ring drawn outside the control, so give it padding at least as wide as the ring reaches, or draw the ring inside. For a colour pair that suits every solid background, pick two colours at 9:1 or more with each other; the contrast checker measures a pair, and the box shadow generator uses the same engine for edges and glass.