Email inputs in RTL forms
Configure email fields in Arabic forms with LTR entry, Arabic labels and errors, email autocomplete and editing behavior that preserves the address.
By Omran Khleifat, Founder of Ritla
Guide13 min read
A printmaking studio's Arabic waitlist form contains an email input without a direction declaration. It inherits RTL. A saved Latin address may still look intact, so a screenshot of the completed form does not expose the field's base direction. Empty entry, editing and the surrounding instructions need checking too.
Give the address an explicit LTR context while keeping the label, help and validation messages Arabic. type="email" describes the kind of value and supplies browser behavior; it does not give the field the LTR default that telephone inputs receive.
This guide follows the studio's waitlist email from entry to confirmation. The fixture bookings+weekend@inkharbor.example exercises an address containing a plus tag. It is sample data for the form, not a mailbox for delivery tests. The field should preserve the address while making its purpose and any correction instructions understandable in Arabic.
Declare direction on the email control#
An Arabic wrapper does not give an email field its own direction policy:
Inherited RTL
<div lang="ar" dir="rtl"> <label for="waitlist-email">البريد الإلكتروني لقائمة الانتظار</label> <input id="waitlist-email" name="email" type="email"></div>The input inherits the surrounding direction. Do not assume that an address's technical syntax makes every browser control containing it LTR. Declare the intended context:
LTR value with Arabic instructions
<div class="waitlist-field" lang="ar" dir="rtl"> <label for="waitlist-email">البريد الإلكتروني لقائمة الانتظار (مطلوب)</label> <input id="waitlist-email" name="email" type="email" dir="ltr" autocomplete="email" spellcheck="false" required aria-describedby="waitlist-email-help waitlist-email-error"> <p id="waitlist-email-help">سنرسل إلى هذا العنوان عند توفر مكان في الدورة.</p> <p id="waitlist-email-error"></p></div>Use the second fragment inside the application's form; the fragments are alternatives, not fields to mount together with duplicate IDs. The dir attribute belongs on the control whose value needs that context. Putting LTR on the entire field wrapper would also change the inherited context of its Arabic text.
The browser observations in this guide were measured in Chromium 151 on September 24, 2026. Firefox and Safari were not measured. In that setup, email inputs inherited page direction unless told otherwise. Check the actual rendered control in the browsers your product supports.
Do not invent a reversed-address failure#
An RTL email field does not necessarily reverse every character or move every address component. Latin letters form LTR runs within a bidi context. The fixture's visible text can remain recognizable even when the field's base direction is unsuitable for the intended entry experience.
Separate the claim you can establish from the behavior you need to observe. Inspect the computed direction to establish whether the input is RTL or LTR. Type and edit the exact fixture to inspect its presentation, caret and punctuation. Do not publish a supposed reversed rendering that has not been measured for that string.
Test an empty control as well as a populated one. Then replace part of the local part, move into the domain and paste a complete replacement. The field must support correction, not only display a final address that happened to conceal its inherited context.
Copying the address checks logical content rather than visual bidi order. A matching copied value does not establish that the field was comfortable to read or edit. Conversely, a visual alignment difference does not establish that the server received altered characters.
For deeper display behavior outside editing controls, use how browsers render mixed-direction text. Here the implementation decision is an explicit field context and a reproducible editing test.
Keep alignment independent of direction#
An Arabic label can align with the rest of the form while the email value starts on the left. The label and input do not have to share one text-alignment rule.
For the waitlist fragment, use a control-specific style:
.waitlist-field input[type="email"] { text-align: start;}With the input's explicit LTR direction, start alignment is left. MDN's text-alignment reference explains the logical values. The Arabic wrapper retains its own context and can position the label and help accordingly.
If the design deliberately right-aligns email values, keep dir="ltr" and test that choice. Right alignment does not make an address RTL, just as right alignment cannot repair an incorrectly directed Arabic prose field.
Do not mirror the entire field with a transform. That treats labels, typed text and controls as a picture rather than assigning each its intended layout and reading context. Avoid inserting spaces into the value to simulate padding or position either.
When a screenshot is reported as “the email is on the wrong side,” collect both properties. The starting edge may come from text-align, while direction may be correct. Changing both without inspecting them can introduce a new problem into a field that only needed an alignment adjustment.
Prefer persistent Arabic help to a competing placeholder#
The waitlist fragment uses visible help and no placeholder. The explanation of where course notifications go remains available after the user has entered an address or returned to correct it.
An Arabic placeholder inside an LTR email control can appear at the left edge. That appearance does not justify changing the address's direction. A short address-shaped example can illustrate syntax, while an Arabic sentence explaining the purpose is better placed beside the control.
If the design requires a separately aligned empty hint, :placeholder-shown can select the input while it displays one. Keep the value's LTR policy stable and test the alignment transition when the first character arrives. This is a presentation option, not a reason to make the direction depend on whether the field is empty.
Keep the persistent label visible. Neither a translated placeholder nor an English accessible name attached to an otherwise unlabelled input provides the same experience as a visible Arabic question throughout entry.
Test populated and invalid states when reviewing the instruction. The user should not need to clear the field to recover its purpose or the supported format. If the explanation is clipped in the input's hint area, move it outside rather than shrinking the Arabic text to fit.
Configure autofill and mobile entry by field meaning#
Use autocomplete="email" when the field collects the address for course notifications. MDN's autocomplete reference defines the token. Avoid disabling autofill across the Arabic form merely because the saved address is written in Latin characters.
Field meaning matters when the same component is reused. A login identifier may have different autocomplete semantics from a contact email, even if both values look like addresses. Configure that meaning at the field call site rather than baking one token into every text-input component.
type="email" also helps browsers offer email-related entry behavior. inputmode is a keyboard hint, not an email validator or a direction setting. Adding an email keyboard hint to a plain text field does not reproduce the type's validation behavior.
Test the actual mobile keyboard, including access to the at-sign, period and plus sign used by the fixture. Keep paste available and check saved-address selection. Do not require users to retype an address to force it through a custom key handler.
The example disables spellchecking. Review any shared autocorrection or value-rewriting code too. The address should remain what the user selected or entered; a word suggestion must not become an unannounced change to the notification destination.
Check shared input code for unsupported selection APIs#
A generic text component may run caret-restoration code after every update. That implementation cannot assume every text-like HTML control exposes the same selection APIs.
selectionStart applies to specified input types such as text, search and telephone. Email is not in that list. Reading it on an email input returns null; setting it is unsupported and can throw an InvalidStateError.
This creates a debugging trap: a component may work for an Arabic description but fail when configured as an email field. Switching its direction does not fix code that calls an unsupported API. Inspect console errors and the component's update path before attributing every caret problem to RTL.
Do not change the field to type="text" just to make that helper run unless you deliberately replace the email behavior you are giving up. Prefer removing unnecessary rewriting and branching on the actual capabilities the component needs.
Test editing in the middle after an application rerender, after autofill and after validation appears. Record whether focus was lost, the node was replaced or an exception interrupted the update. Those are distinct from the browser's own bidi caret behavior and need different fixes.
Distinguish syntax, service policy and mailbox confirmation#
Native email validation checks the browser's supported address syntax. It does not prove that the mailbox exists, can receive a message or belongs to the person submitting the form. The HTML email state defines the control's requirements.
Keep the waitlist's decisions separate:
| Check | What it establishes |
|---|---|
| Required value | The user supplied an answer |
| Browser email constraint | The value satisfies that control's syntax rules |
| Server validation | The address meets the service's supported syntax and policy |
| Confirmation flow, if required | The user completed the service's mailbox-confirmation step |
Do not add an arbitrary regular expression merely because the interface is Arabic. A pattern that excludes plus tags would reject the fixture for a reason unrelated to direction. If the studio has a real address restriction, state it as a service rule and test it independently of the layout.
The waitlist expects one notification address. Do not enable multiple just to make a pasted list stop failing validation; that changes the input contract. If the product needs several recipients, design their entry and correction deliberately rather than silently treating one field as a distribution list.
Keep server validation authoritative. A successful browser check is useful feedback, but it does not replace the checks required by the application that will save and use the address.
Show Arabic errors without confusing language and validity#
Declaring the page Arabic does not guarantee that browser-generated validation messages are Arabic. In the measured English Chromium configuration, required-field feedback remained English on an Arabic page.
One option is to keep native constraints while presenting application-controlled inline messages. The following extends the improved waitlist fragment. Run it after the markup, inside a form that retains native constraint validation:
const waitlistEmail = document.getElementById("waitlist-email");const waitlistError = document.getElementById("waitlist-email-error");if (!waitlistEmail || !waitlistError) throw new Error("Waitlist email is missing"); function showWaitlistEmailError() { const validity = waitlistEmail.validity; const message = validity.valid ? "" : validity.valueMissing ? "أدخل البريد الإلكتروني لقائمة الانتظار." : "تحقق من صيغة عنوان البريد الإلكتروني."; waitlistError.textContent = message; if (message) waitlistEmail.setAttribute("aria-invalid", "true"); else waitlistEmail.removeAttribute("aria-invalid");} waitlistEmail.addEventListener("invalid", event => { event.preventDefault(); showWaitlistEmailError(); waitlistEmail.focus();}); waitlistEmail.addEventListener("input", () => { if (waitlistEmail.hasAttribute("aria-invalid")) showWaitlistEmailError();});The invalid event is handled on this field. Cancelling its default reporting lets the application supply feedback; it does not make the input valid. An invalid control still prevents ordinary validated submission, as MDN's submit-event reference explains.
This example covers the shown field's client constraints. A form with several errors needs a coordinated summary and focus policy rather than copying independent focus calls onto every field. Test that the Arabic description is available with assistive technology, including when the input already has focus. W3C's notification guidance covers those correction paths.
Be deliberate about what triggers the handler. Calling checkValidity() can dispatch invalid; it is not a passive read of a boolean. Polling it during initial rendering would activate this example's feedback and focus behavior before the user tries to submit. Read the current validity flags when inspecting state without requesting that validation event.
Clear stale errors when the value changes#
The snippet waits until a validation attempt before showing an error, then updates visible feedback while the user corrects it. Test an omitted address, a missing at-sign, a corrected fixture and another invalid replacement. The old message and aria-invalid state should not survive a valid correction.
Programmatic replacement is a separate integration path. Assigning a value through JavaScript does not itself fire the input event. If application code replaces an address while this example's error is visible, call showWaitlistEmailError() after that replacement to refresh its feedback. Do not call it unconditionally when mounting an empty form, because that would show the required-field error before the user has answered.
If application code uses setCustomValidity() for additional rules, it must clear the custom message when the rule no longer fails. A nonempty custom error can keep the field invalid even after its email syntax is corrected. That extra state is separate from the inline example above.
Translate server-originated conditions too. An unsupported address format, a duplicate waitlist entry and a temporary service failure should not all become “invalid email.” They offer different actions and say different things about the entered value.
Associate an asynchronous result with the address it checked. If the user changes the address while a request is pending, a delayed result for the previous value must not overwrite feedback for the current one. This is a state-management issue, not a browser direction issue.
Preserve the address after rejection. If an error embeds it in an Arabic sentence, give the address its own direction boundary there. The input's LTR attribute has no effect on a separate paragraph that happens to display the same string.
Preserve address characters rather than applying phone cleanup#
Do not share a phone-number sanitizer with email entry. Removing punctuation can discard the at-sign, dots and the plus tag that distinguish the fixture's address. Do not strip everything outside letters and digits to make the value appear simpler.
Preserve the local part unless a documented address policy requires a transformation. RFC 5321 distinguishes domain case handling from the potentially case-sensitive local part. Lowercasing the whole address on every keystroke is not a direction fix.
Likewise, do not assume plus tags can be removed or dots ignored across all providers. The studio's job is to contact the submitted destination, not infer another provider's mailbox-alias rules. Any separate comparison policy for duplicate entries needs its own justification.
Test paste with surrounding whitespace and unexpected characters. Compare the live control value with the submitted payload and server interpretation. Do not silently remove internal characters or insert hidden direction controls into the address to repair presentation.
If the service suggests a corrected domain after detecting a likely typo, make the correction visible and optional. Keep the original available until the user chooses. Automatically changing an address can send course notifications to a destination the user never approved.
Do not equate LTR entry with English-only addresses#
An LTR field is a presentation policy, not a declaration that email only exists in English. Internationalized addresses introduce support questions that cannot be solved by switching the input to RTL or transliterating what the user entered.
RFC 6531 defines the SMTPUTF8 extension for internationalized email. Internationalized domains and non-ASCII local parts are different cases, and support needs to extend through the browser, server parser, storage and sending infrastructure.
MDN notes specification issues around internationalized domains in HTML email validation. Do not promise acceptance merely because the backend parser accepts a Unicode string. Native constraints can reject a value before the application's submit handling receives it.
Choose and document the product's supported address forms. Test those exact forms through the whole flow, including delivery using controlled mailboxes. If broader support requires a custom input strategy, account for the native behavior being replaced instead of treating type="text" as a complete fix.
An unsupported-format message should describe the current service limitation. Do not claim that an address cannot exist because one validator rejects it, and do not convert Arabic letters into Latin guesses to make the test pass.
Verify filled, narrow and restored states#
Long addresses need more than an empty-field screenshot. Use the fixture, then a longer address from the same supported syntax set. Inspect whether the full value can be reached and edited at the narrowest supported viewport.
Keep validation text in normal layout so an Arabic explanation can wrap without covering the input. Adjacent status icons and clear actions need their own space. Do not remove part of the address from the editing value to make it fit visually. For layout failures, use RTL elements overlapping on mobile.
Test the field while the mobile keyboard is open, including the error shown near it. Confirm that the user can see the domain they are correcting and reach the submit action afterwards. Desktop emulation without an open keyboard does not exercise that same state.
Repeat after saved-address autofill, server rejection and switching the interface language. The current address should survive while the label, help and error use the selected language. The value's LTR policy should remain on the rendered input after each rerender.
If changing another course preference unexpectedly replaces the email element, investigate that component lifecycle. Losing focus or a partially edited value during an unrelated update is not corrected by adding another direction declaration.
Keep the confirmation consistent with the edited address#
The waitlist confirmation needs a separate direction boundary around the address:
<p lang="ar" dir="rtl"> عنوان البريد الإلكتروني المسجل: <bdi dir="ltr">bookings+weekend@inkharbor.example</bdi></p>This establishes the display context outside the input. It is not evidence that the fixture is deliverable or that a confirmation email has been sent. The interface should distinguish saving a waitlist request from completing any mailbox-confirmation step the service requires.
Use the saved address that the user actually reviewed. If the backend applies a documented transformation, verify that the displayed result and notification destination agree. Test returning from confirmation to edit the address without losing its plus tag or other characters.
If the waitlist requires mailbox confirmation, bind that status to the address that was confirmed. Changing the field to another address must not carry the previous mailbox's confirmed state onto the replacement. Show which destination is awaiting confirmation and provide a correction route alongside any resend action.
Test that relationship with a pending request: begin confirmation for one address, edit the field and then receive the earlier result. The interface must not label the new destination confirmed because an older request completed. Keep the current field value, the saved waitlist destination and the address associated with the result distinguishable in application state. This also makes an Arabic message about where a confirmation was sent reflect the operation that actually happened.
For details about boundaries in Arabic text, continue with bidi isolation. Do not add invisible characters to the stored address merely to make a confirmation sentence look right.
Test the email field as a complete interaction#
| Case | What to verify |
|---|---|
| Empty field | Arabic label and help, explicit LTR input direction |
| Typed and pasted fixture | Address preserved, including the plus tag |
| Editing the local part and domain | Focus and caret behavior without unsupported selection code |
| Autofill or programmatic restoration | Correct value, autocomplete meaning and direction after population |
| Missing or malformed address | Arabic feedback and blocked invalid submission |
| Corrected value | Old error text, custom validity and invalid state cleared as applicable |
| Delayed server response | Feedback belongs to the address that was checked |
| Supported internationalized form | Consistent browser, server and delivery behavior |
| Narrow layout and open keyboard | Reachable value and visible correction instructions |
| Confirmation and return to edit | Displayed, saved and editable addresses agree |
Collect direction, visual presentation, editing and submitted-value evidence separately. A value can look intact in an RTL control, and a syntactically accepted address can still fail a delivery check. Record which part was tested instead of labelling the whole email flow correct after one assertion.
A free Ritla scan can report : tel/email/url inputs rendered RTL (these must stay LTR), and : Untranslated form labels / validation / help text. Editing and address acceptance need the field tests above; continue with text-align start versus right for alignment decisions or bidi isolation for addresses displayed in Arabic confirmation text.