Kitab
HomeBlogAboutDashboard
Kitab

A multilingual blog starter showcasing RTL support and Arabic typography.

Navigation

  • Home
  • Blog
  • About

Resources

  • GitHub
  • Documentation
  • Components

Connect

2025 Kitab. All rights reserved.

Made with noorui-rtl and Next.js

Kitab
HomeBlogAboutDashboard
Kitab

A multilingual blog starter showcasing RTL support and Arabic typography.

Navigation

  • Home
  • Blog
  • About

Resources

  • GitHub
  • Documentation
  • Components

Connect

2025 Kitab. All rights reserved.

Made with noorui-rtl and Next.js

  1. Home
  2. Blog
  3. Building Accessible Forms for Arabic Users
RTL/LTR Concepts

Building Accessible Forms for Arabic Users

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

12 min read0
Building Accessible Forms for Arabic Users
KA

Karim Benali

Senior frontend developer with 10+ years building RTL-first applications.

The Challenge of Forms in RTL

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.

Label Placement: What Works Best

The Traditional Approach (Left-Aligned Labels)

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.

The Better Approach: Top-Aligned Labels

For RTL forms, place labels above inputs:

RTL form with inline labels - poor UX
❌ Inline labels: Long eye travel distance
RTL form with top-aligned labels - good UX
✅ Top labels: Natural reading flow

Benefits:

  • Works identically in LTR and RTL
  • Shorter eye travel distance
  • Better for mobile responsive design
  • More space for longer translated labels
  • Cleaner visual hierarchy

Best Practice: Use top-aligned labels for all multilingual forms. They work universally and eliminate the need for direction-specific layouts.

Implementation

.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>

Text Alignment Inside Inputs

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:

  • Arabic text aligns to the right (RTL)
  • English text aligns to the left (LTR)
  • Text feels natural in both contexts
Comparison of text alignment in RTL inputs
Text aligned to 'start' automatically adjusts to reading direction

Placeholder Text Direction

Placeholder text should match the expected input language:

<!-- Arabic form -->
<input
  type="text"
  placeholder="أدخل البريد الإلكتروني"
  dir="auto"
/>
 
<!-- The dir="auto" attribute automatically detects text direction -->

The dir="auto" Attribute

This 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.

Mixed-Language Input Challenge

Real-world forms often need to accept mixed-language input. Consider a registration form:

  • Name: Arabic or Latin script
  • Email: Always LTR (example@domain.com)
  • Phone: Numbers (weakly LTR)
  • Password: Usually Latin characters and symbols
  • Address: Might be mixed

Strategy 1: Explicit Direction Setting

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 TypeDirectionReason
Namedir="auto"Could be Arabic or Latin
Emaildir="ltr"Email addresses are always LTR
Passworddir="ltr"Typically uses Latin characters
Phonedir="ltr"International format recognition
Addressdir="auto"Could be mixed language
Searchdir="auto"User might search in any language
Message/Commentdir="auto"User's natural language
URLdir="ltr"URLs are always LTR
Credit Carddir="ltr"Numbers and Latin characters

Strategy 2: Visual Indicators

Help users understand what format is expected:

Email field with LTR indicator in Arabic form
Email field with visual LTR indicator
Phone field with country code and format example
Phone field showing expected format
<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

Validation messages need careful positioning and clear messaging in Arabic.

Positioning

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;
}
Form validation messages in Arabic
Validation messages positioned below inputs with color and border indicators

Error Message Language

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';
}

Required Field Indicators

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;
}

Checkboxes and Radio Buttons

Checkbox and radio button alignment requires special attention in RTL.

Standard Pattern

<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;
}
Checkbox in LTR layout
LTR: Checkbox on left, label on right
Checkbox in RTL layout
RTL: Checkbox on right, label on left

Multi-Line Labels

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;
}

Select Dropdowns

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.

Accessibility (A11y) Considerations

Screen Reader Support

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>

ARIA Labels in Arabic

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>

Keyboard Navigation

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>

Complete Example: Registration Form

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>
Complete Arabic registration form example
A fully accessible registration form with proper RTL layout, validation, and accessibility features

Testing Checklist

Before launching forms for Arabic users:

Visual Testing:

  • Labels positioned above inputs
  • Text aligned to start in all inputs
  • Validation messages appear below inputs
  • Required indicators properly positioned
  • Checkboxes/radios aligned correctly
  • Dropdown arrows point correct direction
  • Button text and icons properly aligned

Functional Testing:

  • Tab order follows visual order (right-to-left)
  • Email/password fields stay LTR
  • Phone number formatting works
  • Validation messages in Arabic
  • Error messages clear and helpful

Accessibility Testing:

  • Screen reader announces labels in Arabic
  • ARIA labels in correct language
  • Required fields properly announced
  • Error states communicated clearly
  • Keyboard navigation works smoothly

Cross-Browser Testing:

  • Test in Chrome, Firefox, Safari
  • Test on iOS Safari and Chrome
  • Test on Android Chrome
  • Check form on different screen sizes

Key Takeaways

  1. Top-aligned labels work best: They're universal, responsive, and eliminate RTL-specific issues.

  2. Use dir="auto" for flexible inputs: Let the browser detect text direction for name, address, and search fields.

  3. Force LTR for technical inputs: Email, password, phone, and URLs should always be LTR.

  4. Validate in Arabic: Error messages must be in the user's language for clarity.

  5. CSS logical properties: Use inline-start, inline-end, text-align: start for automatic direction support.

  6. Test with real users: Have native Arabic speakers test your forms on real devices.

  7. Accessibility is non-negotiable: Proper ARIA labels, keyboard navigation, and screen reader support are essential.

Further Reading

  • CSS Logical Properties for RTL/LTR Support
  • Understanding RTL Text Direction
  • Common RTL Bugs and How to Fix Them
  • Icon Direction: What Flips and What Doesn't
forms
accessibility
rtl
arabic
ux
a11y
Back to Blog

Related Articles

Icon Direction: What Flips and What Doesn't

8 min read

Why Numbers Stay Left-to-Right in Arabic Text

7 min read

Responsive Design in Both Directions

9 min read

  1. Home
  2. Blog
  3. Building Accessible Forms for Arabic Users
RTL/LTR Concepts

Building Accessible Forms for Arabic Users

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

12 min read0
Building Accessible Forms for Arabic Users
KA

Karim Benali

Senior frontend developer with 10+ years building RTL-first applications.

The Challenge of Forms in RTL

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.

Label Placement: What Works Best

The Traditional Approach (Left-Aligned Labels)

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.

The Better Approach: Top-Aligned Labels

For RTL forms, place labels above inputs:

RTL form with inline labels - poor UX
❌ Inline labels: Long eye travel distance
RTL form with top-aligned labels - good UX
✅ Top labels: Natural reading flow

Benefits:

  • Works identically in LTR and RTL
  • Shorter eye travel distance
  • Better for mobile responsive design
  • More space for longer translated labels
  • Cleaner visual hierarchy

Best Practice: Use top-aligned labels for all multilingual forms. They work universally and eliminate the need for direction-specific layouts.

Implementation

.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>

Text Alignment Inside Inputs

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:

  • Arabic text aligns to the right (RTL)
  • English text aligns to the left (LTR)
  • Text feels natural in both contexts
Comparison of text alignment in RTL inputs
Text aligned to 'start' automatically adjusts to reading direction

Placeholder Text Direction

Placeholder text should match the expected input language:

<!-- Arabic form -->
<input
  type="text"
  placeholder="أدخل البريد الإلكتروني"
  dir="auto"
/>
 
<!-- The dir="auto" attribute automatically detects text direction -->

The dir="auto" Attribute

This 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.

Mixed-Language Input Challenge

Real-world forms often need to accept mixed-language input. Consider a registration form:

  • Name: Arabic or Latin script
  • Email: Always LTR (example@domain.com)
  • Phone: Numbers (weakly LTR)
  • Password: Usually Latin characters and symbols
  • Address: Might be mixed

Strategy 1: Explicit Direction Setting

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 TypeDirectionReason
Namedir="auto"Could be Arabic or Latin
Emaildir="ltr"Email addresses are always LTR
Passworddir="ltr"Typically uses Latin characters
Phonedir="ltr"International format recognition
Addressdir="auto"Could be mixed language
Searchdir="auto"User might search in any language
Message/Commentdir="auto"User's natural language
URLdir="ltr"URLs are always LTR
Credit Carddir="ltr"Numbers and Latin characters

Strategy 2: Visual Indicators

Help users understand what format is expected:

Email field with LTR indicator in Arabic form
Email field with visual LTR indicator
Phone field with country code and format example
Phone field showing expected format
<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

Validation messages need careful positioning and clear messaging in Arabic.

Positioning

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;
}
Form validation messages in Arabic
Validation messages positioned below inputs with color and border indicators

Error Message Language

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';
}

Required Field Indicators

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;
}

Checkboxes and Radio Buttons

Checkbox and radio button alignment requires special attention in RTL.

Standard Pattern

<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;
}
Checkbox in LTR layout
LTR: Checkbox on left, label on right
Checkbox in RTL layout
RTL: Checkbox on right, label on left

Multi-Line Labels

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;
}

Select Dropdowns

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.

Accessibility (A11y) Considerations

Screen Reader Support

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>

ARIA Labels in Arabic

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>

Keyboard Navigation

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>

Complete Example: Registration Form

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>
Complete Arabic registration form example
A fully accessible registration form with proper RTL layout, validation, and accessibility features

Testing Checklist

Before launching forms for Arabic users:

Visual Testing:

  • Labels positioned above inputs
  • Text aligned to start in all inputs
  • Validation messages appear below inputs
  • Required indicators properly positioned
  • Checkboxes/radios aligned correctly
  • Dropdown arrows point correct direction
  • Button text and icons properly aligned

Functional Testing:

  • Tab order follows visual order (right-to-left)
  • Email/password fields stay LTR
  • Phone number formatting works
  • Validation messages in Arabic
  • Error messages clear and helpful

Accessibility Testing:

  • Screen reader announces labels in Arabic
  • ARIA labels in correct language
  • Required fields properly announced
  • Error states communicated clearly
  • Keyboard navigation works smoothly

Cross-Browser Testing:

  • Test in Chrome, Firefox, Safari
  • Test on iOS Safari and Chrome
  • Test on Android Chrome
  • Check form on different screen sizes

Key Takeaways

  1. Top-aligned labels work best: They're universal, responsive, and eliminate RTL-specific issues.

  2. Use dir="auto" for flexible inputs: Let the browser detect text direction for name, address, and search fields.

  3. Force LTR for technical inputs: Email, password, phone, and URLs should always be LTR.

  4. Validate in Arabic: Error messages must be in the user's language for clarity.

  5. CSS logical properties: Use inline-start, inline-end, text-align: start for automatic direction support.

  6. Test with real users: Have native Arabic speakers test your forms on real devices.

  7. Accessibility is non-negotiable: Proper ARIA labels, keyboard navigation, and screen reader support are essential.

Further Reading

  • CSS Logical Properties for RTL/LTR Support
  • Understanding RTL Text Direction
  • Common RTL Bugs and How to Fix Them
  • Icon Direction: What Flips and What Doesn't
forms
accessibility
rtl
arabic
ux
a11y
Back to Blog

Related Articles

Icon Direction: What Flips and What Doesn't

8 min read

Why Numbers Stay Left-to-Right in Arabic Text

7 min read

Responsive Design in Both Directions

9 min read

Comments (0)

Sign in to join the conversation

Comments (0)

Sign in to join the conversation