CSS Logical Properties

Introduction to Logical Properties

CSS Logical Properties provide a way to control layout through logical, rather than physical, direction and dimension mappings. This makes creating internationalized layouts much easier, especially for languages that use different writing modes.

Why Logical Properties Matter

Traditional CSS properties like margin-left or border-right are based on physical directions. This creates challenges when supporting languages with different writing directions:

  • Left-to-right (LTR) languages: English, Spanish, French, etc.
  • Right-to-left (RTL) languages: Arabic, Hebrew, Persian, etc.
  • Top-to-bottom languages: Traditional Chinese, Japanese, Korean, etc.

Logical properties solve this by using flow-relative terms instead of physical directions:

  • Inline: The direction text flows (left-to-right in English, right-to-left in Arabic)
  • Block: The direction blocks stack (top-to-bottom in most languages)
  • Start: The beginning of a flow
  • End: The end of a flow
Key Insight: With logical properties, you define layout relative to text flow, not physical screen directions. This means your layout automatically adapts to different writing modes and directions.

Physical vs. Logical Properties

Mapping Physical to Logical Properties

Physical Property Logical Property LTR Equivalent RTL Equivalent
margin-top margin-block-start margin-top margin-top
margin-bottom margin-block-end margin-bottom margin-bottom
margin-left margin-inline-start margin-left margin-right
margin-right margin-inline-end margin-right margin-left
padding-top padding-block-start padding-top padding-top
padding-bottom padding-block-end padding-bottom padding-bottom
padding-left padding-inline-start padding-left padding-right
padding-right padding-inline-end padding-right padding-left
border-top border-block-start border-top border-top
border-bottom border-block-end border-bottom border-bottom
border-left border-inline-start border-left border-right
border-right border-inline-end border-right border-left

Dimension Properties

Physical Property Logical Property LTR Equivalent
width inline-size width
height block-size height
min-width min-inline-size min-width
min-height min-block-size min-height
max-width max-inline-size max-width
max-height max-block-size max-height

Using Logical Properties

Basic Usage


/* Traditional physical properties */
.box-physical {
  margin-top: 10px;
  margin-right: 20px;
  margin-bottom: 10px;
  margin-left: 20px;
  
  padding-top: 15px;
  padding-right: 25px;
  padding-bottom: 15px;
  padding-left: 25px;
  
  border-top: 1px solid black;
  border-right: 2px solid black;
  border-bottom: 1px solid black;
  border-left: 2px solid black;
}

/* Equivalent logical properties */
.box-logical {
  margin-block-start: 10px;
  margin-inline-end: 20px;
  margin-block-end: 10px;
  margin-inline-start: 20px;
  
  padding-block-start: 15px;
  padding-inline-end: 25px;
  padding-block-end: 15px;
  padding-inline-start: 25px;
  
  border-block-start: 1px solid black;
  border-inline-end: 2px solid black;
  border-block-end: 1px solid black;
  border-inline-start: 2px solid black;
}
                        

Shorthand Properties


/* Block axis shorthands (top/bottom) */
.element {
  margin-block: 10px;         /* margin-block-start and margin-block-end */
  padding-block: 15px;        /* padding-block-start and padding-block-end */
  border-block: 1px solid;    /* border-block-start and border-block-end */
}

/* Inline axis shorthands (left/right in LTR) */
.element {
  margin-inline: 20px;        /* margin-inline-start and margin-inline-end */
  padding-inline: 25px;       /* padding-inline-start and padding-inline-end */
  border-inline: 2px solid;   /* border-inline-start and border-inline-end */
}

/* Individual border properties */
.element {
  border-block-start-width: 1px;
  border-block-start-style: solid;
  border-block-start-color: black;
  
  /* Shorthand */
  border-block-start: 1px solid black;
}
                        

Logical Values for Float and Clear


/* Physical values */
.float-left {
  float: left;
}

.clear-right {
  clear: right;
}

/* Logical values */
.float-start {
  float: inline-start;  /* left in LTR, right in RTL */
}

.clear-end {
  clear: inline-end;    /* right in LTR, left in RTL */
}
                        

Text Alignment and Direction

Text Alignment


/* Physical alignment */
.align-left {
  text-align: left;
}

.align-right {
  text-align: right;
}

/* Logical alignment */
.align-start {
  text-align: start;  /* left in LTR, right in RTL */
}

.align-end {
  text-align: end;    /* right in LTR, left in RTL */
}
                        

Direction and Writing Mode


/* Set text direction */
.rtl-text {
  direction: rtl;  /* Right to left */
}

.ltr-text {
  direction: ltr;  /* Left to right (default) */
}

/* Set writing mode */
.horizontal-tb {
  writing-mode: horizontal-tb;  /* Default: horizontal, top to bottom */
}

.vertical-rl {
  writing-mode: vertical-rl;    /* Vertical, right to left */
}

.vertical-lr {
  writing-mode: vertical-lr;    /* Vertical, left to right */
}
                        
Note: When you change the writing mode, the meaning of inline and block also changes. In vertical writing modes, inline runs vertically and block runs horizontally.

Practical Examples

Bidirectional Navigation Menu


/* HTML */
<nav class="main-nav">
  <ul>
    <li><a href="#">Home</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Services</a></li>
    <li><a href="#">Contact</a></li>
  </ul>
</nav>

/* CSS */
.main-nav ul {
  display: flex;
  list-style: none;
  padding-inline-start: 0;  /* Removes default padding */
  margin-block: 0;          /* Removes top and bottom margins */
}

.main-nav li:not(:last-child) {
  margin-inline-end: 20px;  /* Space between items */
}

.main-nav a {
  padding-block: 10px;
  padding-inline: 15px;
  border-inline-start: 3px solid transparent;
}

.main-nav a:hover {
  border-inline-start-color: blue;
}

/* This menu will work correctly in both LTR and RTL contexts */
                        

Card Component with Icon


/* HTML */
<div class="card">
  <div class="card-icon">
    <i class="icon"></i>
  </div>
  <div class="card-content">
    <h3>Card Title</h3>
    <p>Card description text goes here.</p>
  </div>
</div>

/* CSS */
.card {
  display: flex;
  padding: 15px;
  border-radius: 8px;
  box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}

.card-icon {
  margin-inline-end: 15px;  /* Space between icon and content */
}

.card-content {
  padding-inline-start: 10px;
  border-inline-start: 2px solid #eee;
}

/* In LTR: Icon on left, content on right */
/* In RTL: Icon on right, content on left */
                        

Form Layout


/* HTML */
<form class="contact-form">
  <div class="form-group">
    <label for="name">Name:</label>
    <input type="text" id="name">
  </div>
  <div class="form-group">
    <label for="email">Email:</label>
    <input type="email" id="email">
  </div>
  <div class="form-actions">
    <button type="submit">Submit</button>
    <button type="reset">Reset</button>
  </div>
</form>

/* CSS */
.form-group {
  margin-block-end: 15px;
  display: flex;
  flex-wrap: wrap;
}

.form-group label {
  flex: 0 0 100px;
  text-align: end;
  padding-inline-end: 10px;
}

.form-group input {
  flex: 1;
  min-inline-size: 200px;
}

.form-actions {
  margin-inline-start: 100px;  /* Align with inputs */
  padding-block-start: 10px;
}

.form-actions button:first-child {
  margin-inline-end: 10px;
}
                        

Logical Properties in Grid and Flexbox

Grid Layout with Logical Properties


.grid-container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);  /* Still using columns */
  gap: 20px;
}

/* Using logical properties for item placement */
.header {
  grid-column: 1 / -1;  /* Spans all columns */
  padding-block: 20px;
  border-block-end: 1px solid #ddd;
}

.sidebar {
  grid-row: 2 / 4;
  padding-inline: 15px;
  border-inline-end: 1px solid #ddd;
}

.content {
  grid-column: 2 / -1;
  padding: 20px;
}

.footer {
  grid-column: 1 / -1;
  padding-block: 20px;
  border-block-start: 1px solid #ddd;
}
                        

Flexbox with Logical Properties


.flex-container {
  display: flex;
  flex-direction: row;  /* Default */
  justify-content: space-between;
  padding-block: 20px;
  padding-inline: 15px;
}

.flex-item {
  margin-inline-end: 10px;
  padding-inline: 15px;
  border-inline-start: 2px solid #ddd;
}

.flex-item:last-child {
  margin-inline-end: 0;
}

/* For RTL support, no changes needed to the flex layout */
/* Just add dir="rtl" to the HTML element or set direction: rtl; in CSS */
                        

Browser Support and Fallbacks

Current Browser Support

Logical properties have good support in modern browsers, but you may need fallbacks for older browsers:

  • Chrome: Full support since version 89
  • Firefox: Full support since version 66
  • Safari: Full support since version 15
  • Edge: Full support since version 89

Providing Fallbacks


/* Method 1: Cascade - Physical properties first, then logical */
.element {
  /* Fallback for older browsers */
  margin-left: 20px;
  margin-right: 20px;
  
  /* Modern browsers will use these */
  margin-inline-start: 20px;
  margin-inline-end: 20px;
}

/* Method 2: Feature detection with @supports */
.element {
  /* Fallback for all browsers */
  margin-left: 20px;
  margin-right: 20px;
}

@supports (margin-inline-start: 20px) {
  .element {
    margin-left: 0;  /* Reset physical property */
    margin-right: 0;
    margin-inline-start: 20px;
    margin-inline-end: 20px;
  }
}
                        

Using PostCSS for Automatic Fallbacks

The postcss-logical plugin can automatically generate physical fallbacks for logical properties:


/* Your CSS with logical properties */
.element {
  margin-inline: 20px;
  padding-block: 10px;
  border-inline-start: 1px solid black;
}

/* After PostCSS processing */
.element {
  margin-left: 20px;
  margin-right: 20px;
  padding-top: 10px;
  padding-bottom: 10px;
  border-left: 1px solid black;
  
  margin-inline: 20px;
  padding-block: 10px;
  border-inline-start: 1px solid black;
}

/* In RTL contexts, the physical fallbacks may be incorrect, 
   but the logical properties will work correctly */
                        

Best Practices

When to Use Logical Properties

  • Multilingual websites that support both LTR and RTL languages
  • International applications where content direction may change
  • Components that need to adapt to different writing modes
  • Design systems that aim for maximum flexibility and reusability

Migration Strategy

  1. Start with new components: Apply logical properties to new code first
  2. Identify direction-sensitive components: Focus on components that need to work in multiple writing directions
  3. Use automated tools: Consider using PostCSS or similar tools to help with the transition
  4. Test thoroughly: Verify layouts in both LTR and RTL contexts

Common Pitfalls

  • Mixing logical and physical properties: Be consistent to avoid confusion
  • Forgetting about images and icons: These may need to be flipped or adjusted for RTL
  • Assuming all languages read top-to-bottom: Some languages use vertical writing modes
  • Hardcoding values in JavaScript: Ensure JS also respects the document direction
Pro Tip: When building internationalized interfaces, test early and often with real content in different languages. What works well for Latin scripts might not work as well for Arabic, Hebrew, or Asian languages.

Resources and Further Reading

Documentation

Tools

Articles and Tutorials

Final Thought: Logical properties represent a significant improvement in how we handle layout in CSS. As global audiences become increasingly important, building layouts that work seamlessly across different writing systems is no longer optional but essential.