Skip to content

Password fields in RTL

Build password fields for Arabic interfaces with deliberate direction, accessible reveal buttons, readable strength feedback and keyboard-language checks.

By , Founder of Ritla

Guide13 min read

A volunteer portal's Arabic account screen can look correct while its password interaction fails. The masking symbols fit, but revealing the value changes its alignment. The show-password button submits the form. A person types with an Arabic keyboard while expecting Latin characters and cannot understand why the next sign-in attempt fails.

These are separate failures. Layout direction does not select a keyboard language, and masking does not establish that the entered characters match the user's intention. A reveal control must expose the same value without replacing the field or changing its content.

This guide follows the portal's account-creation password field. The implementation uses a stable LTR entry context as an explicit product choice, with Arabic labels and help around it. It also explains where a different policy can be appropriate for passwords containing Arabic, and how to test masked and revealed states without guessing their rendering.

Choose direction separately from accepted characters#

Password inputs inherit direction unless their markup or styles establish another context. They do not share the telephone input's LTR default. MDN's password-input reference describes the native control, while the dir reference describes direction declarations.

For the volunteer portal, declare LTR on the password input and retain RTL on its Arabic wrapper. That keeps the chosen base context stable when the value is hidden or revealed. It does not restrict the field to Latin letters, convert Arabic characters or force every character's visual order to follow its stored position.

Other products can choose inherited RTL or automatic direction when that serves their accepted content and editing model. HTML's automatic-direction rules include password controls. Automatic direction uses the value's strong characters; it does not determine what language the user intended to type.

Test the policy with Latin, Arabic and mixed-script disposable values. Do not infer correct editing from identical-looking masking symbols. The policy needs to make sense when the value is visible too.

Avoid a universal rule that every password on an Arabic page must be RTL or must be LTR. Define the supported experience, then check that both sign-up and sign-in use it consistently. For broader first-strong behavior, continue with how automatic direction works.

Treat masking and direction as different properties#

A password field masks its presentation. The mask's appearance varies by browser and operating system; it is not a directional annotation or proof that the underlying value is unchanged.

The browser observations supplied for this guide were measured in Chromium 151 on September 24, 2026. Firefox and Safari were not measured. In that setup, password inputs inherited page direction without an explicit declaration. Do not extend those measurements into an untested claim about exactly where every caret or masking symbol appears on every platform.

Inspect the computed direction on the input, then reveal a disposable test value and inspect its visible presentation. Logical text alignment can follow that direction, but alignment and direction remain separate decisions.

Do not rotate, mirror or reverse the password to make the masked field resemble another input. Do not treat a changed count of visible symbols as an authoritative comparison of Unicode strings. Test value preservation directly with fixtures that contain no real credentials.

Keep diagnostics limited to those fixtures. A screenshot of a revealed production password or a console dump of its value is not needed to establish a direction bug. Record the control's type, direction, focus state and the test steps instead.

Give the reveal control a button contract#

Inside a form, this reveal control has two problems:

Problem

html
<button aria-label="Show password">إظهار كلمة المرور</button>

Its accessible name is English despite the Arabic visible label. It also omits an explicit non-submit type. MDN's button reference explains the submission behavior that can follow from that omission inside a form.

Account-creation field with a labelled toggle

html
<div class="volunteer-credential" lang="ar" dir="rtl">  <label for="volunteer-password">كلمة المرور الجديدة</label>  <div class="credential-controls">    <input id="volunteer-password" name="password" type="password" dir="ltr"           autocomplete="new-password" spellcheck="false" autocorrect="off"           autocapitalize="none" required           aria-describedby="password-keyboard-help">    <button id="password-reveal" type="button" hidden aria-controls="volunteer-password"            aria-pressed="false">إظهار كلمة المرور</button>  </div>  <p id="password-keyboard-help">تحقق من لغة لوحة المفاتيح إذا لم تكن الأحرف كما تتوقع.</p></div>

Use this fragment inside the account form. The native button supplies keyboard activation, its Arabic text supplies its name, and aria-controls identifies the associated input. The explicit type prevents revealing the password from acting as the submit operation.

This example uses a toggle with a stable label and a pressed state. W3C's button pattern describes that model. A changing action label is another design, but do not mix a changing label with pressed-state semantics without deciding how users should understand the control.

Reveal the same input without rewriting its value#

Run this after the account-creation markup:

js
const passwordInput = document.getElementById("volunteer-password");const revealButton = document.getElementById("password-reveal");if (!passwordInput || !revealButton) throw new Error("Password control is missing"); revealButton.addEventListener("click", () => {  const start = passwordInput.selectionStart;  const end = passwordInput.selectionEnd;  const selectionDirection = passwordInput.selectionDirection || "none";  const reveal = passwordInput.type === "password";   passwordInput.type = reveal ? "text" : "password";  revealButton.setAttribute("aria-pressed", String(reveal));   if (start !== null && end !== null) {    passwordInput.setSelectionRange(start, end, selectionDirection);  }}); revealButton.hidden = false;

The code changes the existing input's type. It does not copy the password into a second field, replace the node or alter its direction, name or autocomplete token. The button's pressed state reflects whether this control is revealing the value.

Both password and text inputs support setSelectionRange(). Preserving the selection state does not promise identical visible caret placement across platforms. The code also does not force focus back from the button; test the resulting keyboard and touch interactions before adding your own focus policy.

Check that a framework rerender does not replace the input immediately afterwards or overwrite the revealed state with stale component state. A DOM-only toggle and a state-driven component need one agreed owner for the current type.

Toggle repeatedly with an empty value, a populated value and an active selection. Verify exact fixture equality after every change. The reveal operation must not submit the form or trigger a fresh password-strength calculation that rewrites the value.

The button starts hidden and becomes available after its handler is attached. If the script does not load, the password input remains a native masked control rather than displaying a reveal button that does nothing. MDN describes the hidden attribute. Test the page with this enhancement unavailable as well as with it initialized.

Keep styles stable when the input type changes#

A reveal toggle changes which type-based selectors match. A rule aimed only at input[type="password"] stops matching when the same element becomes a text input. CSS attribute selectors follow the current attribute value, not the element's original purpose.

That can expose an unrelated shared text-input rule. The revealed password might acquire another width, font, alignment or author-defined direction even though the reveal code never touched those properties. The unchanged dir attribute alone does not prove that the resulting CSS still agrees with it.

Style this component through its stable class or wrapper, as the control-row example below does. Reserve type-specific rules for behavior that really should differ while the password is revealed. Compare computed styles before and after toggling when the field seems to jump or reverse.

Include invalid and focused styles in that comparison. A reveal operation should not make a visible error treatment disappear merely because its selector was written for the masked type alone. Test both an empty invalid field and a populated field that the application rejects.

Review text-entry assistance in the revealed state too. The fragment explicitly disables spellchecking, autocorrection and automatic capitalization. Native password-mode behavior alone does not describe an input after the application switches it to text. Keep these settings on the same element so revealing it does not opt into a different editing policy. Test typing a lowercase first character and accepting keyboard suggestions while revealed on supported devices. The password should not change case or spelling because the presentation mode changed.

Position the control relative to the right box#

The Arabic field row and its LTR input have different inline starting edges. Decide whether the reveal button belongs to the field's layout or is an overlay inside the value area before choosing its position.

An adjacent button avoids reserving space over editable text. For the fragment above, a wrapping row is one option:

css
.credential-controls {  display: flex;  flex-wrap: wrap;  gap: 0.65rem;} .credential-controls input {  flex: 1 1 15rem;  min-inline-size: 0;  max-inline-size: 100%;  text-align: start;}

The row inherits RTL from the wrapper while the input retains its LTR value context. flex-wrap allows the controls to occupy another line when necessary. Test the layout at the product's actual widths and text sizes; this fragment is not a universal breakpoint policy.

If the design uses an eye icon over the input instead, reserve room for the icon, native browser controls and password-manager UI. An empty field does not show whether these will collide with a long revealed value.

Keep the input before its reveal button in the intended document sequence and test Tab navigation. Do not repair a screenshot by reversing the row again or assigning positive tab indexes. For positioning details, use absolute positioning in RTL layouts.

Explain keyboard mismatch without treating Arabic as an error#

The portal cannot infer the intended password from the interface language. A person can intentionally create an Arabic password, intentionally use Latin characters or accidentally type under the wrong keyboard layout.

dir="ltr" does not switch the operating system's keyboard to English. Neither does an input's Arabic or English language tag. inputmode suggests an input mechanism, not a guaranteed keyboard language.

Use a neutral Arabic hint, like the one associated with the example input. Offer the reveal control so the user can inspect what they entered. Do not change the value into a guessed Latin equivalent when Arabic characters appear.

Do not use browser interface language as evidence of the active keyboard layout. KeyboardEvent.key reflects the produced key value under the relevant modifiers and layout, but a key event is not a complete record of text supplied through paste, autofill or an input method.

If the application offers a script-related hint, make its scope explicit: it observed characters, not the user's intention. An Arabic letter in a password is not itself proof of a mistake. The hint must not block an intentionally supported password or repeatedly interrupt every keystroke.

Preserve password characters across every language route#

Do not reuse cleanup designed for phone numbers or names. Converting Arabic-Indic digits into Western digits changes a password. So can trimming whitespace, removing punctuation, transliterating letters or lowercasing the value.

Keep the direction fix in markup and styling. If the authentication system defines Unicode normalization, implement that documented policy consistently through account creation, password change and sign-in. Do not introduce a separate normalization rule in the Arabic frontend to make display or validation easier.

Use disposable fixtures to distinguish character preservation from strength or acceptance. For example, Cedar!Lantern?58, Cedar!Lantern?٥٨ and Cedar!مصباح?58 exercise different scripts. They are test strings, not password recommendations or claims about what the portal's policy accepts.

Test leading and trailing spaces separately if the product supports them. Compare exact fixture strings through reveal, hide, validation and submission handling. Do not assume two visually similar digit forms represent the same credential.

A person who creates a supported Arabic password on the Arabic route must be able to sign in with it on another language route. A mismatch between those flows is an input-policy defect even when each screen's Arabic text and alignment look correct.

Use autocomplete tokens for the actual password task#

The example creates a password, so it uses autocomplete="new-password". A sign-in password uses current-password. A password-change form can contain an existing password plus a new one; configure those fields according to their roles.

MDN's autocomplete reference defines these tokens and distinguishes them from one-time-code. Do not treat every hidden or sensitive-looking input as the same task. A verification code is not a new account password.

Keep the username or account identifier associated with the credential flow where the form requires one. Do not rename or swap inputs between masked and revealed states just to change appearance; that gives autofill and password managers a different structure to interpret.

Allow paste and password-manager entry. W3C's accessible-authentication guidance explains how blocking those mechanisms can force users into manual transcription. Arabic keyboard mismatch is another reason not to make typing the only route.

Test generated and saved credentials as well as manual input. A field populated before focus should still have the intended direction and a reveal control whose state agrees with the input. Verify that the submitted credential does not depend on a particular key handler having executed.

If application code populates or clears the field programmatically, refresh any strength and error presentation through the same component state path. Assigning a value through JavaScript does not itself dispatch an input event. A meter updated only by that event can otherwise keep describing the previous candidate after the field has changed.

Give strength feedback a meaning before choosing its fill direction#

A strength indicator estimates or classifies a candidate under the product's chosen method. Mirroring the bar must not reverse its meaning: a larger displayed score should still represent the same classification on the Arabic and English routes.

Decide where the low end and high end belong in the Arabic layout, then test native or custom rendering. Do not assume that every browser's native meter fills from the same edge or that flipping an entire meter with a transform preserves its text and meaning.

The native meter element represents a value in a known range. This is an illustrative presentation fixture for a product using a zero-to-four score:

html
<div lang="ar" dir="rtl">  <span id="password-strength-label">تقدير قوة كلمة المرور</span>  <meter min="0" max="4" value="2" aria-labelledby="password-strength-label"         aria-describedby="password-strength-text">متوسطة</meter>  <p id="password-strength-text">التقدير الحالي: متوسطة.</p></div>

The score is not calculated here and is not assigned to any example password in this guide. Connect the presentation to the application's actual estimator, update its accessible text alongside the value and keep the Arabic classification visible rather than relying only on color.

Test minimum, intermediate and maximum states in both interface directions. Native appearance needs browser testing; custom bars need their own layout and accessibility checks.

Keep strength guidance distinct from acceptance errors#

A strength estimate, an unmet account-creation rule and an incorrect sign-in password are different feedback states. Do not put a strength meter on sign-in and imply that raising its score would repair a rejected existing credential.

Translate the actual requirements the portal enforces. If a rule expects a particular character class, the Arabic wording must identify that class rather than saying only “letters.” Do not impose a Latin-only rule merely because a shared validator was written that way.

Any counter must agree with the enforced length policy. HTML's maxlength measures UTF-16 code units, which need not match a visible-character count. Test combining marks and other supported Unicode content against both client and server limits; do not infer the count from masking symbols.

If the account screen also asks users to confirm a new password, compare the accepted strings under the authentication system's documented policy. Two fields with different base directions can display the same underlying candidate differently; two visually similar candidates can contain different characters. Do not reverse either value to make the pair look alike. Reveal each field through its own associated control, then test matching and mismatching fixtures without changing their contents.

Keep helpful guidance available while the user edits, but avoid announcing a strength update on every character. W3C's status-message guidance covers changes that can be conveyed without moving focus. Choose when updates deserve an announcement, and test the result with assistive technology.

For rejection, use Arabic copy that describes the available correction without showing the password in the message. Associate errors with the relevant control. W3C's form-notification guidance covers field feedback and correction paths.

Test reveal state through rerenders and recovery#

Changing another account preference, receiving a validation error or switching the interface language can rerender the password component. Verify that it does not create a second input, lose its current value or leave the toggle pressed while the input has returned to masking.

Define the product's reveal lifecycle. If the application re-masks after an error, reset the button state at the same time. If it preserves the reveal state, verify that the state is intentional and accurately announced. Do not claim a universal browser policy for those application decisions.

Reset needs an explicit state decision too. A reset that clears the value should not leave a stale strength score or a stale error beside an empty field. A newly mounted account form should not inherit the previous form instance's reveal setting accidentally.

Do not echo a submitted password into server-rendered error markup or populate it from a URL to reconstruct a failed screen. Decide the correction flow with the authentication implementation; client-side retention within the current interaction and server-side reprinting are different mechanisms.

Test failed submission with the field masked and revealed. Check the input type, toggle state, error association and focus. A successful reveal demonstration alone does not verify recovery.

Check narrow layouts with the real keyboard open#

The translated reveal label can take more space than an icon. Test its longest reviewed wording with enlarged text, a long disposable value and the password manager enabled. Keep both the input and the control reachable when the row wraps.

On mobile, inspect the field while the keyboard is open. Reveal, move back to the field, edit the middle and hide again. Check whether focus or scrolling leaves the active input under a header or obscures the correction instructions.

Include native reveal controls if a supported browser supplies them. Do not assume the custom button is the only affordance occupying the input's edge. Choose a consistent experience and verify the native and custom controls do not contradict each other's visible state.

The empty field is not a sufficient layout fixture. Combine a revealed value, a wrapped Arabic error, visible strength guidance and the browser's credential UI. For collisions in that state, continue with RTL elements overlapping on mobile.

Verify character preservation and interaction separately#

Use disposable test credentials, not real account passwords, for repeatable diagnostics. Capture what changed in the UI without including secret values in screenshots or ordinary logs.

TestWhat to verify
Latin, Arabic and mixed-script fixturesThe intended direction policy in masked and revealed states
Reveal, hide and repeatSame input and exact fixture value; no submission
Selection before togglingSelection preserved as intended and focus remains usable
Keyboard and touch activationA reachable button with an Arabic name and accurate state
Wrong-layout simulationA neutral hint and inspection path without automatic transliteration
Paste, generation and autofillEntry works without relying on manual key events
Strength statesMatching classification, text and accessible value across language routes
Error, reset and rerenderNo stale reveal state, score or invalid message
Narrow screen with keyboard openNo overlap or unreachable editing and reveal controls
Creation followed by sign-inThe accepted fixture is interpreted consistently across routes

A style assertion cannot establish that the keyboard produced the intended characters. A value-equality assertion cannot establish that the Arabic toggle name is announced or that the meter is readable. Keep each observation tied to the behavior it verifies.

A free Ritla scan can report R011: Untranslated interactive labels (buttons, nav/footer links, menu items, tabs), and R071: Untranslated form labels / validation / help text. Reveal behavior, keyboard mismatch and strength semantics need the tests above; continue with RTL elements overlapping on mobile for control collisions or Arabic localization testing for reviewing password guidance and correction wording.

Checks in this guide

See what your Arabic pages are hiding

Paste a URL. Ritla renders the page on desktop and mobile, runs every check, and shows the top issues with screenshot evidence.

Scan a page freeBrowse the checks