CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-postcss-focus-within

PostCSS plugin that transforms CSS :focus-within pseudo-selectors with browser polyfill support

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

browser-polyfill.mddocs/

Browser Polyfill

The browser polyfill provides :focus-within behavior in browsers that don't support the native pseudo-class by dynamically applying attributes or classes to elements when their descendants receive focus.

Capabilities

Polyfill Initialization Function

Initializes the focus-within polyfill in the browser environment. The polyfill detects browser support and only activates if needed (unless forced).

/**
 * Initialize the focus-within polyfill in the browser
 * @param options - Polyfill configuration options
 */
function focusWithin(options?: BrowserOptions): void;

interface BrowserOptions {
  /** Force polyfill to run even if browser supports :focus-within. Default: false */
  force?: boolean;
  /** The replacement selector (class or attribute). Default: "[focus-within]" */
  replaceWith?: string;
}

Usage Examples:

import focusWithin from "postcss-focus-within/browser";

// Basic initialization with default options
focusWithin();

// Force polyfill to run regardless of browser support
focusWithin({ force: true });

// Use custom replacement selector
focusWithin({ replaceWith: ".focus-within" });

// Combined options
focusWithin({ 
  force: false, 
  replaceWith: "[data-focus-within]" 
});

Global script usage:

Note: When using the global script, the function is available as focusWithinInit (not focusWithin).

<script src="https://unpkg.com/postcss-focus-within@9.0.1/dist/browser-global.js"></script>
<script>
  focusWithinInit({ replaceWith: "[focus-within]" });
</script>

Polyfill Options

force

Controls whether the polyfill runs even when the browser natively supports :focus-within.

force?: boolean; // Default: false

Usage:

// Only run if browser lacks support (default)
focusWithin({ force: false });

// Always run polyfill
focusWithin({ force: true });

replaceWith

Specifies the attribute or class to apply to elements when they contain focused descendants. Must match the replaceWith option used in the PostCSS plugin.

replaceWith?: string; // Default: "[focus-within]"

Supported formats:

// Attribute selector (default)
focusWithin({ replaceWith: "[focus-within]" });

// Class selector
focusWithin({ replaceWith: ".focus-within" });

// Custom attribute
focusWithin({ replaceWith: "[data-focus]" });

Polyfill Behavior

Automatic Browser Detection

The polyfill automatically detects browser support by attempting to use document.querySelector(':focus-within'). If this throws an error, the polyfill activates.

try {
  document.querySelector(':focus-within');
  // Browser supports :focus-within, polyfill won't run (unless forced)
} catch (error) {
  // Browser doesn't support :focus-within, polyfill will run
}

DOM Ready Handling

The polyfill handles various document ready states:

if (document.readyState === 'complete') {
  // Initialize immediately
} else {
  // Wait for DOMContentLoaded event
  document.addEventListener('DOMContentLoaded', initialize);
}

Focus Event Management

The polyfill manages focus state by listening to focus and blur events:

// Event listeners are attached with capture: true
document.addEventListener('focus', handleFocusChange, true);
document.addEventListener('blur', handleFocusChange, true);

Element State Management

When focus changes, the polyfill:

  1. Removes the replacement selector from all previously focused ancestor elements
  2. Identifies the currently focused element
  3. Applies the replacement selector to the focused element and all its ancestors (excluding document, HTML, and BODY)

Example behavior:

<!-- Before focus -->
<form class="my-form">
  <fieldset class="fieldset">
    <input type="text" id="name">
  </fieldset>
</form>

<!-- After focusing input with replaceWith: "[focus-within]" -->
<form class="my-form" focus-within>
  <fieldset class="fieldset" focus-within>
    <input type="text" id="name">
  </fieldset>
</form>

Polyfill Ready Class

The polyfill automatically adds the js-focus-within class to the document element to indicate it's active:

document.documentElement.className += ' js-focus-within';

This class is used by the PostCSS plugin to scope fallback selectors and prevent flash of unstyled content.

Error Handling

The polyfill validates the replaceWith option and throws an error for invalid selectors:

// These will throw errors:
focusWithin({ replaceWith: ".class > .child" }); // Contains >
focusWithin({ replaceWith: "[attr]:hover" });    // Contains :
focusWithin({ replaceWith: "#id" });             // Contains #

Error example:

try {
  focusWithin({ replaceWith: "#invalid" });
} catch (error) {
  console.error(error.message); 
  // "#invalid is not a valid replacement since it can't be applied to single elements."
}

Framework Integration

Next.js Integration

For Next.js applications, use dynamic imports to ensure the polyfill only runs in the browser:

import { useEffect } from 'react';

useEffect(async () => {
  const focusWithin = (await import('postcss-focus-within/browser')).default;
  focusWithin();
}, []);

Install with Tessl CLI

npx tessl i tessl/npm-postcss-focus-within

docs

browser-polyfill.md

index.md

postcss-plugin.md

tile.json