Direction Attribute Missing
Ensure dir="ltr" or dir="rtl" is set on your HTML element
The plugin works out of the box with zero configuration, but offers powerful customization options for advanced use cases.
module.exports = { plugins: [ require('postcss-logical-polyfill')() ]}const logicalPolyfill = require('postcss-logical-polyfill');
module.exports = { plugins: [ logicalPolyfill({ // Direction selectors (default shown) rtl: { selector: '[dir="rtl"]' }, ltr: { selector: '[dir="ltr"]' },
// Output order for unscoped properties outputOrder: 'ltr-first' // or 'rtl-first' }) ]}Control how the plugin generates direction-specific selectors:
{ rtl: { selector: '[dir="rtl"]' }, ltr: { selector: '[dir="ltr"]' }}{ rtl: { selector: '.rtl' }, ltr: { selector: '.ltr' }}{ rtl: { selector: '[data-theme="rtl"]' }, ltr: { selector: '[data-theme="ltr"]' }}Control the order of generated rules for unscoped properties:
{ outputOrder: 'ltr-first' // Default: LTR rules first, then RTL // outputOrder: 'rtl-first' // RTL rules first, then LTR}Example Output:
.container { margin-left: 1rem; margin-right: 1rem;}[dir="ltr"] .container { padding-left: 1rem;}[dir="rtl"] .container { padding-right: 1rem;}.container { margin-left: 1rem; margin-right: 1rem;}[dir="rtl"] .container { padding-right: 1rem;}[dir="ltr"] .container { padding-left: 1rem;}module.exports = { webpack: (config) => { config.module.rules.push({ test: /\.css$/, use: [ 'style-loader', 'css-loader', { loader: 'postcss-loader', options: { postcssOptions: { plugins: [ require('postcss-logical-polyfill')({ rtl: { selector: '[dir="rtl"]' }, ltr: { selector: '[dir="ltr"]' } }) ] } } } ] }); return config; }};import { defineConfig } from 'vite';
export default defineConfig({ css: { postcss: { plugins: [ require('postcss-logical-polyfill')({ outputOrder: 'ltr-first' }) ] } }});module.exports = { module: { rules: [ { test: /\.css$/, use: [ 'style-loader', 'css-loader', { loader: 'postcss-loader', options: { postcssOptions: { plugins: [ require('postcss-logical-polyfill')({ rtl: { selector: '.rtl' }, ltr: { selector: '.ltr' } }) ] } } } ] } ] }};module.exports = { content: ['./src/**/*.{html,js}'], theme: { extend: {} }, plugins: [], // Add to PostCSS processing corePlugins: { // Disable Tailwind's logical properties if using this plugin margin: true, padding: true }};
// postcss.config.jsmodule.exports = { plugins: [ require('tailwindcss'), require('postcss-logical-polyfill')(), require('autoprefixer') ]};For complex scenarios, you can use advanced selector patterns:
{ rtl: { selector: 'html[dir="rtl"]', // More specific }, ltr: { selector: 'html[dir="ltr"]', }}{ rtl: { selector: '[dir="rtl"], .rtl-mode' // Multiple selectors }, ltr: { selector: '[dir="ltr"], .ltr-mode' }}You must set the dir attribute on your HTML for the generated CSS to work:
<!DOCTYPE html><html dir="ltr"> <!-- For left-to-right layouts --><head> <meta charset="UTF-8"> <title>My App</title></head><body> <!-- Your content --></body></html>For RTL languages:
<html dir="rtl"> <!-- For right-to-left layouts -->For applications that support dynamic direction switching:
// JavaScript to toggle directionfunction toggleDirection() { const html = document.documentElement; const currentDir = html.getAttribute('dir'); html.setAttribute('dir', currentDir === 'rtl' ? 'ltr' : 'rtl');}import { useState } from 'react';
function App() { const [direction, setDirection] = useState('ltr');
useEffect(() => { document.documentElement.setAttribute('dir', direction); }, [direction]);
return ( <div> <button onClick={() => setDirection(direction === 'ltr' ? 'rtl' : 'ltr')}> Switch to {direction === 'ltr' ? 'RTL' : 'LTR'} </button> {/* Your app content */} </div> );}The plugin automatically optimizes block-direction properties to generate fewer rules:
/* Input */.element { margin-block: 1rem; padding-block-start: 0.5rem;}
/* Optimized Output - No direction selectors needed */.element { margin-top: 1rem; margin-bottom: 1rem; padding-top: 0.5rem;}For large codebases, consider processing only files that contain logical properties:
// Only process certain file patternsmodule.exports = { plugins: [ // Other plugins require('postcss-logical-polyfill')() ]};You can debug the transformation process by examining the generated CSS:
const postcss = require('postcss');const logicalPolyfill = require('postcss-logical-polyfill');
const result = postcss([logicalPolyfill()]) .process(css, { from: undefined });
console.log('Original CSS:', css);console.log('Transformed CSS:', result.css);Direction Attribute Missing
Ensure dir="ltr" or dir="rtl" is set on your HTML element
Selector Specificity
Check that your direction selectors have appropriate specificity
Order Matters
Consider the outputOrder option for consistent rule ordering
dir attribute on your <html> element/* Before: Physical properties */.element { margin-left: 1rem; margin-right: 2rem; padding-left: 0.5rem;}
/* After: Logical properties */.element { margin-inline: 1rem 2rem; padding-inline-start: 0.5rem;}If migrating from other logical property tools, note that this plugin works in the opposite direction - it converts logical properties TO physical properties for compatibility.