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.
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.