Bidirectional horizontal rules in CSS
Tags: css, rtl, multilingual
Published: 2019-10-22 10:34:51

---
title: Bidirectional horizontal rules in CSS
published: true
description: Using CSS's logical properties to support both LTR and RTL layouts.
tags: CSS,RTL,multilingual
---

The [dir attribute in HTML](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir) and the [dir property in CSS](https://developer.mozilla.org/en-US/docs/Web/CSS/direction) can be used to set the direction of text and horizontal flow. Some languages are written Left-To-Right (LTR), while others are written Right-To-Left (RTL). So having this level of control is vital for creating documents and interfaces for the web.

Building an interface to support both LTR and RTL layouts is a challenge. Flexbox and Grid certainly makes things easier, but they don't cover all our styling needs.

There are many CSS rules we write in which we specify a physical direction or side. For instance, when we write CSS to layout horizontal elements, it is common to set a margin only on a single side and set a margin of `0` (on the same side) to the first or last sibling element.

```css
.element {
    margin-right: 1rem;
}

.element:last-child {
    margin-right: 0;
}

```

Or

```css
.element:not(:last-child) {
    margin-right: 1rem;
}
```

In the above example we are adding a margin on the right side of each element except the last. That's how it is written. Though what we mean when we write this is to add a margin _after_ the element in the direction of the horizontal flow of the document (or the parent element).

A common way to style `blockquote` is to add a border to one side of the quote; the side we consider to come _before_ the quote.

This is [Bulma](https://bulma.io/)'s `<blockquote>` styling:

```css
.content blockquote {
    background-color: #f5f5f5;
    border-left: 5px solid #dbdbdb;
    padding: 1.25em 1.5em;
}
```

And there are many other styling choices we make in which we specify a side/direction (left/right) in CSS, but what we actually mean is before/after.

So when building interfaces that support both LTR and RTL layouts, one option would be to write CSS rules like:

```css
.class {}

html[dir="rtl"] .class {}
```

Or perhaps even load different stylesheets for LTR and RTL layouts. However, both options require we either write more CSS or [set up our tooling to generate the appropriate flipped styles](https://gist.github.com/Integralist/7269907). And there are also [tools that convert LTR to RTL styles](https://rtl.daskhat.ir/) for you.

Wouldn't it be nice to work with a lower level of abstraction instead? What if we can tell the browser we are targeting the side before/after an element instead of referring to the physical directions left/right? At the end of the day this is what we mean a lot of the times. This reminds me of this tweet: 

{% twitter 842728744653676544 %}

CSS has what is called *logical properties*. We can now tell the browser what we actually mean. Instead of using `-left` and `-right`, we can use `-inline-start` and `-inline-end`:

```css
.element:not(:last-child) {
    margin-inline-end: 1rem;
}
```

Similarly instead of using `-top` and `-bottom`, we can use `-block-start` and `-block-end`.


This means we can write one set of rules that target both LTR and RTL layouts. Here is an example using the `margin-inline-end` property:

{% codepen https://codepen.io/hus_hmd/pen/bGGgMZd default-tab=result %}


Using the `border-inline-start` and `padding-inline-start` properties:

{% codepen https://codepen.io/hus_hmd/pen/vYYgrBM default-tab=result %}


Firefox also supports `border-*-*-radius` so you can target different corners with `border-start-start-radius`, `border-end-start-radius`, etc.

{% codepen https://codepen.io/hus_hmd/pen/abbpKzK default-tab=result %}


All demos:

{% codepen https://codepen.io/hus_hmd/pen/YzzNzPp default-tab=result %}


For a deeper explanation, you can refer to Rachel Andrew's article [Understanding Logical Properties And Values](https://www.smashingmagazine.com/2018/03/understanding-logical-properties-values/). This is not just about RTL interfaces or horizontal bidirectional CSS rules. Rachel's article also covers logical dimensions.


## Browser Support

Can I Use?:

- [Logical Properties](https://caniuse.com/#feat=css-logical-props)
- [border-\*-\*-radius](https://caniuse.com/#feat=mdn-css_properties_border-start-start-radius)