focus-visible
A polyfill for the CSS :focus-visible pseudo-class, shown only for keyboard/assistive focus
Repository Health
Technical Analysis
focus-visible is a small JavaScript polyfill for the (now-standardized) CSS :focus-visible pseudo-selector. It adds a focus-visible class to an element whenever the browser determines the focus ring should be shown — for example after keyboard navigation — while leaving it off when focus was triggered purely by a mouse click, letting authors style keyboard-focus rings distinctly from mouse-focus without suppressing accessibility affordances entirely.
The project was developed under the W3C Web Incubator Community Group (WICG) alongside the :focus-visible spec itself and was widely adopted during the years before all major browsers shipped native support. As of the current README, :focus-visible is now supported natively across Chrome, Edge, Firefox, Safari, and their mobile equivalents, so the maintainers explicitly recommend using the native CSS selector where possible and are not planning further releases — the polyfill remains available and stable for projects that still need to support older browser versions or want a consistent fallback.
What You Get
- A
focus-visibleclass applied only when keyboard-driven or otherwise ‘visible-focus-worthy’ focus occurs - Heuristics based on keydown-then-focus sequences (Tab, Shift+Tab, arrow keys) and always-visible-focus form elements
- A
data-js-focus-visible/data-focus-visible-addedattribute mode for frameworks that overwrite element classes - An imperative
applyFocusVisiblePolyfill()API for applying the polyfill to Shadow DOM roots - A
focus-visible-polyfill-readyevent for coordinating lazy-loaded usage
Common Use Cases
- Suppressing mouse-click focus outlines while preserving them for keyboard navigation on older/legacy browser support matrices
- Providing a consistent focus-ring behavior across browsers before universal native
:focus-visiblesupport existed - Applying focus-visible-aware styling inside Shadow DOM components via the imperative API
- Defensive CSS fallback pattern (
.js-focus-visible :focus:not(.focus-visible)) for design systems supporting a broad browser matrix
Under The Hood
Architecture: The entire polyfill lives in a single ~300-line source file (src/focus-visible.js) that attaches global keydown/focus/blur/mousedown listeners at the document level, tracks a ‘had keyboard event’ flag, and toggles a focus-visible class (or data-focus-visible-added attribute) on the currently focused element based on that flag plus a whitelist of form-like input types that should always show a focus ring. A rollup.config.js bundles this single source file into the distributed dist/focus-visible.js / .min.js UMD-style build.
Tech Stack: Vanilla JavaScript with no runtime dependencies; Rollup handles bundling, ESLint and Prettier (via lint-staged) enforce style on commit, and the package ships as a plain UMD/CommonJS-compatible bundle consumed via a <script> tag or node_modules import.
Code Quality: There’s a dedicated test/ directory with specs and fixtures subdirectories exercising the focus-heuristic behavior, plus historical Travis CI integration (badge in README). The license is listed as W3C in package.json (the GitHub API reports NOASSERTION, i.e. no auto-detected SPDX license, since W3C’s license text isn’t a standard SPDX identifier) which is standard for WICG-incubated specs/polyfills. With 38 contributors and 270 total commits, the project saw active development during the years the spec was being finalized, but the maintainers have explicitly frozen new feature work now that :focus-visible ships natively everywhere.
API Design: For the common case there is no API at all — just include the script and add one CSS rule (.js-focus-visible :focus:not(.focus-visible) { outline: none; }) — making adoption essentially zero-boilerplate. The only exposed programmatic surface (window.applyFocusVisiblePolyfill() and the focus-visible-polyfill-ready event) exists solely for the Shadow DOM edge case, keeping the default integration path extremely simple.
Used by 4 apps in this directory
Forem
Community · Blogging
Open source Ruby on Rails platform for building developer communities with articles, discussions, and social profiles—the same software that powers dev.to.
GB Studio
Developer Tools · Game Development · Design Tools
Drag-and-drop retro Game Boy game creator that compiles real ROMs — no coding required.
Jitsi Meet
Team Chat · Collaboration · Video Conferencing
Open-source, end-to-end encrypted video conferencing you can self-host or embed into any web or mobile app.
Rivet
AI Agents · Developer Tools
Stateful actors as a primitive for AI agents, real-time collaboration, and durable execution — with in-memory state, WebSockets, queues, and scheduling built in.