Examples
margin-block
padding-block-start
border-block-end
overflow-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-block
padding-block-start
border-block-end
overflow-block
Transformation
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-inline
padding-inline-start
border-inline-end
overflow-inline
Transformation
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
inset
border-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-block
overflow-inline
Containment Properties
contain-intrinsic-block-size
contain-intrinsic-inline-size
Logical Values
float: inline-start
clear: inline-end
resize: 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 Output
This architecture ensures reliable, performant transformation of logical properties while maintaining CSS semantics and optimizing output quality.