A comprehensive guide to designing and developing forms that work beautifully for Arabic users, covering layout, validation, accessibility, and mixed-language input challenges.

Karim Benali
Senior frontend developer with 10+ years building RTL-first applications.
Forms are the backbone of user interaction on the web—registration, checkout, contact forms, search bars. But when it comes to Arabic and other RTL languages, forms present unique challenges that go beyond simply flipping the layout.
Done wrong, forms can be confusing, frustrating, or even unusable. Done right, they feel natural and seamless.
This guide covers everything you need to build truly accessible, user-friendly forms for Arabic users.
In LTR forms, labels are often placed to the left of inputs:
[Label] [Input field................]When naively flipped for RTL:
[Input field................] [Label]Problem: In RTL, users scan from right to left. Having the label far to the left creates a long eye travel distance and breaks the natural reading flow.
For RTL forms, place labels above inputs:
Benefits:
Best Practice: Use top-aligned labels for all multilingual forms. They work universally and eliminate the need for direction-specific layouts.
.form-group {
display: flex;
flex-direction: column;
margin-block-end: 1.5rem;
}
.form-label {
margin-block-end: 0.5rem;
font-weight: 500;
text-align: start; /* Aligns right in RTL, left in LTR */
}
.form-input {
padding: 0.75rem;
border: 1px solid #d1d5db;
border-radius: 0.375rem;
}<div class="form-group">
<label for="name" class="form-label">الاسم الكامل</label>
<input
type="text"
id="name"
class="form-input"
placeholder="أدخل اسمك الكامل"
/>
</div>Input fields should align text to the start of the reading direction:
/* Correct: Logical property */
.form-input {
text-align: start;
}
/* Wrong: Fixed direction */
.form-input {
text-align: right; /* This breaks in LTR! */
}Result:

Placeholder text should match the expected input language:
<!-- Arabic form -->
<input
type="text"
placeholder="أدخل البريد الإلكتروني"
dir="auto"
/>
<!-- The dir="auto" attribute automatically detects text direction -->dir="auto" AttributeThis powerful HTML attribute detects the directionality of the first strong directional character:
<!-- If user types Arabic, field becomes RTL -->
<!-- If user types English, field becomes LTR -->
<input type="text" dir="auto" />How it works: The browser examines the first character with strong directionality (Arabic letter = RTL, Latin letter = LTR) and sets the field's direction accordingly. Numbers and punctuation are neutral and don't affect the direction.
Real-world forms often need to accept mixed-language input. Consider a registration form:
Set direction explicitly based on input type:
<!-- Name: Allow auto-detection -->
<input
type="text"
name="fullName"
placeholder="الاسم الكامل"
dir="auto"
/>
<!-- Email: Force LTR -->
<input
type="email"
name="email"
placeholder="example@domain.com"
dir="ltr"
/>
<!-- Password: Force LTR -->
<input
type="password"
name="password"
dir="ltr"
/>
<!-- Phone: Force LTR with proper formatting -->
<input
type="tel"
name="phone"
placeholder="+966 50 123 4567"
dir="ltr"
inputmode="tel"
/>| Field Type | Direction | Reason |
|---|---|---|
| Name | dir="auto" | Could be Arabic or Latin |
dir="ltr" | Email addresses are always LTR | |
| Password | dir="ltr" | Typically uses Latin characters |
| Phone | dir="ltr" | International format recognition |
| Address | dir="auto" | Could be mixed language |
| Search | dir="auto" | User might search in any language |
| Message/Comment | dir="auto" | User's natural language |
| URL | dir="ltr" | URLs are always LTR |
| Credit Card | dir="ltr" | Numbers and Latin characters |
Help users understand what format is expected:
<div class="form-group">
<label for="email" class="form-label">
البريد الإلكتروني
<span class="text-muted">(English)</span>
</label>
<input
type="email"
id="email"
dir="ltr"
placeholder="example@domain.com"
/>
<span class="form-hint">
سيتم إدخال البريد الإلكتروني بالأحرف الإنجليزية
</span>
</div>.form-hint {
display: block;
margin-block-start: 0.25rem;
font-size: 0.875rem;
color: #6b7280;
}
.text-muted {
font-weight: normal;
color: #9ca3af;
font-size: 0.875rem;
}Validation messages need careful positioning and clear messaging in Arabic.
Place validation messages below the input field:
<div class="form-group">
<label for="email" class="form-label">البريد الإلكتروني</label>
<input
type="email"
id="email"
class="form-input"
aria-invalid="true"
aria-describedby="email-error"
/>
<span id="email-error" class="form-error" role="alert">
يرجى إدخال عنوان بريد إلكتروني صالح
</span>
</div>.form-error {
display: block;
margin-block-start: 0.5rem;
padding-inline-start: 0.75rem;
color: #dc2626;
font-size: 0.875rem;
border-inline-start: 3px solid #dc2626;
}
/* Success state */
.form-success {
display: block;
margin-block-start: 0.5rem;
padding-inline-start: 0.75rem;
color: #059669;
font-size: 0.875rem;
border-inline-start: 3px solid #059669;
}
Always display error messages in the user's language:
Don't: Show English error messages in an Arabic interface. This breaks the user experience and can confuse users who don't understand English.
// Good: Localized validation messages
const validationMessages = {
ar: {
required: 'هذا الحقل مطلوب',
email: 'يرجى إدخال عنوان بريد إلكتروني صالح',
minLength: (min) => `يجب أن يحتوي على ${min} أحرف على الأقل`,
pattern: 'التنسيق غير صحيح',
},
en: {
required: 'This field is required',
email: 'Please enter a valid email address',
minLength: (min) => `Must be at least ${min} characters`,
pattern: 'Invalid format',
}
};
function showError(fieldId, errorType, locale = 'ar') {
const message = validationMessages[locale][errorType];
const errorElement = document.getElementById(`${fieldId}-error`);
errorElement.textContent = message;
errorElement.style.display = 'block';
}The asterisk (*) is universally understood but needs proper placement:
<!-- Place asterisk after label text in Arabic -->
<label for="name" class="form-label">
الاسم الكامل
<span class="required" aria-label="مطلوب">*</span>
</label>.required {
color: #dc2626;
margin-inline-start: 0.25rem; /* Positions after text in both directions */
}Alternative: Use a visual badge:
<label for="name" class="form-label">
الاسم الكامل
<span class="badge badge-required">مطلوب</span>
</label>.badge-required {
display: inline-block;
margin-inline-start: 0.5rem;
padding: 0.125rem 0.5rem;
font-size: 0.75rem;
font-weight: 600;
color: #dc2626;
background-color: #fee2e2;
border-radius: 0.25rem;
}Checkbox and radio button alignment requires special attention in RTL.
<div class="form-check">
<input
type="checkbox"
id="terms"
class="form-check-input"
/>
<label for="terms" class="form-check-label">
أوافق على الشروط والأحكام
</label>
</div>.form-check {
display: flex;
align-items: flex-start;
gap: 0.75rem;
margin-block-end: 1rem;
}
.form-check-input {
/* Ensure checkbox appears at the start (right in RTL, left in LTR) */
order: -1; /* Places checkbox before label in reading order */
margin-block-start: 0.25rem; /* Align with first line of text */
flex-shrink: 0;
}
.form-check-label {
cursor: pointer;
user-select: none;
}For long checkbox labels that wrap:
.form-check {
display: grid;
grid-template-columns: auto 1fr;
gap: 0.75rem;
align-items: start;
}
.form-check-input {
margin-block-start: 0.25rem;
}
.form-check-label {
line-height: 1.5;
}Dropdown arrows need special handling in RTL:
.form-select {
appearance: none; /* Remove default arrow */
background-image: url("data:image/svg+xml,..."); /* Custom arrow */
background-position: left 0.75rem center; /* LTR position */
background-repeat: no-repeat;
background-size: 1rem;
padding-inline-start: 2.5rem; /* Space for arrow */
padding-inline-end: 1rem;
}
[dir="rtl"] .form-select {
background-position: right 0.75rem center; /* RTL position */
}
/* Better: Use logical properties */
.form-select {
appearance: none;
background-image: url("data:image/svg+xml,...");
background-position: inline-start 0.75rem center;
background-repeat: no-repeat;
background-size: 1rem;
padding-inline-start: 2.5rem;
padding-inline-end: 1rem;
}Note: Not all CSS properties support logical keywords yet. For background-position, you may need direction-specific rules until broader browser support is available.
Arabic screen readers (like NVDA with Arabic speech, JAWS) need proper markup:
<form aria-label="نموذج التسجيل">
<div class="form-group">
<label for="username" id="username-label">
اسم المستخدم
<span class="required" aria-label="مطلوب">*</span>
</label>
<input
type="text"
id="username"
aria-labelledby="username-label"
aria-required="true"
aria-invalid="false"
aria-describedby="username-hint"
/>
<span id="username-hint" class="form-hint">
يجب أن يحتوي على 3-20 حرفًا
</span>
</div>
</form>Always provide ARIA labels in the user's language:
<!-- Good: Arabic ARIA labels -->
<button aria-label="إرسال النموذج">إرسال</button>
<!-- Bad: English ARIA labels in Arabic interface -->
<button aria-label="Submit form">إرسال</button>Ensure tab order follows visual order (right-to-left in RTL):
<!-- Tab order: 1 → 2 → 3 (reading order) -->
<input type="text" tabindex="1" />
<input type="text" tabindex="2" />
<button type="submit" tabindex="3">إرسال</button>Generally, rely on natural DOM order rather than explicit tabindex:
<!-- Preferred: Natural tab order -->
<input type="text" />
<input type="text" />
<button type="submit">إرسال</button>Here's a fully accessible Arabic registration form:
<form class="form" aria-label="نموذج التسجيل" dir="rtl">
<!-- Name Field -->
<div class="form-group">
<label for="fullName" class="form-label">
الاسم الكامل
<span class="required" aria-label="مطلوب">*</span>
</label>
<input
type="text"
id="fullName"
class="form-input"
dir="auto"
placeholder="أدخل اسمك الكامل"
required
aria-required="true"
/>
</div>
<!-- Email Field -->
<div class="form-group">
<label for="email" class="form-label">
البريد الإلكتروني
<span class="required" aria-label="مطلوب">*</span>
<span class="text-muted">(English)</span>
</label>
<input
type="email"
id="email"
class="form-input"
dir="ltr"
placeholder="example@domain.com"
required
aria-required="true"
aria-describedby="email-hint"
/>
<span id="email-hint" class="form-hint">
يتم إدخال البريد الإلكتروني بالأحرف الإنجليزية
</span>
</div>
<!-- Phone Field -->
<div class="form-group">
<label for="phone" class="form-label">
رقم الهاتف
<span class="required" aria-label="مطلوب">*</span>
</label>
<input
type="tel"
id="phone"
class="form-input"
dir="ltr"
placeholder="+966 50 123 4567"
inputmode="tel"
required
aria-required="true"
/>
</div>
<!-- Password Field -->
<div class="form-group">
<label for="password" class="form-label">
كلمة المرور
<span class="required" aria-label="مطلوب">*</span>
</label>
<input
type="password"
id="password"
class="form-input"
dir="ltr"
required
aria-required="true"
aria-describedby="password-hint"
/>
<span id="password-hint" class="form-hint">
يجب أن تحتوي على 8 أحرف على الأقل
</span>
</div>
<!-- Terms Checkbox -->
<div class="form-check">
<input
type="checkbox"
id="terms"
class="form-check-input"
required
aria-required="true"
/>
<label for="terms" class="form-check-label">
أوافق على <a href="/terms">الشروط والأحكام</a>
</label>
</div>
<!-- Submit Button -->
<button type="submit" class="btn btn-primary">
إنشاء حساب
</button>
</form>
Before launching forms for Arabic users:
Visual Testing:
Functional Testing:
Accessibility Testing:
Cross-Browser Testing:
Top-aligned labels work best: They're universal, responsive, and eliminate RTL-specific issues.
Use dir="auto" for flexible inputs: Let the browser detect text direction for name, address, and search fields.
Force LTR for technical inputs: Email, password, phone, and URLs should always be LTR.
Validate in Arabic: Error messages must be in the user's language for clarity.
CSS logical properties: Use inline-start, inline-end, text-align: start for automatic direction support.
Test with real users: Have native Arabic speakers test your forms on real devices.
Accessibility is non-negotiable: Proper ARIA labels, keyboard navigation, and screen reader support are essential.
A comprehensive guide to designing and developing forms that work beautifully for Arabic users, covering layout, validation, accessibility, and mixed-language input challenges.

Karim Benali
Senior frontend developer with 10+ years building RTL-first applications.
Forms are the backbone of user interaction on the web—registration, checkout, contact forms, search bars. But when it comes to Arabic and other RTL languages, forms present unique challenges that go beyond simply flipping the layout.
Done wrong, forms can be confusing, frustrating, or even unusable. Done right, they feel natural and seamless.
This guide covers everything you need to build truly accessible, user-friendly forms for Arabic users.
In LTR forms, labels are often placed to the left of inputs:
[Label] [Input field................]When naively flipped for RTL:
[Input field................] [Label]Problem: In RTL, users scan from right to left. Having the label far to the left creates a long eye travel distance and breaks the natural reading flow.
For RTL forms, place labels above inputs:
Benefits:
Best Practice: Use top-aligned labels for all multilingual forms. They work universally and eliminate the need for direction-specific layouts.
.form-group {
display: flex;
flex-direction: column;
margin-block-end: 1.5rem;
}
.form-label {
margin-block-end: 0.5rem;
font-weight: 500;
text-align: start; /* Aligns right in RTL, left in LTR */
}
.form-input {
padding: 0.75rem;
border: 1px solid #d1d5db;
border-radius: 0.375rem;
}<div class="form-group">
<label for="name" class="form-label">الاسم الكامل</label>
<input
type="text"
id="name"
class="form-input"
placeholder="أدخل اسمك الكامل"
/>
</div>Input fields should align text to the start of the reading direction:
/* Correct: Logical property */
.form-input {
text-align: start;
}
/* Wrong: Fixed direction */
.form-input {
text-align: right; /* This breaks in LTR! */
}Result:

Placeholder text should match the expected input language:
<!-- Arabic form -->
<input
type="text"
placeholder="أدخل البريد الإلكتروني"
dir="auto"
/>
<!-- The dir="auto" attribute automatically detects text direction -->dir="auto" AttributeThis powerful HTML attribute detects the directionality of the first strong directional character:
<!-- If user types Arabic, field becomes RTL -->
<!-- If user types English, field becomes LTR -->
<input type="text" dir="auto" />How it works: The browser examines the first character with strong directionality (Arabic letter = RTL, Latin letter = LTR) and sets the field's direction accordingly. Numbers and punctuation are neutral and don't affect the direction.
Real-world forms often need to accept mixed-language input. Consider a registration form:
Set direction explicitly based on input type:
<!-- Name: Allow auto-detection -->
<input
type="text"
name="fullName"
placeholder="الاسم الكامل"
dir="auto"
/>
<!-- Email: Force LTR -->
<input
type="email"
name="email"
placeholder="example@domain.com"
dir="ltr"
/>
<!-- Password: Force LTR -->
<input
type="password"
name="password"
dir="ltr"
/>
<!-- Phone: Force LTR with proper formatting -->
<input
type="tel"
name="phone"
placeholder="+966 50 123 4567"
dir="ltr"
inputmode="tel"
/>| Field Type | Direction | Reason |
|---|---|---|
| Name | dir="auto" | Could be Arabic or Latin |
dir="ltr" | Email addresses are always LTR | |
| Password | dir="ltr" | Typically uses Latin characters |
| Phone | dir="ltr" | International format recognition |
| Address | dir="auto" | Could be mixed language |
| Search | dir="auto" | User might search in any language |
| Message/Comment | dir="auto" | User's natural language |
| URL | dir="ltr" | URLs are always LTR |
| Credit Card | dir="ltr" | Numbers and Latin characters |
Help users understand what format is expected:
<div class="form-group">
<label for="email" class="form-label">
البريد الإلكتروني
<span class="text-muted">(English)</span>
</label>
<input
type="email"
id="email"
dir="ltr"
placeholder="example@domain.com"
/>
<span class="form-hint">
سيتم إدخال البريد الإلكتروني بالأحرف الإنجليزية
</span>
</div>.form-hint {
display: block;
margin-block-start: 0.25rem;
font-size: 0.875rem;
color: #6b7280;
}
.text-muted {
font-weight: normal;
color: #9ca3af;
font-size: 0.875rem;
}Validation messages need careful positioning and clear messaging in Arabic.
Place validation messages below the input field:
<div class="form-group">
<label for="email" class="form-label">البريد الإلكتروني</label>
<input
type="email"
id="email"
class="form-input"
aria-invalid="true"
aria-describedby="email-error"
/>
<span id="email-error" class="form-error" role="alert">
يرجى إدخال عنوان بريد إلكتروني صالح
</span>
</div>.form-error {
display: block;
margin-block-start: 0.5rem;
padding-inline-start: 0.75rem;
color: #dc2626;
font-size: 0.875rem;
border-inline-start: 3px solid #dc2626;
}
/* Success state */
.form-success {
display: block;
margin-block-start: 0.5rem;
padding-inline-start: 0.75rem;
color: #059669;
font-size: 0.875rem;
border-inline-start: 3px solid #059669;
}
Always display error messages in the user's language:
Don't: Show English error messages in an Arabic interface. This breaks the user experience and can confuse users who don't understand English.
// Good: Localized validation messages
const validationMessages = {
ar: {
required: 'هذا الحقل مطلوب',
email: 'يرجى إدخال عنوان بريد إلكتروني صالح',
minLength: (min) => `يجب أن يحتوي على ${min} أحرف على الأقل`,
pattern: 'التنسيق غير صحيح',
},
en: {
required: 'This field is required',
email: 'Please enter a valid email address',
minLength: (min) => `Must be at least ${min} characters`,
pattern: 'Invalid format',
}
};
function showError(fieldId, errorType, locale = 'ar') {
const message = validationMessages[locale][errorType];
const errorElement = document.getElementById(`${fieldId}-error`);
errorElement.textContent = message;
errorElement.style.display = 'block';
}The asterisk (*) is universally understood but needs proper placement:
<!-- Place asterisk after label text in Arabic -->
<label for="name" class="form-label">
الاسم الكامل
<span class="required" aria-label="مطلوب">*</span>
</label>.required {
color: #dc2626;
margin-inline-start: 0.25rem; /* Positions after text in both directions */
}Alternative: Use a visual badge:
<label for="name" class="form-label">
الاسم الكامل
<span class="badge badge-required">مطلوب</span>
</label>.badge-required {
display: inline-block;
margin-inline-start: 0.5rem;
padding: 0.125rem 0.5rem;
font-size: 0.75rem;
font-weight: 600;
color: #dc2626;
background-color: #fee2e2;
border-radius: 0.25rem;
}Checkbox and radio button alignment requires special attention in RTL.
<div class="form-check">
<input
type="checkbox"
id="terms"
class="form-check-input"
/>
<label for="terms" class="form-check-label">
أوافق على الشروط والأحكام
</label>
</div>.form-check {
display: flex;
align-items: flex-start;
gap: 0.75rem;
margin-block-end: 1rem;
}
.form-check-input {
/* Ensure checkbox appears at the start (right in RTL, left in LTR) */
order: -1; /* Places checkbox before label in reading order */
margin-block-start: 0.25rem; /* Align with first line of text */
flex-shrink: 0;
}
.form-check-label {
cursor: pointer;
user-select: none;
}For long checkbox labels that wrap:
.form-check {
display: grid;
grid-template-columns: auto 1fr;
gap: 0.75rem;
align-items: start;
}
.form-check-input {
margin-block-start: 0.25rem;
}
.form-check-label {
line-height: 1.5;
}Dropdown arrows need special handling in RTL:
.form-select {
appearance: none; /* Remove default arrow */
background-image: url("data:image/svg+xml,..."); /* Custom arrow */
background-position: left 0.75rem center; /* LTR position */
background-repeat: no-repeat;
background-size: 1rem;
padding-inline-start: 2.5rem; /* Space for arrow */
padding-inline-end: 1rem;
}
[dir="rtl"] .form-select {
background-position: right 0.75rem center; /* RTL position */
}
/* Better: Use logical properties */
.form-select {
appearance: none;
background-image: url("data:image/svg+xml,...");
background-position: inline-start 0.75rem center;
background-repeat: no-repeat;
background-size: 1rem;
padding-inline-start: 2.5rem;
padding-inline-end: 1rem;
}Note: Not all CSS properties support logical keywords yet. For background-position, you may need direction-specific rules until broader browser support is available.
Arabic screen readers (like NVDA with Arabic speech, JAWS) need proper markup:
<form aria-label="نموذج التسجيل">
<div class="form-group">
<label for="username" id="username-label">
اسم المستخدم
<span class="required" aria-label="مطلوب">*</span>
</label>
<input
type="text"
id="username"
aria-labelledby="username-label"
aria-required="true"
aria-invalid="false"
aria-describedby="username-hint"
/>
<span id="username-hint" class="form-hint">
يجب أن يحتوي على 3-20 حرفًا
</span>
</div>
</form>Always provide ARIA labels in the user's language:
<!-- Good: Arabic ARIA labels -->
<button aria-label="إرسال النموذج">إرسال</button>
<!-- Bad: English ARIA labels in Arabic interface -->
<button aria-label="Submit form">إرسال</button>Ensure tab order follows visual order (right-to-left in RTL):
<!-- Tab order: 1 → 2 → 3 (reading order) -->
<input type="text" tabindex="1" />
<input type="text" tabindex="2" />
<button type="submit" tabindex="3">إرسال</button>Generally, rely on natural DOM order rather than explicit tabindex:
<!-- Preferred: Natural tab order -->
<input type="text" />
<input type="text" />
<button type="submit">إرسال</button>Here's a fully accessible Arabic registration form:
<form class="form" aria-label="نموذج التسجيل" dir="rtl">
<!-- Name Field -->
<div class="form-group">
<label for="fullName" class="form-label">
الاسم الكامل
<span class="required" aria-label="مطلوب">*</span>
</label>
<input
type="text"
id="fullName"
class="form-input"
dir="auto"
placeholder="أدخل اسمك الكامل"
required
aria-required="true"
/>
</div>
<!-- Email Field -->
<div class="form-group">
<label for="email" class="form-label">
البريد الإلكتروني
<span class="required" aria-label="مطلوب">*</span>
<span class="text-muted">(English)</span>
</label>
<input
type="email"
id="email"
class="form-input"
dir="ltr"
placeholder="example@domain.com"
required
aria-required="true"
aria-describedby="email-hint"
/>
<span id="email-hint" class="form-hint">
يتم إدخال البريد الإلكتروني بالأحرف الإنجليزية
</span>
</div>
<!-- Phone Field -->
<div class="form-group">
<label for="phone" class="form-label">
رقم الهاتف
<span class="required" aria-label="مطلوب">*</span>
</label>
<input
type="tel"
id="phone"
class="form-input"
dir="ltr"
placeholder="+966 50 123 4567"
inputmode="tel"
required
aria-required="true"
/>
</div>
<!-- Password Field -->
<div class="form-group">
<label for="password" class="form-label">
كلمة المرور
<span class="required" aria-label="مطلوب">*</span>
</label>
<input
type="password"
id="password"
class="form-input"
dir="ltr"
required
aria-required="true"
aria-describedby="password-hint"
/>
<span id="password-hint" class="form-hint">
يجب أن تحتوي على 8 أحرف على الأقل
</span>
</div>
<!-- Terms Checkbox -->
<div class="form-check">
<input
type="checkbox"
id="terms"
class="form-check-input"
required
aria-required="true"
/>
<label for="terms" class="form-check-label">
أوافق على <a href="/terms">الشروط والأحكام</a>
</label>
</div>
<!-- Submit Button -->
<button type="submit" class="btn btn-primary">
إنشاء حساب
</button>
</form>
Before launching forms for Arabic users:
Visual Testing:
Functional Testing:
Accessibility Testing:
Cross-Browser Testing:
Top-aligned labels work best: They're universal, responsive, and eliminate RTL-specific issues.
Use dir="auto" for flexible inputs: Let the browser detect text direction for name, address, and search fields.
Force LTR for technical inputs: Email, password, phone, and URLs should always be LTR.
Validate in Arabic: Error messages must be in the user's language for clarity.
CSS logical properties: Use inline-start, inline-end, text-align: start for automatic direction support.
Test with real users: Have native Arabic speakers test your forms on real devices.
Accessibility is non-negotiable: Proper ARIA labels, keyboard navigation, and screen reader support are essential.