npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

postcss-logical-polyfill

v0.7.1

Published

Compile CSS logical properties into one stylesheet with LTR and RTL physical-property rules for older browsers and WebViews.

Readme

postcss-logical-polyfill

NPM Version Build Status Coverage Status

Write CSS logical properties and compile one stylesheet with LTR and RTL physical-property rules for older browsers and WebViews.

Use this plugin when your internationalized application needs both directions in the same CSS file and your target browsers lack the logical properties you use. Direction-independent declarations stay in a common rule; directional declarations use configurable selectors.

Documentation · Playground · Examples

Is this the right tool?

| Your requirement | Consider | | --- | --- | | Your target browsers support the logical properties you use | Native CSS; no transformation is needed | | Compile logical properties for one configured direction or writing mode | postcss-logical, also available through postcss-preset-env | | Mirror existing physical LTR styles into RTL styles | RTLCSS or postcss-rtlcss | | Compile logical properties into one stylesheet with horizontal LTR/RTL scopes, including existing direction selectors and opt-in logical animations | postcss-logical-polyfill | | Need logical-property transformations for vertical writing modes | Evaluate postcss-logical-properties-polyfill, whose documentation lists these features |

Other tools also generate combined LTR/RTL styles. This plugin focuses on logical-property input, existing direction scopes, common declarations and additional logical values. Check the supported properties and limitations below against your application.

Quick start

Requires Node.js 20.19.0 or later and PostCSS 8.4.0 or later within version 8.

npm install --save-dev postcss postcss-logical-polyfill
# or: pnpm add -D postcss postcss-logical-polyfill
# or: yarn add -D postcss postcss-logical-polyfill

For an ESM project, including Vite projects that load a PostCSS configuration:

// postcss.config.mjs
import logicalPolyfill from 'postcss-logical-polyfill';

export default {
  plugins: [logicalPolyfill()]
};

For CommonJS:

// postcss.config.cjs
module.exports = {
  plugins: [require('postcss-logical-polyfill')()]
};

Set an explicit direction marker on an ancestor of your styled elements:

<html dir="ltr">
  <body>
    <div class="card">Card content</div>
  </body>
</html>

Use dir="rtl" for RTL. The browser's default LTR direction does not add a dir attribute, so it does not match the default [dir="ltr"] selector. Changing document.documentElement.dir switches between the generated rules without another CSS build.

Input:

.card {
  padding-block: 1rem;
  margin-inline-start: 2rem;
}

Output:

.card {
  padding-top: 1rem;
  padding-bottom: 1rem;
}
[dir="ltr"] .card {
  margin-left: 2rem;
}
[dir="rtl"] .card {
  margin-right: 2rem;
}

Existing direction scopes and logical values

Recognized direction-scoped rules are transformed for their existing context:

/* Input */
[dir="rtl"] .notice {
  margin-inline-start: 1rem;
}

/* Output */
[dir="rtl"] .notice {
  margin-right: 1rem;
}

Additional transformations include scroll margin/padding, logical overflow and containment sizes, and logical values such as float: inline-start, clear: inline-end and resize: block. Experimental logical gradient directions are also supported; they are an extension, not a guarantee of native browser support.

/* Input */
.notice {
  float: inline-start;
}

/* Output */
[dir="ltr"] .notice {
  float: left;
}
[dir="rtl"] .notice {
  float: right;
}

Configuration

The default options are:

import logicalPolyfill from 'postcss-logical-polyfill';

export default {
  plugins: [logicalPolyfill({
    ltr: { selector: '[dir="ltr"]' },
    rtl: { selector: '[dir="rtl"]' },
    outputOrder: 'ltr-first' // or 'rtl-first'
  })]
};

Custom direction classes are supported:

logicalPolyfill({
  ltr: { selector: '.ltr' },
  rtl: { selector: '.rtl' }
});

These classes must match ancestors of the styled elements. They scope the generated CSS; also set the HTML dir attribute for text direction and other browser behavior.

See the configuration guide for selector lists and integration options.

Logical keyframes (opt-in)

logicalPolyfill({ animations: true });

The plugin keeps original keyframes and creates LTR/RTL physical-property copies for referenced logical animations. Both animation-name and animation shorthand references are rewritten. Ordinary animations are unchanged. Generated names avoid existing definitions and static references; same-name definitions retain their original media/supports/layer contexts.

/* Input */
@keyframes slide {
  from { margin-inline-start: 0; }
  to { margin-inline-start: 100px; }
}
.card { animation: slide 1s linear; }

This generates direction-specific lp-slide-ltr and lp-slide-rtl keyframes and matching animation rules. Generated names may gain a numeric suffix when needed to avoid collisions.

Try the runnable animation example.

Run postcss-import before this plugin when definitions and references are in separate files. Runtime names inside var() or env() cannot be resolved reliably: they remain unchanged with a PostCSS warning, and original definitions remain available for browsers with native logical-property support. They do not gain a physical-property animation fallback. Expand CSS nesting before the plugin.

Compatibility and limitations

  • Transformations assume horizontal writing modes. Vertical writing modes are not inferred.
  • Keyframes are left untouched by default. Enable animations: true to transform referenced logical keyframes and static animation names. Logical property names in transition and transition-property are transformed independently of this option.
  • Expand CSS nesting before this plugin, using a tool such as postcss-nested or postcss-nesting. Unexpanded nested rules are left intact with a PostCSS warning.
  • Direction prefixes add selector specificity. Overrides in separate rules should use matching direction scopes. For subtrees with conflicting direction ancestors, write explicit direction-scoped selectors so the plugin can use the rightmost context.
  • Repeated physical properties within an optimized rule are resolved by !important priority, then source order. Overlapping common shorthands are retained in direction rules where needed to preserve their ordering relative to directional longhands.
  • Browser compatibility depends on the physical properties and values in the output. Transforming a logical name does not polyfill unrelated CSS features such as custom properties, scroll behavior or containment.

When transition-property expands a shorthand such as margin-inline, static companion timing lists are expanded to keep their original correspondence. Dynamic or inherited lists, and component lists extracted from function-valued transition shorthands, are preserved with a PostCSS warning when they cannot be aligned safely. Explicit timing longhands with static functions can be aligned.

See how it works and troubleshooting.

Examples and documentation

The repository includes examples for plain PostCSS, Vite, Webpack, Sass, Less, the PostCSS CLI, custom selectors and output order. After cloning the repository and installing dependencies:

pnpm build
pnpm examples

Contributing

Contributions and reports of real-world compatibility issues are welcome. Include your input CSS, generated CSS, direction markers and target browser when reporting an issue.

Credits and license

This plugin wraps and extends postcss-logical. Licensed under MIT.