هذا الدرس يبني على إمكانية الوصول — إن لم تكن قد قرأته بعد، ابدأ منه. هنا نتعمّق في أربع نقاط لا يكفيها درس مقدّمة واحد.
التركيز وترتيب التنقّل بـ Tab
كل عنصر تفاعلي (a, button, input...) قابل للتركيز تلقائيًا بترتيب ظهوره في الكود. السمة tabindex تتحكم بهذا:
<button tabindex="0">زر عادي — بترتيبه الطبيعي</button>
<button tabindex="-1">قابل للتركيز برمجيًا فقط، لا بـ Tab</button>
<button tabindex="3">❌ يقفز لترتيب مخصّص</button>
tabindex="0"يُدخل عنصرًا غير تفاعلي أصلًا (كـdiv) في ترتيب Tab الطبيعي — نادرًا ما تحتاجه لو استخدمت عناصر HTML التفاعلية الصحيحة أصلًا.tabindex="-1"يزيل العنصر من ترتيب Tab لكن يبقيه قابلًا للتركيز عبرelement.focus()في جافاسكريبت — مفيد لنقل التركيز برمجيًا (مثلًا إلى عنوان قسم بعد تنقّل داخل الصفحة).- أي قيمة موجبة أكبر من صفر تقريبًا خطأ دائمًا. ترتيب Tab المنطقي هو ترتيب العناصر في الكود نفسه — إعادة ترتيبه يدويًا بأرقام مخصّصة يكسر توقّعات المستخدم ويصعب صيانته.
⚠️ لا تُزل مؤشّر التركيز المرئي (outline) بلا بديل — مستخدم لوحة المفاتيح يفقد تمامًا معرفة أين هو في الصفحة. هذا قرار CSS لا HTML، لكن كمؤلّف HTML تذكّره كل مرة تضيف فيها
tabindex="-1"مؤقتًا لعنصر تفاعلي — ذلك يزيله من التنقّل بالكامل.
الاسم الوصولي (Accessible Name)
قارئ الشاشة يعلن "اسمًا" لكل عنصر تفاعلي. المتصفح يحسبه بترتيب أولوية: النص المرئي داخل العنصر أولًا، فـ aria-label، فـ aria-labelledby (يشير لعنصر آخر يحمل النص)، وأخيرًا title كحل أخير أضعفها.
<!-- ❌ غامض: قارئ الشاشة يعلن "زر" بلا أي سياق -->
<button>✕</button>
<!-- ✅ اسم وصولي واضح رغم أن الشكل المرئي أيقونة فقط -->
<button aria-label="إغلاق النافذة">✕</button>
المصدر الأفضل دائمًا نص مرئي حقيقي إن أمكن — aria-label حل جيد فقط حين لا يوجد نص مرئي (زر أيقونة بحتة).
تعدّد المعالم: حين يوجد أكثر من nav
راجعت في HTML الدلالي أن header/nav/main/aside/footer تمنح كل منها دور معلم (Landmark Role) تلقائيًا يتنقّل بينه مستخدم قارئ الشاشة مباشرة. لكن ماذا لو كان بصفحتك أكثر من nav واحد (تنقّل رئيسي أعلى الصفحة، وتنقّل فرعي داخل مقال طويل مثلًا)؟
<nav aria-label="التنقّل الرئيسي">...</nav>
<nav aria-label="فهرس هذا المقال">...</nav>
بلا aria-label مميّز، يسمع مستخدم قارئ الشاشة الذي يتصفّح قائمة المعالم "تنقّل، تنقّل" بلا أي طريقة للتفريق بينهما. نفس المبدأ ينطبق على تعدّد aside أو section ذات دلالة معلمية.
HTML الدلالي مقابل ARIA — القاعدة الأولى فعليًا
القاعدة الذهبية المذكورة في الدرس السابق تستحق مثالين ملموسين:
<!-- ❌ إعادة اختراع زر موجود أصلًا -->
<div role="button" tabindex="0" onclick="save()">حفظ</div>
<!-- ✅ العنصر الأصلي يمنحك كل هذا مجانًا: تركيز، تفعيل بـ Enter/Space، دور button -->
<button onclick="save()">حفظ</button>
النسخة الأولى تحتاج منك يدويًا: tabindex للتركيز، role للدلالة، ومعالج ضغط مفتاح إضافي لأن div لا يستجيب لـ Enter/Space تلقائيًا كما يفعل button — تفصيل يُنسى غالبًا فيكسر الوصول رغم النية الحسنة.
ARIA ضرورية فعلًا حين لا يوجد عنصر HTML أصلي بنفس السلوك — مثل تبويبات (Tabs) مخصّصة التصميم لا تطابقها أي عناصر HTML قياسية؛ هناك تحتاج فعلًا role="tablist"/role="tab"/role="tabpanel" مع إدارة تركيز يدوية دقيقة. هذه حالة متقدّمة تستحق دراسة منفصلة عند بنائها فعليًا — النقطة هنا أن تعرف متى تحتاجها فعلًا لا أن تلجأ إليها افتراضيًا.
كيف تكتشف أخطر الأخطاء فعليًا
الدرس السابق ذكر Lighthouse وقارئات الشاشة كأدوات — إليك كيف تستخدمها فعليًا لا مجرد معرفة أنها موجودة:
- افصل الفأرة فعليًا وتصفّح صفحتك بـ Tab وShift+Tab وEnter فقط. أي عنصر لا تستطيع الوصول إليه أو تفعيله هكذا يفشل مع مستخدمي لوحة المفاتيح الحقيقيين.
- شغّل قارئ شاشة حقيقيًا لخمس دقائق: NVDA (مجاني، ويندوز) أو VoiceOver (مدمج، Mac/iOS). اسمع صفحتك كما يسمعها مستخدم فعلي — التجربة تكشف مشاكل لا يراها أي أداة آلية.
- افتح شجرة إمكانية الوصول (Accessibility Tree) في أدوات المطوّر (تبويب Accessibility في Chrome/Edge DevTools) — تُظهر بالضبط الاسم والدور اللذين سيسمعهما قارئ الشاشة لكل عنصر، فتكتشف فورًا لو كان زرك بلا اسم وصولي.
الأخطاء الشائعة
- ❌
tabindexموجب مخصّص لإعادة ترتيب التنقّل بدل الاعتماد على ترتيب الكود. - ❌ زر أيقونة بلا
aria-label— قارئ الشاشة يعلن "زر" بلا أي معنى. - ❌ أكثر من
navبلاaria-labelمميّز — يضيع المستخدم بين المعالم المتشابهة. - ❌ إعادة بناء عنصر HTML موجود أصلًا بـ ARIA يدويًا بدل استخدام العنصر الدلالي المناسب مباشرة.
خلاصة
إمكانية الوصول المتقدمة تعني تفاصيل دقيقة: ترتيب تركيز منطقي بلا tabindex مخصّص، اسم وصولي واضح لكل عنصر تفاعلي، تمييز المعالم المتكررة بـ aria-label، وتفضيل HTML الدلالي دائمًا على إعادة بناء نفس السلوك بـ ARIA يدويًا. الأداة الأهم لاختبار كل هذا: افصل الفأرة وجرّب صفحتك بنفسك.