Styleframe Logo
Modifiers

Pseudo-State Modifiers

Create pseudo-state modifiers for interactive states like hover, focus, active, and more with full type safety.
Part of the Modifiers Preset:usePseudoStateModifiers is included in the Modifiers Preset (useModifiersPreset) and you can configure it through the preset's pseudoStates option. For most projects, applying it via the preset is the recommended approach.

Overview

Pseudo-state modifiers let you apply utility styles conditionally based on user interaction states. They wrap utility declarations in CSS pseudo-class selectors like :hover, :focus, and :active, generating variant utility classes that respond to user behavior.

Why Use Pseudo-State Modifiers?

Pseudo-state modifiers help you:

  • Create interactive UIs: Apply styles when users hover, focus, or click on elements
  • Build accessible interfaces: Use focus-visible for keyboard-only focus indicators
  • Generate state variants: Automatically create hover, focus, and active versions of any utility
  • Keep styling declarative: Express interactive states directly in your HTML class names

useHoverModifier

The useHoverModifier() function creates a modifier that applies styles when the user hovers over an element.

styleframe.config.ts
import { styleframe } from "styleframe";
import { useColorDesignTokens } from "@styleframe/theme";
import { useBackgroundColorUtility } from "@styleframe/theme";
import { useHoverModifier } from "@styleframe/theme";

const s = styleframe();
const { ref } = s;

const { colorPrimary, colorSecondary } = useColorDesignTokens(s, {
    primary: '#006cff',
    secondary: '#6c757d',
} as const);

const hover = useHoverModifier(s);

useBackgroundColorUtility(s, {
    primary: ref(colorPrimary),
    secondary: ref(colorSecondary),
}, [hover]);

export default s;

CSS Selector

Modifier NameCSS Selector
hover&:hover

useFocusModifier

The useFocusModifier() function creates a modifier that applies styles when an element receives focus.

styleframe.config.ts
import { styleframe } from "styleframe";
import { useRingUtility } from "@styleframe/theme";
import { useFocusModifier } from "@styleframe/theme";

const s = styleframe();

const focus = useFocusModifier(s);

useRingUtility(s, {
    primary: '0 0 0 2px #006cff',
}, [focus]);

export default s;

CSS Selector

Modifier NameCSS Selector
focus&:focus

useFocusWithinModifier

The useFocusWithinModifier() function creates a modifier that applies styles when any child element receives focus.

styleframe.config.ts
import { styleframe } from "styleframe";
import { useBorderColorUtility } from "@styleframe/theme";
import { useFocusWithinModifier } from "@styleframe/theme";

const s = styleframe();

const focusWithin = useFocusWithinModifier(s);

useBorderColorUtility(s, {
    primary: '#006cff',
}, [focusWithin]);

export default s;

CSS Selector

Modifier NameCSS Selector
focus-within&:focus-within

useFocusVisibleModifier

The useFocusVisibleModifier() function creates a modifier that applies styles only when focus is visible (typically keyboard navigation).

styleframe.config.ts
import { styleframe } from "styleframe";
import { useOutlineUtility } from "@styleframe/theme";
import { useFocusVisibleModifier } from "@styleframe/theme";

const s = styleframe();

const focusVisible = useFocusVisibleModifier(s);

useOutlineUtility(s, {
    primary: '2px solid #006cff',
}, [focusVisible]);

export default s;

CSS Selector

Modifier NameCSS Selector
focus-visible&:focus-visible
Pro tip: Prefer useFocusVisibleModifier over useFocusModifier for focus indicators. It only shows the indicator for keyboard navigation, not mouse clicks, providing a cleaner user experience.

useActiveModifier

The useActiveModifier() function creates a modifier that applies styles when an element is being activated (clicked/pressed).

styleframe.config.ts
import { styleframe } from "styleframe";
import { useScaleUtility } from "@styleframe/theme";
import { useActiveModifier } from "@styleframe/theme";

const s = styleframe();

const active = useActiveModifier(s);

useScaleUtility(s, {
    95: '0.95',
}, [active]);

export default s;

CSS Selector

Modifier NameCSS Selector
active&:active

useVisitedModifier

The useVisitedModifier() function creates a modifier that applies styles to visited links.

styleframe.config.ts
import { styleframe } from "styleframe";
import { useTextColorUtility } from "@styleframe/theme";
import { useVisitedModifier } from "@styleframe/theme";

const s = styleframe();

const visited = useVisitedModifier(s);

useTextColorUtility(s, {
    muted: '#6c757d',
}, [visited]);

export default s;

CSS Selector

Modifier NameCSS Selector
visited&:visited

useTargetModifier

The useTargetModifier() function creates a modifier that applies styles when the element is the target of the current URL fragment.

styleframe.config.ts
import { styleframe } from "styleframe";
import { useBackgroundColorUtility } from "@styleframe/theme";
import { useTargetModifier } from "@styleframe/theme";

const s = styleframe();

const target = useTargetModifier(s);

useBackgroundColorUtility(s, {
    highlight: '#fff3cd',
}, [target]);

export default s;

CSS Selector

Modifier NameCSS Selector
target&:target

usePseudoStateModifiers

The usePseudoStateModifiers() function registers all pseudo-state modifiers at once and returns them as a destructurable object.

styleframe.config.ts
import { styleframe } from "styleframe";
import { useColorDesignTokens } from "@styleframe/theme";
import { useOpacityUtility } from "@styleframe/theme";
import { usePseudoStateModifiers } from "@styleframe/theme";

const s = styleframe();

const { hover, focus, active } = usePseudoStateModifiers(s);

useOpacityUtility(s, {
    75: '0.75',
    50: '0.5',
}, [hover, focus, active]);

export default s;

Returned Modifiers

KeyModifier NameCSS Selector
hoverhover&:hover
focusfocus&:focus
focusWithinfocus-within&:focus-within
focusVisiblefocus-visible&:focus-visible
activeactive&:active
visitedvisited&:visited
targettarget&:target

Examples

Interactive Button

styleframe.config.ts
import { styleframe } from "styleframe";
import { useColorDesignTokens } from "@styleframe/theme";
import { useBackgroundColorUtility, useScaleUtility, useOpacityUtility } from "@styleframe/theme";
import { usePseudoStateModifiers } from "@styleframe/theme";

const s = styleframe();
const { ref } = s;

const { colorPrimary } = useColorDesignTokens(s, { primary: '#006cff' } as const);

const { hover, active, focusVisible } = usePseudoStateModifiers(s);

useBackgroundColorUtility(s, {
    primary: ref(colorPrimary),
}, [hover]);

useOpacityUtility(s, {
    90: '0.9',
}, [hover]);

useScaleUtility(s, {
    95: '0.95',
}, [active]);

export default s;

Focus Ring with Focus-Visible

styleframe.config.ts
import { styleframe } from "styleframe";
import { useRingUtility, useOutlineUtility } from "@styleframe/theme";
import { useFocusVisibleModifier } from "@styleframe/theme";

const s = styleframe();

const focusVisible = useFocusVisibleModifier(s);

useRingUtility(s, {
    primary: '0 0 0 3px rgba(0, 108, 255, 0.5)',
}, [focusVisible]);

useOutlineUtility(s, {
    none: 'none',
}, [focusVisible]);

export default s;

Best Practices

  • Prefer focus-visible over focus: Use useFocusVisibleModifier for focus indicators to avoid showing focus rings on mouse clicks
  • Combine hover and active: Create buttons that respond to both hover and press states for better feedback
  • Use focus-within for form groups: Highlight parent containers when any child input is focused
  • Limit modifier count: Only generate the state variants your design requires to keep CSS bundle size small
  • Test touch devices: :hover may behave unexpectedly on touch devices; design fallbacks accordingly

FAQ