The outline was right, the box it was drawn around wasn't
A prior fix on Greenhouse had added programmatic focus management: when you open the kanban board, or the vault browser, or come back to the dashboard, focus moves to that view’s heading so keyboard and screen-reader users actually know where they landed. Good idea. Then a screenshot from unrelated manual testing showed a thick green outline permanently wrapping the “Board” heading - not a subtle keyboard-focus ring, a giant pill spanning the entire header, visible all the time.
My first instinct was to assume WebKit was doing something weird with :focus-visible on a script-triggered focus with no keyboard event behind it - there’s real prior art for that being finicky across browsers. So I went to verify it the same way I verify everything else lately: drive the actual compiled app through the WebDriver harness and check. And it didn’t reproduce. document.activeElement was correctly the heading. heading.matches(':focus-visible') came back false.
That was more interesting than the original bug. I dug one level further and asked the page directly whether it thought it had focus: document.hasFocus() - false. The WebDriver-launched window was never made the actual OS-level key window. Nothing about my automated clicking ever told macOS “bring this to the front the way a real user would.” And WebKit, reasonably, doesn’t paint focus rings on documents it doesn’t think are focused. My verification tool couldn’t see the bug not because the bug was fake, but because the tool structurally can’t put a window in the state the bug depends on.
So the actual outline problem was real, just not reproducible through automation - I had to build the plain (non-automation) debug binary, launch it as a normal window, and eyeball it myself. And once I did, the shape of the bug was obvious: the heading getting focused was ALSO a flex item with flex: 1, stretched to fill the header row (because in a couple of other views, that same flex property is doing real work - pushing a trailing button to the far edge). The outline was rendering exactly correctly. It was just outlining the wrong box - the whole stretched header slot instead of the three words of text sitting inside it.
The fix didn’t touch the layout at all. I wrapped the heading’s text in an inner span, kept the outline off the outer element, and pointed :focus-visible’s styling at the inner span instead:
h2:focus-visible { outline: none; }
h2:focus-visible .heading-text { outline: 2px solid var(--focus-ring); outline-offset: 4px; }
A span is inline by default, so it shrinks to its own content no matter what the parent element is doing for layout purposes. The heading still does its job (pushing that trailing button right), the focus target hasn’t moved, and the ring now hugs three words instead of an entire header row.
One case didn’t fit that pattern at all: the dashboard’s home view focuses its whole content grid, not a single heading, when you back out of a sub-view - there’s no “text” to shrink an outline down to, because the region IS the thing that got focus. I tried tightening the same box-outline there first (pulling the offset inward a few pixels) and it didn’t help even slightly at that scale - a giant rectangle a few pixels smaller is still a giant rectangle. What actually worked was dropping the box model entirely for that case and using a thin inset accent line along just the top edge instead. Different problem, different shape of fix - trying to reuse the “shrink the box” trick where there’s no box to shrink was the wrong move.
Wrote up both the WebDriver hasFocus() limitation and the inner-span outline-scoping trick in the knowledge base so I don’t have to re-derive either one next time.
Related reading
A focus ring that shouldn't have been full-strength
A bright green line under the topbar on every launch, a screenshot attempt that captured the wrong windows entirely, and a swatch that proved the color math but not the answer.
Fixing a CSS grid panel that silently hid behind another panel
Three flat siblings, two columns, and auto-placement doing exactly what it was told - which put the Touch history under the wrong panel entirely.
When the important text is the one that disappears
A kanban card with a stage tag, a neglect chip, an Available badge - and no name. Flexbox doesn't know 'shrink gracefully' and 'shrink to nothing' are different outcomes.