Styleframe Logo
Modifiers

Directional Modifiers

Create directional modifiers for targeting elements based on text direction (RTL/LTR) with full type safety.
Part of the Modifiers Preset:useDirectionalModifiers is included in the Modifiers Preset (useModifiersPreset) and you can configure it through the preset's directional option. For most projects, applying it via the preset is the recommended approach.

Overview

Directional modifiers let you apply utility styles conditionally based on the text direction of the document or a parent element. They wrap utility declarations in CSS selectors that match either right-to-left (RTL) or left-to-right (LTR) contexts, generating variant utility classes that adapt to text direction.

Why Use Directional Modifiers?

Directional modifiers help you:

  • Support internationalization: Adapt layouts for RTL languages like Arabic, Hebrew, and Persian
  • Flip directional properties: Swap margins, paddings, and positions based on text direction
  • Build bidirectional components: Create components that work in both LTR and RTL contexts
  • Maintain zero specificity: The :where() wrapper prevents specificity conflicts

useRtlModifier

The useRtlModifier() function creates a modifier that applies styles in right-to-left contexts. It uses :where() to maintain zero specificity.

styleframe.config.ts
import { styleframe } from "styleframe";
import { useMarginLeftUtility, useMarginRightUtility } from "@styleframe/theme";
import { useRtlModifier } from "@styleframe/theme";

const s = styleframe();

const rtl = useRtlModifier(s);

useMarginLeftUtility(s, {
    md: '1rem',
    0: '0',
}, [rtl]);

useMarginRightUtility(s, {
    md: '1rem',
    0: '0',
}, [rtl]);

export default s;

CSS Selector

Modifier NameCSS Selector
rtl&:where(:dir(rtl), [dir="rtl"], [dir="rtl"] *)
Pro tip: The RTL modifier uses :where() to keep specificity at zero. This prevents the RTL variant from winning over other utility classes due to specificity, making the cascade more predictable.

useLtrModifier

The useLtrModifier() function creates a modifier that applies styles in left-to-right contexts. Like the RTL modifier, it uses :where() for zero specificity.

styleframe.config.ts
import { styleframe } from "styleframe";
import { useTextAlignUtility } from "@styleframe/theme";
import { useLtrModifier, useRtlModifier } from "@styleframe/theme";

const s = styleframe();

const ltr = useLtrModifier(s);
const rtl = useRtlModifier(s);

useTextAlignUtility(s, {
    left: 'left',
    right: 'right',
}, [ltr, rtl]);

export default s;

CSS Selector

Modifier NameCSS Selector
ltr&:where(:dir(ltr), [dir="ltr"], [dir="ltr"] *)

useDirectionalModifiers

The useDirectionalModifiers() function registers both directional modifiers at once and returns them as a destructurable object.

styleframe.config.ts
import { styleframe } from "styleframe";
import { usePaddingLeftUtility, usePaddingRightUtility } from "@styleframe/theme";
import { useDirectionalModifiers } from "@styleframe/theme";

const s = styleframe();

const { rtl, ltr } = useDirectionalModifiers(s);

usePaddingLeftUtility(s, {
    md: '1rem',
    0: '0',
}, [rtl, ltr]);

usePaddingRightUtility(s, {
    md: '1rem',
    0: '0',
}, [rtl, ltr]);

export default s;

Returned Modifiers

KeyModifier NameCSS Selector
rtlrtl&:where(:dir(rtl), [dir="rtl"], [dir="rtl"] *)
ltrltr&:where(:dir(ltr), [dir="ltr"], [dir="ltr"] *)

Examples

Bidirectional Navigation

styleframe.config.ts
import { styleframe } from "styleframe";
import {
    useMarginLeftUtility,
    useMarginRightUtility,
    usePaddingLeftUtility,
    usePaddingRightUtility,
} from "@styleframe/theme";
import { useDirectionalModifiers } from "@styleframe/theme";

const s = styleframe();

const { rtl } = useDirectionalModifiers(s);

useMarginLeftUtility(s, { auto: 'auto', 0: '0' }, [rtl]);
useMarginRightUtility(s, { auto: 'auto', 0: '0' }, [rtl]);

usePaddingLeftUtility(s, { md: '1rem', 0: '0' }, [rtl]);
usePaddingRightUtility(s, { md: '1rem', 0: '0' }, [rtl]);

export default s;

Best Practices

  • Prefer logical properties: When possible, use CSS logical properties (margin-inline-start, padding-inline-end) instead of directional modifiers, as they handle RTL automatically
  • Use directional modifiers for exceptions: Apply them when logical properties don't cover your use case (e.g., absolute positioning, transforms)
  • Set dir attribute: Ensure your HTML has the correct dir="rtl" or dir="ltr" attribute for the selectors to match
  • Test both directions: Verify your layouts work correctly in both LTR and RTL modes
  • Keep specificity low: The :where() wrapper ensures directional modifiers don't cause specificity battles

FAQ