In HTML, what problem does the <bdi> element solve, and how does it differ from <bdo>?
answer
- untrusted strings inside your sentence
- neutral characters follow the strong run
- one isolates, one overrides
- direction detected from content
- the override needs an explicit direction
basics
~20 sThe bdi element isolates a run of text whose direction you do not control, such as a username, so it cannot reorder the characters around it. The bdo element does the opposite: with a required dir value it overrides direction and forces rendering order.
solid answer
~50 s`<bdi>` isolates a run of text whose direction you do not control — typically user-generated content such as a username — so the Unicode bidirectional algorithm cannot let it reorder the characters around it. Its `dir` defaults to `auto`, so the direction is detected from the content itself. The classic bug is a template like `<bdi>NAME</bdi> — 12 points`: without isolation, a Hebrew or Arabic name can drag the dash and the number to the wrong side of the line, so the score appears to belong somewhere else. `<bdo>` is the opposite tool: it takes a required `dir` of `ltr` or `rtl` and overrides the algorithm, forcing the characters to render in that order. You reach for `<bdo>` rarely, mostly to demonstrate or repair one specific string, and for `<bdi>` whenever you interpolate text of unknown direction into a sentence.
code
html · 6 lines<ul>
<li><bdi>שרה</bdi> - 12 points</li>
<li><bdi>Ana</bdi> - 9 points</li>
</ul>
<p><bdo dir="rtl">Rendered in reverse order</bdo></p>go deeper
Know that HTML has elements for mixed-direction text and that user-supplied names may need isolating, without being expected to recall the details under pressure.
Explain the mechanism: neutral characters such as dashes and digits join the adjacent strong run, so isolating an interpolated string keeps the surrounding template in order.
Demonstrate that you treat every interpolation of outside text as a bidi risk, wrap it at the component boundary, and test with right-to-left fixtures rather than waiting for reports from a subset of users.
Own internationalisation as a system property: one interpolation helper that isolates by default, right-to-left data in the standard fixture set, and a review habit that treats bidi defects as a template concern rather than a translation afterthought.
## The bug these elements exist for Browsers lay out mixed-direction text with the Unicode bidirectional algorithm. Characters that have a strong direction — Latin letters are left-to-right, Hebrew and Arabic letters are right-to-left — pull the neutral characters near them (spaces, dashes, digits, punctuation, parentheses) into their own run. That is exactly what you want inside a sentence written in one language, and exactly what you do not want when you have concatenated a string you did not write into a template you did. The canonical failure looks like this: ```html <p>USERNAME - 12 points</p> ``` With an ASCII username this reads as intended. With a right-to-left username, the dash and sometimes the number are neutral characters adjacent to a strong RTL run, so the algorithm reorders them: the score appears attached to the wrong side, or the dash jumps to the far end of the line. Nothing is broken in your data — the *display order* is wrong, and it is wrong only for the users whose names caused it, which is why it survives review. ## What `<bdi>` does `<bdi>` is the **bidirectional isolate** element. Its purpose is stated in its name: the content inside it is treated as a self-contained run, so its directionality cannot influence the ordering of text outside it, and the surrounding direction does not reorder its insides either. It also carries a default of `dir="auto"`, which means the direction of the content is inferred from its first strong character rather than inherited. That combination is precisely the contract you want for interpolated content: ```html <li><bdi>שרה</bdi> - 12 points</li> <li><bdi>Ana</bdi> - 9 points</li> ``` Both rows now render with the dash and the score where the template author intended, whatever the name's script. Because the element renders as ordinary inline content with no visible decoration, adding it is cheap and invisible for the majority of your users — which is the argument for putting it in the component rather than waiting for a bug report. ## What `<bdo>` does `<bdo>` is the **bidirectional override**. It requires a `dir` attribute of `ltr` or `rtl`, and it forces the characters inside to be laid out in that direction, overriding what the algorithm would have decided from the characters themselves: ```html <p><bdo dir="rtl">This text is laid out right to left</bdo></p> ``` This is a blunt instrument. It does not translate, it does not mirror meaning — it reverses the ordering of the rendered characters. Legitimate uses are narrow: demonstrating bidirectional behaviour in documentation, or repairing a specific string that arrives with its ordering already mangled by an upstream system. Using `<bdo>` on user content in the hope of "fixing" direction is a mistake, because you are asserting a direction you do not actually know. ## Where the `dir` attribute fits `dir` is a global attribute with the values `ltr`, `rtl` and `auto`. Setting `dir="auto"` on an element asks the browser to infer direction from the content, and in modern browsers an element that carries an explicit `dir` also gets isolated from its surroundings. So `<span dir="auto">` behaves similarly to `<bdi>` in practice. Why prefer `<bdi>` anyway? Because it states the intent — *this is a run of text whose direction I do not control* — in the element name rather than in an attribute a later editor might strip while "cleaning up" the markup, and because it carries the auto behaviour without anyone having to remember to add it. In an interview, name both facts: the isolation is what matters, and `<bdi>` is the element whose whole reason for existing is to provide it. ## How to talk about it as production judgment The senior framing is not "I memorised an obscure element". It is: any place where your template concatenates a string from outside your control with text you wrote is a potential bidi defect, and the defect is invisible in a monolingual test suite. Names, search terms, filenames, tags, book and song titles, chat messages, addresses — all of them belong in `<bdi>` at the component boundary. It is the same instinct as escaping output: you do it structurally, once, at the point of interpolation, rather than reacting to reports. ## Pitfalls Using `<bdo dir="ltr">` to "fix" an RTL name — this forces the name's own characters into the wrong order, so you have traded a misplaced dash for a mangled name. Setting `dir="ltr"` on the whole line, which establishes the paragraph direction but does not isolate the embedded run that caused the problem. Replacing spaces with ` `, which changes nothing because non-breaking spaces are still directionally neutral. And assuming the issue is a font or a CSS problem — the ordering is decided by the bidirectional algorithm operating on characters, and the markup is where you constrain it.
- Does setting dir="auto" on a <span> achieve the same thing as <bdi>?In modern browsers it is close: an element with an explicit `dir` is isolated from its surroundings, and `auto` infers direction from the content. The reasons to prefer `<bdi>` are that isolation and auto-detection are its defined purpose rather than a side effect of an attribute, and that the intent survives editing — nobody deletes an element the way they delete an attribute they do not recognise.
- Why is <bdo dir="ltr"> the wrong fix for a misordered right-to-left username?Because it overrides rather than isolates. Forcing left-to-right layout on Hebrew or Arabic characters renders the name itself in the wrong order, which is worse than a misplaced dash — you have corrupted the user's own name to tidy your template. `<bdi>` fixes the interaction between the two runs while letting each render correctly on its own terms.
- How would you catch bidi ordering bugs before users report them?Treat every interpolation point as suspect and seed test data with right-to-left strings — names, search terms, filenames, tags — rather than ASCII placeholders. A monolingual fixture set will never show the defect. The structural fix is to wrap interpolated text in `<bdi>` inside the component that renders it, so correctness does not depend on each caller remembering.
saying these in an interview costs you the question
- Thinks it is a font or CSS rendering problem
- Uses bdo to force direction on user content
- Believes setting dir on the container isolates inner runs
- Assumes non-breaking spaces stop the reordering
- Says the stored data itself is corrupted