Guide to CSS unicode-bidi for Arabic and Hebrew Text

This article provides an overview of the CSS unicode-bidi property and explains how it controls the rendering of bidirectional text. It covers how the Unicode Bidirectional (BiDi) algorithm processes right-to-left (RTL) languages like Arabic and Hebrew, identifies common visual layout issues when mixing different text directions, and details how the specific values of unicode-bidi—used alongside the direction property—resolve punctuation misplacement and directional bleed.

Understanding the Bidirectional (BiDi) Algorithm

Scripts such as Arabic and Hebrew are written from right to left (RTL), while scripts such as Latin are written from left to right (LTR). When these scripts are mixed in a single sentence or user interface, browsers use the Unicode Bidirectional Algorithm to determine the layout order.

The algorithm assigns strong directional properties to characters:

  • Strong RTL characters: Hebrew and Arabic alphabets.
  • Strong LTR characters: Latin, Cyrillic, and Greek alphabets.
  • Weak and Neutral characters: Numbers, punctuation, spaces, and mathematical symbols.

Neutral characters lack an intrinsic direction; their visual position is inferred from adjacent strong characters. This dynamic causes visual errors when embedding RTL names or snippets into LTR text, or vice versa, often displacing punctuation marks (such as periods, exclamation marks, or parentheses) to the wrong side of the phrase.

The Role of the unicode-bidi Property

The unicode-bidi property instructs the browser on how to treat the bidirectional levels inside an element relative to its surrounding text. It must be paired with the CSS direction property (direction: rtl; or direction: ltr;) to have an effect.

Key Values of unicode-bidi

  • normal: The default value. The element does not open an additional level of embedding; directionality is determined entirely by the standard BiDi algorithm and the inherited direction.
  • embed: Opens an additional level of embedding. The direction specified by the direction property applies inside the element, but the element still interacts with surrounding inline elements for bidirectional ordering.
  • isolate: Creates a directional boundary around the element. The text inside is calculated independently, preventing its internal directionality from affecting the positioning of adjacent punctuation or words outside the element. This is the CSS equivalent of the HTML <bdi> tag and is the standard approach for dynamic text.
  • bidi-override: Overrides the intrinsic directional properties of all characters inside the element. Characters are rendered strictly according to the specified direction property, regardless of whether they are Arabic, Hebrew, or Latin.
  • isolate-override: Combines the behavior of isolate and bidi-override. It isolates the element from its surroundings while strictly forcing the specified direction on all interior characters.
  • plaintext: Calculates directionality solely based on the first strong directional character found within the element, ignoring the parent container's direction property. If the element begins with Arabic or Hebrew, it renders as RTL; if it begins with Latin, it renders as LTR.

Practical Handling of Hebrew and Arabic

Fixing Punctuation and Spillover with isolate

When displaying a Hebrew or Arabic phrase inside an English paragraph, trailing punctuation often jumps to the beginning of the RTL phrase because the browser considers the punctuation part of the surrounding LTR flow.

.user-name {
  direction: rtl;
  unicode-bidi: isolate;
}

Applying unicode-bidi: isolate ensures that an Arabic name such as "محمد!" does not let the exclamation mark spill into the surrounding English sentence structure.

Formatting Codes and Keys with bidi-override

In cases where numbers, serial codes, or mixed strings must read in a strict sequence regardless of script rules (such as an Arabic product code that must be displayed strictly from left to right):

.serial-number {
  direction: ltr;
  unicode-bidi: bidi-override;
}

This prevents the browser from reversing segments containing Arabic or Hebrew letters within the code.

Dynamic Feeds with plaintext

In applications with user-generated content where the language is unknown at render time (e.g., chat messages or social feeds):

.message-body {
  unicode-bidi: plaintext;
}

The browser evaluates the text on a line-by-line basis. If a user posts in Arabic or Hebrew, the container automatically aligns and flows right-to-left without requiring server-side language detection.