Examples
margin-blockpadding-block-startborder-block-endoverflow-block
PostCSS Logical Polyfill processes CSS through a sophisticated 7-phase optimization pipeline that intelligently transforms logical properties into physical properties while preserving directional behavior.
When generating optimized direction-specific rules, repeated physical properties are resolved by declaration priority: !important takes precedence, and the last declaration wins among declarations of equal importance.
When a common shorthand and a direction-dependent longhand overlap (for example, margin and margin-left), the direction rule also includes the overlapping declarations in their original winning order. This prevents selector specificity from changing the cascade. Each property still appears only once within an optimized rule.
CSS nesting must be expanded before this plugin (for example, with postcss-nested or postcss-nesting). Unexpanded nested rules are left intact with a PostCSS warning. Logical properties use the horizontal writing mode; vertical writing modes are not inferred.
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.
Detection Phase
The plugin scans the CSS AST to identify:
Classification Phase
Properties are categorized into three types:
Transformation Phase
Each logical property is converted based on:
Selector Application
Direction selectors are added when needed:
Optimization Phase
The CSS is optimized by:
Priority Management
Implements rightmost selector precedence:
Output Generation
Produces clean, optimized CSS:
Block-direction properties only affect the block dimension (usually vertical) and are direction-independent.
Examples
margin-blockpadding-block-startborder-block-endoverflow-blockTransformation
Simple 1:1 mapping to physical properties without direction selectors
/* Input */.element { margin-block: 1rem; padding-block-start: 0.5rem;}
/* Output - No direction selectors needed */.element { margin-top: 1rem; margin-bottom: 1rem; padding-top: 0.5rem;}Inline-direction properties affect the inline dimension (usually horizontal) and are direction-aware.
Examples
margin-inlinepadding-inline-startborder-inline-endoverflow-inlineTransformation
Generate separate LTR and RTL rules with direction selectors
/* Input */.element { margin-inline: 1rem; padding-inline-start: 0.5rem;}
/* Output - Separate direction rules */.element { margin-left: 1rem; margin-right: 1rem;}[dir="ltr"] .element { padding-left: 0.5rem;}[dir="rtl"] .element { padding-right: 0.5rem;}Mixed-direction properties affect both dimensions and require careful handling.
Examples
insetborder-radius logical variantsTransformation
Generate direction-specific rules for inline components
/* Input */.element { inset: 10px 20px;}
/* Output - Direction-aware for horizontal values */[dir="ltr"] .element { top: 10px; right: 20px; bottom: 10px; left: 20px;}[dir="rtl"] .element { top: 10px; left: 20px; bottom: 10px; right: 20px;}Properties without existing direction selectors are processed to generate both LTR and RTL versions.
/* Input - Unscoped */.container { margin-inline-start: 1rem;}
/* Output - Both directions generated */[dir="ltr"] .container { margin-left: 1rem;}[dir="rtl"] .container { margin-right: 1rem;}Properties already within direction selectors are processed for that specific direction only.
/* Input - Already scoped */[dir="ltr"] .container { margin-inline-start: 1rem;}
/* Output - Only LTR processed */[dir="ltr"] .container { margin-left: 1rem;}The plugin includes an integrated shim system that extends support beyond the core postcss-logical package.
Scroll Properties
scroll-margin-*scroll-padding-*Overflow Properties
overflow-blockoverflow-inlineContainment Properties
contain-intrinsic-block-sizecontain-intrinsic-inline-sizeLogical Values
float: inline-startclear: inline-endresize: block// Shim declaration example'overflow-block': (decl) => { decl.cloneBefore({ prop: 'overflow-y' }); decl.remove();}Compatible rules are merged to reduce CSS size:
/* Before merging */.element { margin-left: 1rem; }.element { margin-right: 1rem; }
/* After merging */.element { margin-left: 1rem; margin-right: 1rem;}Similar selectors are consolidated when possible:
/* Multiple rules with same selector */[dir="ltr"] .a { margin-left: 1rem; }[dir="ltr"] .a { padding-left: 0.5rem; }
/* Consolidated */[dir="ltr"] .a { margin-left: 1rem; padding-left: 0.5rem;}Duplicate or unnecessary declarations are removed:
/* Input with redundancy */.element { margin-inline: 1rem; margin-inline: 1rem; /* Duplicate */}
/* Output - Duplicates removed */.element { margin-left: 1rem; margin-right: 1rem;}The plugin minimizes AST traversals by:
Optimizes memory by:
Reduces output size through:
The plugin gracefully handles invalid logical properties:
/* Invalid property value */.element { margin-inline: invalid-value;}
/* Preserved as-is with warning */.element { margin-inline: invalid-value;}Malformed CSS is preserved to avoid breaking builds:
/* Malformed rule */.element { margin-inline: 1rem /* Missing semicolon */}
/* Preserved with transformation */.element { margin-left: 1rem; margin-right: 1rem}Enable detailed logging during development:
const result = postcss([ logicalPolyfill({ debug: true })]).process(css);
// Logs transformation detailsconsole.log(result.messages);The plugin preserves source map information for debugging:
const result = postcss([logicalPolyfill()]) .process(css, { from: 'input.css', to: 'output.css', map: true });Place postcss-logical-polyfill after CSS processing plugins but before optimization plugins:
module.exports = { plugins: [ require('postcss-import'), require('postcss-nested'), require('postcss-logical-polyfill'), // After CSS processing require('autoprefixer'), require('cssnano') // Before optimization ]};The plugin is compatible with:
Processor Core
Main transformation engine that coordinates all phases
Shim System
Extension system for additional logical properties
Selector Utils
Utilities for parsing and manipulating direction selectors
Property Maps
Mapping tables for logical to physical property conversion
CSS Input ↓AST Parsing ↓Property Detection ↓Classification ↓Transformation ↓Optimization ↓CSS OutputThis architecture ensures reliable, performant transformation of logical properties while maintaining CSS semantics and optimizing output quality.