How dir="auto" works
Learn how dir="auto" finds the first strong character, skips nested boundaries, handles empty text and fails on misleading prefixes.
Guide13 min read
dir="auto" does one specific job: it gives unknown text a base direction from the first strongly directional character the browser finds. It does not detect language, count scripts or decide which direction represents most of the sentence.
That rule makes auto useful for a discussion post that may be Arabic or English. It also makes it predictably wrong for an Arabic post that opens with a Latin course name. The value is a heuristic, not a universal replacement for rtl and ltr.
Use it where text direction is genuinely unknown. When the application, author or schema already knows the direction, declare that answer instead.
The algorithm in one sentence#
The browser scans the relevant text in logical order, ignores characters and subtrees that do not participate in the decision, and stops at the first character with strong LTR or RTL directionality.
<p dir="auto">نص يحدده المتصفح من أول حرف قوي</p>The first strong character is Arabic, so the paragraph resolves RTL.
<p dir="auto">A paragraph whose first strong character is Latin.</p>This one resolves LTR.
The dir attribute documentation on MDN describes auto as first-strong direction detection for content whose direction is not known in advance. W3C's structural direction guide recommends it for inserted text and form content with unknown direction.
The resolved direction becomes the element's base direction and is directionally isolated from surrounding content. It influences the ordering of bidi runs, punctuation at boundaries and default alignment. It is not just a shortcut for text-align.
Strong, weak and neutral characters#
“First character” is shorthand. The first code point in the string may not decide anything.
Strong characters establish a directional type. Arabic and Hebrew letters provide an RTL signal; Latin letters provide an LTR signal. The browser skips past characters that are weak or neutral for this decision.
Common prefixes that do not settle the result include:
- spaces and line breaks;
- common punctuation;
- emoji;
- Western digits;
- many currency marks, mathematical symbols and separators.
This post still resolves RTL because the browser scans past the leading emoji and punctuation:
<p dir="auto">✨ ... مرحبًا بكم في النقاش</p>This one resolves LTR because the first strong character after the neutral prefix is Latin:
<p dir="auto">✨ ... Welcome to the discussion</p>Do not strip neutral characters before rendering. The browser already skips them for the decision, and removing them mutates the user's content.
The first strong character wins#
The scan stops as soon as it finds a strong character. It does not reconsider the answer after reading the rest of the content.
<p dir="auto">OrbitLab كانت التجربة مفيدة لكن التعليمات غير واضحة</p>The Latin O makes the whole paragraph resolve LTR even though the remaining sentence is Arabic. That is correct first-strong behavior and may be the wrong product outcome.
The reverse also happens:
<p dir="auto">التصميم الجديد was the topic of our English report.</p>The opening Arabic quotation makes the paragraph resolve RTL. dir="auto" cannot infer which part is a quotation and which language owns the sentence.
The fix is not a more forceful CSS rule. If the product knows the post language, render dir="rtl" or dir="ltr". If the direction is truly unknown, accept first-strong as the fallback and provide an author or moderator override for valid exceptions.
W3C guidance on direction metadata for strings recommends carrying an explicit string direction when it is available instead of repeatedly relying on a heuristic.
No strong character means LTR base direction#
An element can contain only digits, spaces and punctuation, with no strong LTR or RTL letter. The algorithm still needs a base direction.
In Chromium 151, measured on 2026-09-24, an ordinary dir="auto" element containing only Western digits and punctuation resolves LTR:
<span dir="auto">684 22 701</span>Do not interpret that result as proof that the value is semantically LTR. A spaced identifier may need an explicit LTR boundary to preserve its fixed group order. A numeric range embedded in Arabic can have a different reading-order requirement. Direction comes from the value's meaning when the schema knows it.
The no-strong case has an additional browser edge inside <textarea> and <pre>. W3C's guide notes that a paragraph with only digits gets an LTR base direction while alignment has varied between browser engines. Test the supported browsers if alignment of numeric-only lines matters.
For empty elements, the same absence applies. An empty auto-direction input begins with its fallback direction until the user types a strong character.
The browser scans descendant text#
dir="auto" is not limited to a direct text node. The browser can find the first strong character in ordinary descendants.
<article dir="auto">
<span class="status-icon" aria-hidden="true">●</span>
<p>هذا التعليق يحدد اتجاه البطاقة</p>
</article>The symbol is neutral, so scanning continues into the paragraph. Its Arabic letter makes the article RTL.
That behavior creates a component boundary problem. If the wrapper also contains a fixed English label before the unknown post, the label decides the result:
Problem
<article dir="auto">
<p class="type-label">Student note</p>
<p class="note-text">...</p>
</article>Better
<article>
<p class="type-label">Student note</p>
<p class="note-text" dir="auto">...</p>
</article>The better example puts the heuristic on the unknown content itself. The fixed interface label keeps the surrounding document direction and cannot take over the note.
Use the smallest block that owns one directional string. A page shell, card grid or comment list is too broad when its children can have independent directions.
Some descendant subtrees are skipped#
The scan does not treat all nested text equally. HTML skips content inside certain boundaries when deciding an ancestor's automatic direction.
According to MDN's dir reference and the W3C direction tests, the scan skips text inside:
<bdi>elements;<script>and<style>elements;<textarea>elements;- elements with their own valid
dirattribute.
This is deliberate. A nested value that declares or determines its own direction should not choose the direction of its parent.
<p dir="auto">
<bdi>OrbitLab</bdi>
مرحبًا بكم في مساحة المقرر
</p>The Latin text inside <bdi> is isolated and skipped for the parent's decision. The next eligible strong character is Arabic, so the paragraph resolves RTL.
Remove <bdi> and the Latin brand name becomes eligible, making the parent LTR. That change can surprise a developer who treats <bdi> as a visual wrapper rather than part of the direction algorithm.
An ordinary nested <span> is not skipped unless it has its own valid dir. Its text participates in the parent's scan.
dir="auto" also isolates#
Detection and isolation happen together. An element with dir="auto" establishes its own directional boundary so its mixed content does not merge unpredictably with the surrounding bidi run.
That makes it suitable for an unknown inline value:
<p dir="rtl">
نشر <span dir="auto">OrbitLab</span> تحديثًا جديدًا
</p>The span determines its own base direction and is isolated from the Arabic sentence.
A plain span does neither:
<p dir="rtl">
نشر <span>OrbitLab</span> تحديثًا جديدًا
</p>R021 reports unisolated bidi hazards such as phones, emails and Latin tokens inside Arabic text.
When the value has no existing semantic wrapper, <bdi> is the clearer inline element. It is isolated and defaults to automatic direction. These two forms express similar behavior:
<bdi>OrbitLab</bdi>
<span dir="auto">OrbitLab</span>Use <bdi> for an isolated value such as a display name. Use dir="auto" on an existing semantic element when that element already owns the unknown content.
auto is a value, not an inherited answer#
The literal auto state belongs to the element carrying the attribute. Once the browser resolves it, descendants without their own direction boundary inherit the resulting base direction, not a request to rescan themselves independently.
<article dir="auto">
<h3>عنوان عربي يحدد اتجاه المقال</h3>
<p>English text inside the resolved RTL article.</p>
</article>The heading makes the article RTL. The paragraph inherits that base direction even though its own first strong character is Latin. If the paragraph should choose independently, give it its own dir="auto" or explicit dir="ltr".
This distinction matters in lists. Putting dir="auto" on the list does not independently detect every item. Put it on each item or each text field whose direction can differ.
Avoid stamping dir="auto" on every descendant. Independent boundaries are useful only where the content model permits independent directions. Excess boundaries complicate punctuation and layout without adding information.
CSS visual order does not redefine the content#
Automatic direction follows the element's logical text content. CSS can move boxes without rewriting that content order.
Consider a card whose DOM begins with a Latin course code and then an Arabic description:
<article class="course-card" dir="auto">
<span class="course-code">BIOX</span>
<p class="course-description">وصف عربي للمقرر</p>
</article>The Latin code is the first eligible strong text. Moving the Arabic description above it with flex order, grid placement or absolute positioning does not turn the description into the first text node in logical order. Do not use visual rearrangement to influence direction detection.
The correct fix depends on the content model:
- if the card is an Arabic interface component, inherit RTL on the card and isolate the course code;
- if only the description has unknown direction, move
dir="auto"to the description; - if the entire card represents one externally supplied string, keep the string in one direction boundary and render metadata outside it.
This is also an accessibility issue. A visual reorder that attempts to “fix” direction can make screen-reader and keyboard order diverge from the composition. Keep DOM order semantic, then give each independent string the correct dir boundary.
When debugging, inspect the source order of eligible text, not only what appears at the top or inline start of the rendered card.
<bdi> defaults to automatic direction#
<bdi> is unusual among HTML elements: its direction defaults to auto rather than inheriting from the parent. W3C's test inventory calls this behavior out directly.
<p dir="rtl">
<bdi class="participant-name">Lina</bdi>
<span>أضافت ردًا</span>
</p>The name resolves from its own first strong character and stays isolated. You do not need to add dir="auto" to the <bdi> unless being explicit improves the component API.
When the direction is known, set it explicitly:
<bdi dir="ltr">COURSE-Z8-54</bdi>The program code is an LTR machine value by contract, so detection would add no value.
Do not use <bdi> for a whole document or ordinary layout container. Its purpose is isolating a value whose direction may differ from its surroundings.
Inputs resolve as the user types#
An input can use dir="auto" when it accepts text in more than one direction:
<label for="discussion-search">Search discussions</label>
<input
id="discussion-search"
name="query"
type="search"
dir="auto"
>An Arabic first strong character resolves the control RTL; a Latin one resolves it LTR. The direction can change when editing removes the decisive character and exposes a different first strong character.
This is appropriate for a multilingual search field or free-form message. It is not appropriate for every field in an Arabic interface.
Known Arabic names, addresses and notes should inherit RTL. Email, URL and phone fields should remain LTR. Fixed-format codes should follow their schema. R023 reports text inputs rendered LTR where Arabic input is expected. R070 reports tel, email or url inputs rendered RTL.
Do not attach an input handler that rewrites style.direction after every keystroke. The browser already resolves auto, and users may have a browser command to set direction manually. A script can fight that choice and create caret jumps.
Empty inputs expose the placeholder edge#
Before the user types, an auto-direction input has no strong character. In that measured version it resolves LTR. An Arabic placeholder can therefore be drawn at the left edge even on an RTL page.
<input
type="text"
dir="auto"
placeholder="اكتب سؤالك هنا"
>Typing Arabic changes the control to RTL. Typing a Latin letter or only digits keeps it LTR.
This behavior is not evidence that auto is broken. The content is empty, so first-strong has no signal. Choose the field contract:
- if the field is expected to be Arabic, inherit or set RTL;
- if it is genuinely multilingual, accept the empty fallback and design the placeholder deliberately;
- if the placeholder must follow the interface while entered text is automatic, use a separate visual label rather than asking one direction state to represent two different strings.
Test focus, placeholder, first character, deletion back to empty and pasted text. A screenshot of the filled state misses the transition.
<textarea> and <pre> work per paragraph#
Multiline plain text needs finer behavior than one direction for the whole element. For <textarea dir="auto"> and <pre dir="auto">, the browser determines direction separately for each paragraph. This is documented by MDN and W3C's direction guidance.
<textarea dir="auto" name="lesson-notes"></textarea>An Arabic paragraph can resolve RTL while the next English paragraph resolves LTR. A single-line <input> has no equivalent set of separate paragraphs.
Test:
- Arabic followed by English;
- English followed by Arabic;
- a paragraph beginning with an opposite-script quotation;
- a blank paragraph between two directions;
- a digits-only paragraph;
- pasted text using the newline forms the product accepts;
- caret and selection across the paragraph boundary.
Do not assume the control has one direction value suitable for every stored paragraph. If the application renders those paragraphs later as structured HTML, preserve paragraph boundaries and apply direction at that level.
Dynamic content can change the result#
The resolved direction is based on current content. If the decisive character changes, the browser can recompute the element's direction, a behavior covered by W3C's direction test inventory.
<p id="live-caption" dir="auto"></p>const caption = document.querySelector("#live-caption");
caption.textContent = "Welcome";
// Resolved direction is LTR.
caption.textContent = "مرحبًا";
// Resolved direction is RTL.This is useful for live comments and search suggestions, but it can move alignment while content updates. Reserve space and use logical layout so a direction change does not overlap adjacent controls.
Frameworks should set text as text rather than inject unsanitized HTML. If rich content is allowed, sanitize it before rendering because nested dir and <bdi> boundaries participate in the algorithm.
Test transitions, not only final states. Update LTR to RTL, RTL to LTR, text to numeric-only and content to empty. Verify computed direction and component geometry after each change.
Server rendering can use auto directly#
The server does not need to predict first-strong direction before emitting HTML. It can render a safe text node inside a dir="auto" boundary, and the browser resolves direction as it parses and lays out the page.
<article class="discussion-post" dir="auto">
<!-- Escaped post text is rendered here by the server. -->
</article>That avoids a client-only direction correction after hydration. It also prevents the server and browser from using different character tables or different definitions of “RTL character.”
Hydration should preserve the attribute. Do not replace auto with a cached ltr or rtl value unless the application has trusted direction metadata that is more authoritative than the heuristic.
If explicit metadata exists, emit it immediately:
<article class="discussion-post" lang="ar" dir="rtl">
<!-- Known Arabic post text. -->
</article>The hierarchy is simple: explicit trusted metadata first, browser auto second, custom script detection only when HTML cannot solve the rendering boundary.
Test the server response separately from the hydrated application. Confirm that the attribute is present in initial markup, the first paint has the intended direction, and a client update does not introduce a contradictory CSS direction rule.
auto does not detect language#
Direction answers how bidi runs and boundaries should be arranged. Language supports pronunciation, spellchecking, translation, font choice and locale-specific behavior. They are separate metadata.
This markup is incomplete if the content language is known:
<p dir="auto">...</p>Use both attributes when both answers are available:
<p lang="ar" dir="rtl">...</p>
<p lang="en" dir="ltr">...</p>Do not set lang from the resolved direction. RTL could represent Arabic, Persian, Urdu, Hebrew or another RTL language. LTR covers many unrelated languages. The first-strong result contains no language identity.
For content with unknown language and direction, dir="auto" can still improve bidi rendering. Leave language unknown rather than inventing one from script direction.
Capture direction when a form submits#
The dirname attribute asks the browser to submit a control's direction alongside its value. MDN documents the attribute and its ltr or rtl form value.
<textarea
name="discussion-post"
dir="auto"
dirname="discussion-post.dir"
></textarea>The server receives the post and a discussion-post.dir field. Validate that field against a closed set, store it with the content and render it later as explicit direction when appropriate.
This avoids rerunning first-strong in every output channel. A web page, moderation tool, email and export can share the producer's direction choice.
One direction value cannot describe every paragraph of a multilingual textarea. If paragraph direction must survive, store structured paragraphs or other trusted direction metadata at that granularity.
Read declared and resolved direction correctly#
There are two different facts to inspect:
element.dirorgetAttribute("dir")tells you the declared HTML value, such asauto;getComputedStyle(element).directiontells you the resolvedltrorrtlrendering direction.
// post is an element declared with dir="auto".
const declared = post.getAttribute("dir");
const resolved = getComputedStyle(post).direction;For an Arabic post, declared remains auto while resolved becomes rtl. Do not write a test expecting the DOM attribute to mutate to rtl.
The :dir() pseudo-class lets CSS and JavaScript query directionality:
.discussion-post:dir(rtl) {
border-inline-start: 0.25rem solid var(--accent);
}// post is the discussion element under test.
const isResolvedRtl = post.matches(":dir(rtl)");--accent should come from the application's theme. Keep styling logical so the same component can respond when dynamic content changes direction.
Test the algorithm, not just alignment#
Build a fixture set that reaches the actual branches:
| Fixture | Expected result |
|---|---|
| Arabic letter first | RTL |
| Latin letter first | LTR |
| Emoji and punctuation before Arabic | RTL |
| Western digits and punctuation only | LTR base in the measured browser |
| Latin course name before Arabic sentence | LTR under first strong |
| Arabic quotation before English sentence | RTL under first strong |
<bdi> name before Arabic sibling text | Parent ignores the isolated name |
Nested element with explicit dir before Latin text | Parent skips that nested boundary |
| Empty input | No strong signal; test the browser fallback |
| Multiline textarea | Resolve each paragraph independently |
For each important case, assert the declaration and computed result:
// page and expect are supplied by the browser test runner.
const post = page.locator("[data-test=arabic-post]");
await expect(post).toHaveAttribute("dir", "auto");
const state = await post.evaluate(element => ({
direction: getComputedStyle(element).direction,
matchesRtl: element.matches(":dir(rtl)"),
}));
expect(state.direction).toBe("rtl");
expect(state.matchesRtl).toBe(true);Then inspect punctuation, mixed values and component geometry. A right-aligned screenshot does not prove that isolation and bidi ordering are correct.
Run product-critical edges in every supported browser. The browser-specific results in this guide were measured in that version only; the linked HTML guidance describes the target behavior, while the supported matrix remains the product's responsibility.
Know when not to use auto#
Use an explicit direction instead when:
- the page or component language is known;
- a machine identifier has fixed LTR group order;
- a field accepts a known value type such as email or URL;
- stored content already carries trusted direction metadata;
- a valid sentence begins with an opposite-direction brand, code or quotation;
- product policy chooses a direction independently from the first character.
Use auto when:
- user or CMS text can arrive in either direction;
- no trusted direction metadata exists;
- first-strong behavior is acceptable for the product;
- the boundary contains only the unknown string, not fixed interface text;
- the team has tested empty, neutral-only and misleading-prefix cases.
Do not use CSS direction as a detector. CSS applies a value; it does not inspect content. Do not count Arabic characters and call the result equivalent to HTML either. Majority-script and first-strong heuristics answer different questions.
Use the heuristic at the right boundary#
dir="auto" is predictable once its boundary and scan rules are clear. It takes the first eligible strong character, skips nested directional boundaries, isolates the result and falls back when no strong signal exists. The difficult part is deciding whether that heuristic represents the content's real direction.
A Ritla scan can surface mixed-direction and field-direction failures after automatic content is rendered, including unisolated values that a plain wrapper leaves exposed. Use the bidirectional text guide for inline boundary decisions, and the HTML dir="rtl" guide for the document direction that surrounds auto-detected content.