CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-postcss-focus-visible

PostCSS plugin that transforms :focus-visible pseudo-class selectors into compatible class-based selectors for cross-browser support

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

PostCSS Focus Visible

PostCSS Focus Visible is a PostCSS plugin that transforms :focus-visible pseudo-class selectors into compatible class-based selectors for cross-browser support. It implements the CSS Selectors Level 4 specification for :focus-visible, providing better accessibility by distinguishing between keyboard and mouse focus states.

Package Information

  • Package Name: postcss-focus-visible
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install postcss-focus-visible --save-dev

Core Imports

ES Modules (preferred):

import postcssFocusVisible from "postcss-focus-visible";

For TypeScript with options:

import postcssFocusVisible, { pluginOptions } from "postcss-focus-visible";

CommonJS:

const postcssFocusVisible = require("postcss-focus-visible");

Basic Usage

The plugin transforms :focus-visible selectors into class-based equivalents that work with the focus-visible polyfill:

const postcss = require('postcss');
const postcssFocusVisible = require('postcss-focus-visible');

postcss([
  postcssFocusVisible()
]).process(yourCSS);

Input CSS:

:focus:not(:focus-visible) {
  outline: none;
}

Output CSS (with default options):

:focus:not(.focus-visible).js-focus-visible, .js-focus-visible :focus:not(.focus-visible) {
  outline: none;
}
:focus:not(:focus-visible) {
  outline: none;
}

Capabilities

Main Plugin Function

Creates a PostCSS plugin instance with optional configuration.

/**
 * Creates a PostCSS plugin that transforms :focus-visible pseudo-selectors
 * @param opts - Optional plugin configuration
 * @returns PostCSS plugin instance
 */
function postcssFocusVisible(opts?: pluginOptions): PostCSS.Plugin;

The plugin automatically:

  • Detects :focus-visible pseudo-classes in selectors
  • Replaces them with configurable class selectors (default: .focus-visible)
  • Adds polyfill-ready class prefixes for compatibility (default: .js-focus-visible)
  • Preserves original selectors alongside transformed ones (configurable)

Configuration Options

Plugin behavior can be customized through the options parameter.

interface pluginOptions {
  /** Preserve the original notation. default: true */
  preserve?: boolean;
  /** The replacement class to be used in the polyfill. default: ".focus-visible" */
  replaceWith?: string;
  /** Disable the selector prefix that is used to prevent a flash of incorrectly styled content. default: false */
  disablePolyfillReadyClass?: boolean;
}

preserve (boolean, default: true)

  • true: Keeps both original and transformed selectors in output
  • false: Removes original selectors, leaving only transformed ones

Example with preserve: false:

postcssFocusVisible({ preserve: false })

Input:

:focus:not(:focus-visible) {
  outline: none;
}

Output:

:focus:not(.focus-visible).js-focus-visible, .js-focus-visible :focus:not(.focus-visible) {
  outline: none;
}

replaceWith (string, default: ".focus-visible")

Defines the replacement selector for :focus-visible. Must be compatible with the focus-visible polyfill if used.

Example with custom replacement:

postcssFocusVisible({ replaceWith: '[data-focus-visible-added]' })

Input:

:focus:not(:focus-visible) {
  outline: none;
}

Output:

:focus:not([data-focus-visible-added]).js-focus-visible, .js-focus-visible :focus:not([data-focus-visible-added]) {
  outline: none;
}
:focus:not(:focus-visible) {
  outline: none;
}

disablePolyfillReadyClass (boolean, default: false)

Controls whether selectors are prefixed with the polyfill-ready class (.js-focus-visible). The polyfill-ready class ensures styles only apply when the polyfill is loaded and active.

Example with disabled polyfill-ready class:

postcssFocusVisible({ disablePolyfillReadyClass: true })

Input:

:focus:not(:focus-visible) {
  outline: none;
}

Output:

:focus:not(.focus-visible) {
  outline: none;
}
:focus:not(:focus-visible) {
  outline: none;
}

Plugin Properties

The plugin function includes standard PostCSS plugin properties.

/**
 * PostCSS plugin flag indicating this is a valid PostCSS plugin
 */
postcssFocusVisible.postcss: true;

Integration Patterns

With PostCSS CLI

npx postcss src/*.css --use postcss-focus-visible --dir dest

With Webpack and postcss-loader

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  require('postcss-focus-visible')()
                ]
              }
            }
          }
        ]
      }
    ]
  }
};

With PostCSS Load Config

Create a postcss.config.js file:

module.exports = {
  plugins: [
    require('postcss-focus-visible')({
      preserve: true,
      replaceWith: '.focus-visible'
    })
  ]
};

Polyfill Integration

This plugin is designed to work with the focus-visible polyfill. The polyfill should be included in your JavaScript bundle:

npm install focus-visible
import 'focus-visible';

The polyfill automatically:

  • Adds the .js-focus-visible class to the document when loaded
  • Manages the .focus-visible class on focused elements based on focus method
  • Provides consistent behavior across all browsers

Error Handling

The plugin includes built-in error handling for malformed selectors:

  • Invalid CSS selectors are logged as warnings and left unchanged
  • Malformed :focus-visible pseudo-classes are skipped
  • Processing continues for valid selectors even if some fail to parse

Browser Compatibility

  • Modern browsers: Native :focus-visible support (Chrome 86+, Firefox 85+, Safari 15.4+)
  • Legacy browsers: Requires focus-visible polyfill for full functionality
  • Node.js: Requires Node.js 18+ (as specified in package engines)

Dependencies

  • postcss-selector-parser: CSS selector parsing and manipulation (runtime dependency)
  • postcss: PostCSS framework (peer dependency ^8.4)
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/postcss-focus-visible@10.0.x
Publish Source
CLI
Badge
tessl/npm-postcss-focus-visible badge