CSS :dir() Pseudo Class
The :dir() CSS pseudo-class matches elements that are based on the directionality of the text. Read about the pseudo-class and try examples.
The :dir() pseudo-class matches elements based on the directionality of the text they contain — that is, whether the text flows left-to-right (like English) or right-to-left (like Arabic or Hebrew).
This is useful when you build a layout that must adapt to both directions: instead of writing separate rules and toggling classes from JavaScript, you let the browser style each element according to its resolved text direction.
The :dir() pseudo-class does not look at any stylistic state — it reads the directionality that the document itself resolves for the element. That direction comes from the dir HTML attribute, which can be set to ltr, rtl, or auto, or is inherited from an ancestor.
The selector takes one of two values:
:dir(ltr)matches elements whose resolved directionality is left-to-right.:dir(rtl)matches elements whose resolved directionality is right-to-left.
Any other value is invalid and the selector simply won't match. Note that :dir(rtl) matches based on the resolved direction, so an element set to dir="auto" whose first strong character is Arabic will be matched by :dir(rtl).
:dir(rtl) vs. [dir=rtl]
It is tempting to reach for the attribute selector [dir=rtl] instead, but the two behave differently:
[dir=rtl]matches only when thedirattribute is literally written on that element in the markup.:dir(rtl)matches whenever the element's directionality resolves to right-to-left — even ifdiris inherited from an ancestor or computed fromdir="auto".
Elements without an explicit dir inherit directionality from their closest ancestor that has one. In that case [dir=rtl] does not match the inheriting child (the attribute isn't on it), while :dir(rtl) does. Prefer :dir() when you want to follow the effective direction rather than the raw attribute.
The flip side is browser support: :dir() is newer, so when you need a fallback for very old engines, the attribute selector is the safer bet.
Version
Syntax
CSS :dir() syntax
:dir(ltr) {
css declarations
}Example of the :dir() selector:
CSS :dir() code example
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
<style>
div:dir(ltr) {
background-color: #1c87c9;
}
div:dir(rtl) {
background-color: #8ebf42;
}
</style>
</head>
<body>
<h2>:dir() selector example</h2>
<div dir="rtl">
<span>example1</span>
<div dir="ltr">
example2
<div dir="auto"> ففي </div>
</div>
</div>
</body>
</html>Here the outer <div dir="rtl"> makes its block right-to-left, so it is styled green by div:dir(rtl). The inner <div dir="ltr"> overrides that to left-to-right and is styled blue by div:dir(ltr). The innermost <div dir="auto"> contains Arabic text, so its direction resolves to right-to-left and it too turns green — something [dir=rtl] could never catch.
Inheriting direction without repeating the attribute
A practical use of :dir() is styling deeply nested content where only an ancestor carries the dir attribute. Every paragraph below inherits rtl, yet none of them declare it:
<!DOCTYPE html>
<html>
<head>
<title>Inherited direction</title>
<style>
p:dir(rtl) {
border-inline-start: 4px solid #8ebf42;
padding-inline-start: 10px;
}
</style>
</head>
<body dir="rtl">
<article>
<p>مرحبا بالعالم</p>
<p>هذه فقرة أخرى</p>
</article>
</body>
</html>[dir=rtl] p would work here only because the ancestor is matched first, but p[dir=rtl] would match nothing — the paragraphs never carry the attribute. p:dir(rtl) matches them directly. Pairing it with logical properties like border-inline-start keeps the design correct in both directions automatically.
This pseudo-class is supported in all modern browsers, including Chrome, Edge, Safari, and Firefox.
Related concepts
- CSS
directionproperty — set text direction directly in CSS. - CSS
:lang()pseudo-class — select elements by language, which often goes hand in hand with direction. - CSS selectors — the full list of selectors you can combine with
:dir().