Arabic text input direction
Choose RTL, LTR or automatic direction for Arabic text inputs and textareas, diagnose CSS overrides and test editing, placeholders and restored values.
By Omran Khleifat, Founder of Ritla
Guide13 min read
An archive editor right-aligns every field on its Arabic page. The catalogue summary looks Arabic, but its input still declares LTR. A curator edits the sentence, adds punctuation and finds that the field's reading context does not match the text they are composing. Moving the value to the right edge concealed the direction problem.
Choose direction from what a field accepts. Arabic catalogue prose can use RTL, a title accepting Arabic or English can use automatic direction, and a source URL should stay LTR. The surrounding interface can remain Arabic throughout.
The distinction matters after the first screenshot. An empty field, a pasted title and a reopened record can expose different parts of the same implementation. This guide follows those states in an archive-record editor, including the difference between the direction of editable text and its later preview.
Choose a field policy before setting attributes#
Direction describes the base reading context of a value. It is not a declaration that the interface is translated, a restriction on accepted characters or an instruction to reverse stored text.
Use a policy tied to each field's purpose:
| Archive field | Accepted content | Direction policy |
|---|---|---|
| Arabic catalogue summary | Prose requested in Arabic | RTL |
| Collection display title | Arabic or English title | Automatic |
| Research note | Multilingual plain text | Automatic, with multiline testing |
| Source URL | A URL in the service's accepted format | LTR |
| Storage reference | A defined Latin-and-digit identifier | LTR |
A name or address field does not become Arabic-only because its label is Arabic. If either language is accepted, choose a policy that supports that content. Conversely, a field specifically collecting an Arabic description need not wait for its first character to establish the intended direction.
Set the Arabic document or embedded editor's language and direction independently. lang="ar" describes language; it does not establish RTL. W3C's structural-direction guidance explains inherited base direction. An input without its own direction normally uses that inherited context, subject to the control's type and applicable styles.
Write the policy into the field component's API or configuration. Otherwise a generic component can silently turn a deliberate field decision into whatever default its current page happens to supply.
Correct the Arabic field's direction, not just its alignment#
This archive summary is right-aligned but explicitly LTR:
Problem
<label for="catalogue-summary">ملخص الفهرسة بالعربية</label><input id="catalogue-summary" name="summary" dir="ltr" style="text-align: right" value="دفتر ملاحظات عن ترميم المخطوطات">The letters do not all turn backwards. The problem is the LTR base context around an Arabic value, including the treatment of mixed runs and punctuation. Seeing joined Arabic letters at the right edge is not proof that the control has an RTL reading context.
Use the field's Arabic policy
<label for="catalogue-summary">ملخص الفهرسة بالعربية</label><input id="catalogue-summary" name="summary" dir="rtl" style="text-align: start" value="دفتر ملاحظات عن ترميم المخطوطات">These are alternative versions of the same field, not controls to mount together with duplicate IDs. The second declares RTL and aligns to its start. Remove any conflicting shared direction rule too; an HTML attribute is not a guarantee that author CSS cannot contradict the rendering.
Test a complete summary, including its final punctuation, then insert a word in the middle. Check the computed direction as well as the visible result. Do not reverse the string or add spaces to push it toward the intended edge.
If this field later accepts English summaries too, revisit its content policy. A fixed Arabic direction is justified by the requested content, not by the route name alone.
Automatic direction follows the value's strong characters#
The collection title accepts either language:
<div lang="ar" dir="rtl"> <label for="collection-title">عنوان المجموعة</label> <input id="collection-title" name="title" type="text" dir="auto"></div>For this input, automatic direction examines the value. Arabic strong characters establish RTL when no LTR strong character precedes them; a Latin opening establishes LTR. Digits, spaces and ordinary leading punctuation do not themselves choose Arabic. The HTML directionality algorithm defines that behavior.
Use fixtures that separate those cases:
| Entered title | Direction without a conflicting CSS override |
|---|---|
رسائل من بستان المدينة | RTL |
Orchard correspondence | LTR |
37 رسائل من بستان المدينة | RTL |
37 | LTR |
Orchard رسائل من بستان المدينة | LTR |
The last title is deliberately mixed. Automatic direction does not count which language occupies more of the value, identify its subject or infer the curator's intention. Its first strong character controls the element's directionality.
That limit is a reason to choose the policy carefully, not to add an event handler that continually guesses the language. If a multilingual title can intentionally begin with a foreign name while retaining an Arabic base direction, consider an explicit direction choice in the editor. Define how that choice is stored and restored rather than silently fighting it on the next keystroke.
For the broader algorithm and non-input content, continue with how automatic direction works.
An Arabic placeholder does not settle an empty field's direction#
Adding an Arabic placeholder to the title does not make the entered value Arabic:
<label for="collection-title">عنوان المجموعة</label><input id="collection-title" name="title" dir="auto" placeholder="اكتب عنوان المجموعة">Use this as an alternative to the earlier title fragment. Keep its persistent label; the placeholder is only a temporary entry hint.
The measured browser observations in this guide come from Chromium 151 on September 24, 2026. Firefox and Safari were not included. In that setup, an empty automatic-direction input resolved LTR, with its Arabic placeholder at the left edge. Entering Arabic changed the field to RTL; entering Latin letters or digits kept it LTR.
An Arabic hint at the left edge can therefore be consistent with an intentionally automatic field. Do not change the value policy to fixed RTL just to make its empty screenshot look like the Arabic-only summary.
Test empty, focused, populated and cleared states separately. If the empty presentation is unacceptable to the design, move the explanation into associated help outside the value area or reconsider whether the field really accepts both languages. Styling a hint cannot supply a missing content policy.
Do not use placeholder text as a custom direction detector. It describes how to answer, not what the curator has entered, and it disappears during editing.
Let alignment follow the direction you actually chose#
Direction and alignment can disagree. A fixed right alignment keeps an LTR title at the right side of the control; it does not convert that title into RTL. A fixed left alignment can leave an Arabic field starting at the opposite edge from the intended reading layout.
For an editor where values should align to their own starting edge, scope a shared rule to its controls:
.archive-editor input,.archive-editor textarea { text-align: start;}Apply the class to the archive editor's container. In horizontal text, start means left for LTR and right for RTL, as MDN's text-alignment reference explains. The rule preserves left alignment for LTR fields while allowing RTL fields to start on the right.
A product may deliberately right-align a machine value. That is an alignment choice; its LTR direction can remain explicit. Test editing under that choice instead of assuming the two properties must always use the same physical edge.
Keep the distinction visible in debugging notes. “Text is on the right” reports position. “The input computes to RTL” reports a different fact. Text-align start versus right covers the alignment decision without changing the field's content contract.
Keep a shared component from overriding field decisions#
A component default can prevent inheritance before any page-specific styling runs. If every generic text field emits dir="ltr", placing the archive editor inside an RTL container will not make its Arabic summary inherit RTL. The control already declares a different policy. Make direction an explicit supported field option, and distinguish an omitted option from an automatic one.
A broad Arabic-route selector can cause the opposite problem:
[dir="rtl"] input { direction: rtl;}The selector finds inputs below an RTL ancestor, including a nested input that deliberately declares LTR. It also assigns a fixed CSS direction to the multilingual title instead of leaving the control's rendering rules alone. This is an ancestor selector, not a field-content policy.
Remove this blanket direction override when the controls already express the intended policies through markup. Keep shared styles for presentation, such as the scoped alignment rule above. Do not replace the override with an equally broad rule forcing every archive input LTR.
Test the component in three contexts: the Arabic editor, an English editor and an Arabic editor embedded inside an otherwise English page. The Arabic summary should retain its requested Arabic policy, the title should retain automatic behavior and the source URL should remain LTR in each context. This isolates component defaults from page inheritance.
Inspect the rendered control and the winning CSS#
Inspect the input itself, not only its Arabic label or component wrapper. A library may accept a direction property but apply it to an outer box while rendering an inner input with a conflicting style.
After mounting the collection-title fragment, run this diagnostic in the page's console:
const titleInput = document.getElementById("collection-title");if (!titleInput) throw new Error("Collection title input is missing");const titleStyle = getComputedStyle(titleInput); console.table({ declaredDirection: titleInput.getAttribute("dir"), semanticRTL: titleInput.matches(":dir(rtl)"), computedDirection: titleStyle.direction, alignment: titleStyle.textAlign, currentValue: titleInput.value});The attribute records the declared policy, which can still be auto after the resolved direction becomes RTL. The computed property records the CSS result. In the measured behavior, CSS direction alone did not change matching by :dir(), so disagreement between semantic matching and computed direction is useful evidence of a conflicting layer.
Inspect the winning declaration in DevTools rather than adding a broader override immediately. Check component styles, utility classes, inline styles and rules applied during validation or focus. Remove the incorrect scope at its source where possible.
Repeat after entering Arabic and English values. A snapshot of an empty control cannot verify automatic behavior. If a framework replaces the element during rendering, inspect the new node too; an earlier console reference can still point to the detached control.
Input type and keyboard choice do not replace direction#
In the measured behavior, text, search, email, URL, password and number inputs inherited direction without an explicit declaration. Telephone inputs defaulted to LTR. Do not generalize that telephone behavior to every field holding a machine-format value.
The archive's source URL should declare its value direction while its label remains Arabic:
<div lang="ar" dir="rtl"> <label for="source-url">رابط المصدر</label> <input id="source-url" name="sourceUrl" type="url" dir="ltr"></div>Test a source such as https://records.example/collections/orchard-notes by typing, pasting and editing. The declaration concerns reading direction; the service still needs its own accepted URL policy.
A storage reference such as BOX-N7-584 can remain a text input with explicit LTR direction. Its letters and separators are part of the identifier. Changing it to a number input would confuse data type with direction.
Likewise, inputmode suggests an input mechanism, not a base direction or validation rule. An Arabic mobile keyboard does not establish that every destination field should be RTL. Keep keyboard choice, input type and direction separate in the component configuration and test them together on supported devices.
Multiline text needs paragraph-level testing#
Use a textarea for the archive's multilingual research note:
<label for="research-note">ملاحظة البحث</label><textarea id="research-note" name="researchNote" dir="auto"></textarea>A textarea is a plain-text editor, not a container for independently marked-up inline spans. MDN's textarea reference describes the control. Pasting markup-like text does not give individual words HTML direction attributes.
Automatic multiline rendering also has a distinction that a single-line test misses. HTML's bidirectional rendering rules specify unicode-bidi: plaintext for automatic-direction textareas. MDN explains plaintext behavior: paragraph direction is determined from the text rather than simply using one inherited paragraph direction throughout.
Test a note with an Arabic paragraph, a newline and an English paragraph, then swap their order. Include an empty line and a paragraph beginning with digits. Inspect how paragraphs align and how the caret moves between them. One computed direction value for the element does not describe every paragraph's visible bidi layout.
Do not replace the native behavior with a blanket bidi override to make all lines face one way. If the product requires richer per-paragraph formatting or embedded values with separate markup, that is an editor-model decision. A plain textarea cannot provide the same structure as a rich-text document.
Test editing across direction boundaries#
Rendering a saved value is only part of a text input's job. The curator must be able to place the caret, select text and replace a word without the application corrupting the value.
Start with the mixed collection title from the fixture table. Click around the Arabic and Latin boundary, select across it, then replace the selection. Use arrow keys, Backspace and Delete separately. Record the actual browser behavior instead of prescribing one universal physical movement for every keyboard command.
selectionStart and the related selection properties describe positions within the value. They are useful for checking what an application selected, but they do not establish the caret's visible location. Copying the value likewise checks logical content rather than its visual bidi arrangement.
Selection APIs also have type restrictions. The collection title's text input supports them; do not assume the same API is available on the email or number control you happen to be inspecting. MDN documents the supported input types.
If application code calls setSelectionRange(), its selection direction describes how the selection was made, not whether the paragraph is Arabic. A backward selection is not an RTL content policy. Test focus and visible highlighting separately from the returned offsets.
Avoid rewriting the value to repair its presentation#
Do not reverse Arabic strings before assigning them to an input. Do not reverse groups inside an identifier either. The stored value must keep the order the curator supplied; direction belongs to the rendering context.
Avoid inserting hidden direction characters into every value just to compensate for a missing attribute. That changes the content passed to search, comparison and exports. For a known Arabic summary, declare RTL. For a known LTR source, declare LTR. For a multilingual title, use its chosen automatic or explicit policy.
An input handler that resets direction from the page locale on every keystroke defeats the multilingual title's policy. A detector that treats any character in an Arabic Unicode block as an Arabic letter can also mistake digits or marks for a strong character. Native automatic direction already applies the directionality rules; do not substitute a rough script-range guess for it.
Test custom masks and controlled components with keyboard suggestions and composition. compositionend marks the completion or cancellation of a composition session. Do not assume every Arabic input method uses an identical event sequence. Reassigning transformed values while the user is composing needs testing on the input methods the product supports.
Population, restoration and reset are different paths#
A title can arrive through typing, paste, a catalogue lookup or loading an existing record. Automatic direction needs to work with the current value on every supported path, not just after a custom key handler runs.
Inspect the live value property when debugging. Reading only the initial markup can miss what the component has populated or what the curator has changed. Compare the current value, current direction policy and computed styles after loading completes.
An Arabic record loaded into the English interface still needs the summary's Arabic field policy. An English title loaded into the Arabic interface still needs the title's multilingual policy. Do not derive either from the current navigation language alone.
Test reset deliberately. Native form.reset() restores default control values; it is not a general rollback of every attribute an application changed. If code changed the input from automatic direction to a fixed direction, define whether reset should restore that policy too.
Repeat after a server rejection and after switching between two records without leaving the editor. A previous record's manual direction choice should not leak into the next title merely because the component instance was reused.
Submit direction metadata only when the product needs it#
The value and its direction policy are separate information. A service can derive automatic direction again when reopening a title, but an intentional manual choice may need persistence.
For supported controls, dirname adds a direction field during native form submission:
<label for="collection-title">عنوان المجموعة</label><input id="collection-title" name="title" dir="auto" dirname="titleDirection">This is another alternative title fragment. Inside a submitted form, its text is named title and its accompanying direction is named titleDirection, with an LTR or RTL value. The extra field describes direction, not language, and does not record whether the policy was automatic or manually fixed.
If the application needs that distinction, store the policy separately. Validate stored direction values against the choices the product supports before using them as markup. When application code builds a JSON request from state, adding an HTML attribute does not itself add a property to that custom payload.
Inspect the real request and reopen the saved record. Test an Arabic title, an English title and a cleared title. Do not add direction metadata to every schema simply because the attribute exists; use it where a later editing or rendering decision depends on it.
The preview needs its own direction boundary#
The title's input attribute does not travel with the string when the application inserts that title into a separate preview. The editor can be correct while the record summary outside it has the wrong context.
Render a known Arabic summary in an Arabic context. For a title whose direction is unknown, give the title itself an automatic boundary. Do not include its preceding Arabic field label inside the same automatic boundary: the label can determine the direction before the title is considered.
Likewise, a storage reference inserted into an Arabic preview needs the appropriate boundary there even though its editing input was LTR. This is a separate rendering decision, covered in bidi isolation. It does not justify changing the stored title or reference.
Compare the editable control and the preview using the same current value. Then save, reload and compare again. A copied string that matches in all three places establishes data consistency; inspect each visible presentation separately to establish its reading layout.
Verify transitions, not just attributes#
Use the archive fields to exercise different policies. Keep fixture values stable so a changed result can be traced to an attribute, style or state transition rather than a different sentence.
| Test | What to inspect |
|---|---|
| Open the empty multilingual title | Automatic policy, placeholder and computed direction |
| Enter Arabic, then replace it with English | Resolved direction and alignment after replacement |
| Prefix the Arabic title with digits or Latin text | First-strong behavior from the fixture table |
| Clear the title and paste a replacement | Empty-state recovery without a stale fixed direction |
| Edit across a mixed-script boundary | Selection, caret, unchanged logical text |
| Enter alternating-language paragraphs | Textarea paragraph layout and multiline editing |
| Load, reject, reset and reopen a record | Value and direction policy on each path |
| Display the value in the preview | A separate boundary around the value itself |
Run the editing tests in supported desktop and mobile browsers, including the keyboards curators use. A computed-style assertion cannot verify every caret movement, and a screenshot cannot verify the submitted value. Keep those observations separate in the bug report.
A free Ritla scan can report : Text inputs rendered LTR where Arabic input is expected, and : tel/email/url inputs rendered RTL (these must stay LTR). Editing transitions and restored values need the tests above; continue with how automatic direction works for first-strong cases or dynamic text direction when the same content moves between an editor and a preview.