اختبار قارئات الشاشة
يتحقق اختبار قارئات الشاشة (Screen reader testing) مما إذا كانت الصفحة أو التطبيق يكشفان المعلومات الصحيحة للتقنيات المساعدة: ما هو كل عنصر (دوره)، وما اسمه (اسمه القابل للوصول)، وما حالته، وكيف يُنظَّم المحتوى، وما إذا كانت التغييرات تُعلَن. فقارئ الشاشة لا ينطق إلا بما تخبره به الشيفرة، ولذلك فمعظم الإخفاقات دلالية — زر هو في الحقيقة div، وأيقونة بلا اسم، وعنوان هو مجرد نص عريض.
يشرح هذا الدليل كيف تستخدم قارئات الشاشة الدلالات، وكيف تُحسب الأسماء القابلة للوصول، وما الذي يُفحص في العناوين والمعالم والروابط وعناصر التحكم، وقواعد استخدام ARIA، وكيف يُختبر المحتوى الديناميكي والمناطق الحية، وأي ثنائيات قارئ شاشة ومتصفح تُستخدم، مع روتين اختبار عملي وحالات اختبار وأمثلة عيوب.
كيف تستخدم قارئات الشاشة الدلالات
يحوّل المتصفح DOM إلى شجرة إمكانية الوصول (Accessibility tree): بنية موازية يكون فيها لكل عنصر ذي معنى دور (زر، رابط، عنوان، حقل نص)، واسم، وحالات وخصائص (موسَّع، محدَّد، إلزامي، غير صالح)، وعلاقات. وتمرر واجهة إمكانية الوصول في نظام التشغيل هذه الشجرة إلى قارئ الشاشة الذي ينطقها أو يرسلها إلى شاشة برايل. والتنسيق البصري لا يغيّر دور العنصر: فعنصر div منسّق ليبدو زراً يبقى عنصراً عاماً (generic) في الشجرة. لكن CSS ليست بلا أثر على الشجرة: فالقيمتان display: none وvisibility: hidden تُخرجان المحتوى منها، والنص الذي تولّده CSS (عبر ::before و::after) قد يصبح جزءاً من الاسم القابل للوصول.
- 1DOMعناصر HTML وسمات ARIA
<button aria-label="Search">فرع: أيقونة فقط دون aria-label: لا اسم، فلا يُسمع إلا «button»فشل
- 2شجرة إمكانية الوصوليبنيها المتصفحالدور · الاسم · الحالات والخصائص · العلاقات
role: button · name: "Search" - 3واجهة إمكانية الوصول في نظام التشغيلتمرّر الشجرة إلى قارئ الشاشة
- 4قارئ الشاشة
- 5نطق أو شاشة برايل
"Search, button"المتوقع
رسم مبسّط. التنسيق لا يغيّر الدور: عنصر div منسّق ليبدو زراً يبقى عنصراً عاماً (generic) في الشجرة. لكن CSS قد تُخرج محتوى منها بـ display: none أو visibility: hidden، أو تضيف نصاً إلى الاسم بـ ::before أو ::after.
لهذا تأتي HTML الأصلية أولاً. فالعنصر button له دور الزر، ويتلقى التركيز، ويُفعَّل بـ Enter وSpace، ويأخذ اسمه من نصه — كل ذلك دون شيفرة إضافية. والعناوين (h1 إلى h6)، والقوائم، والجداول مع th، وعناصر label، وfieldset مع legend، والمعالم مثل nav وmain تمنح مستخدمي قارئات الشاشة البنية نفسها التي يراها المبصرون. ومعظم إخفاقات WCAG التي تتناولها هذه الصفحة تقع تحت 1.3.1 Info and Relationships (يجب أن تكون البنية قابلة للتحديد برمجياً) و4.1.2 Name, Role, Value (كل مكوّن واجهة يكشف اسمه ودوره وحالاته وقيمته).
لقارئات الشاشة المكتبية على Windows طريقتا عمل رئيسيتان. في وضع التصفح (Browse mode، ويسمى أيضاً المؤشر الافتراضي) يقرأ المستخدم الصفحة بمفاتيح الأسهم ويقفز حسب نوع العنصر بحروف مفردة؛ وفي وضع التركيز (Focus mode أو وضع النماذج) تذهب ضغطات المفاتيح إلى عنصر التحكم الذي عليه التركيز، فتعمل الكتابة في الحقول وتشغّل الأسهم العناصر. وتنتقل قارئات الشاشة بين الوضعين تلقائياً مع كثير من عناصر التحكم؛ والعناصر المخصصة التي تكسر هذا الانتقال مصدر شائع للعيوب.
الأسماء والأوصاف القابلة للوصول
الاسم القابل للوصول (Accessible name) هو ما يعلنه قارئ الشاشة للعنصر، وهو ما ينطقه مستخدمو التحكم الصوتي لتفعيله. وتحسبه المتصفحات وفق مواصفة W3C لحساب الاسم والوصف القابلين للوصول (accname 1.2، وهي حالياً مسودة عمل Working Draft). وباختصار، يؤخذ الاسم من أول مصدر ينطبق مما يلي:
- aria-labelledby — نص العنصر أو العناصر المشار إليها.
- aria-label — سلسلة نصية على العنصر نفسه.
- التسمية الأصلية — العنصر label لحقول النماذج، وalt للصور، وcaption للجداول، وlegend لمجموعات الحقول.
- المحتوى — للأدوار التي تسمح بذلك، كالأزرار والروابط والعناوين، نص العنصر نفسه.
- البدائل الاحتياطية — السمة title، ونص التلميح الظاهر داخل الحقل الفارغ؛ وهي غير موثوقة ولا ينبغي أن تكون الاسم الوحيد.
فحص الأسماء والتسميات والأوصاف عملياً
استخدم لوحة إمكانية الوصول في أدوات المطوّر بالمتصفح لرؤية الاسم والدور والحالات المحسوبة للعنصر قبل أن تستمع إليه: فهي تخبرك لماذا يُعلَن الشيء بالطريقة التي يُعلَن بها. ثم افحص ثلاثة أمور. أولاً، لكل عنصر تفاعلي اسم — وأزرار الأيقونات فقط (البحث، والإغلاق، والحذف، والقائمة) هي الإخفاق الكلاسيكي. ثانياً، يحتوي الاسم على التسمية المرئية: يشترط المعيار 2.5.3 Label in Name أن يتضمن الاسم القابل للوصول لعنصر التحكم النصَّ الظاهر في تسميته، فالزر الذي يعرض «إرسال» لا يجوز أن يكون اسمه «تقديم النموذج». ثالثاً، الاسم مفيد خارج سياقه: «حذف» في قائمة من عشرين عنواناً أفضل منه «حذف العنوان: 12 شارع العليا».
يضيف الوصف (Description) معلومات ثانوية، عادةً عبر aria-describedby: قاعدة كلمة المرور، أو صيغة التاريخ، أو رسالة خطأ مرتبطة بحقل. وتُعلَن الأوصاف بعد الاسم والدور، وأحياناً بعد توقف، ويستطيع المستخدمون إيقاف بعضها، لذا فالمعلومة الحرجة مكانها الاسم أو التسمية المرئية. ويغطي دليل النماذج القابلة للوصول تسميات النماذج وتعليماتها ورسائل أخطائها بالتفصيل.
العناوين والمعالم وعناوين الصفحات
نادراً ما يقرأ مستخدمو قارئات الشاشة الصفحة من أعلاها إلى أسفلها. فهم يفتحون قائمة بالعناوين أو المعالم، أو يقفزون من عنوان إلى عنوان، ليجدوا الجزء الذي يحتاجونه. وهذا يجعل البنية قابلة للاختبار: افتح قائمة العناوين وقارنها بما تراه. يجب أن يكون كل عنوان مرئي عنصر عنوان حقيقياً، وأن تعكس المستويات التسلسل الهرمي (عنوان h1 رئيسي واحد، وh2 للأقسام، وh3 داخلها)، وأن يصف نص العنوان قسمه (2.4.6 Headings and Labels). والنص المنسّق الذي يبدو عنواناً دون أن يُرمَّز كذلك يخفق في 1.3.1.
تحدد المعالم (Landmarks) مناطق الصفحة: header (banner)، وnav (navigation)، وmain، وaside (complementary)، وfooter (contentinfo)، إضافة إلى مناطق search وform. تحقق من أن المحتوى الرئيسي داخل main، وأن التنقل المتكرر داخل nav، وأنه عند وجود عدة مناطق من النوع نفسه تحمل كل منها تسمية مثل «القائمة الرئيسية» و«روابط التذييل». وأخيراً، عنوان الصفحة هو أول ما يُعلَن: يشترط المعيار 2.4.2 Page Titled عنواناً يصف موضوع الصفحة أو غرضها، ويجب على تطبيقات الصفحة الواحدة تحديثه مع كل تغيير في المسار.
الروابط والأزرار وعناصر النماذج والصور
الروابط تنقل؛ والأزرار تنفّذ. فالرابط الذي يرسل نموذجاً، أو الزر الذي ينتقل إلى صفحة أخرى، يربك المستخدمين لأن الدور يتنبأ بالسلوك. ويجب أن يوضح نص الرابط غرضه من النص نفسه أو من سياقه (2.4.4 Link Purpose (In Context))؛ وقائمة روابط مليئة بـ «انقر هنا» و«اقرأ المزيد» تخذل من يتنقل بالروابط. ويجب أن تعلن الأزرار حالتها إن كانت لها حالة: aria-pressed لأزرار التبديل، وaria-expanded للأزرار التي تفتح القوائم والأكورديونات وعناصر الإفصاح.
تحتاج عناصر النماذج إلى اسم ودور وقيمة حالية وحالة (إلزامي، غير صالح، محدَّد، مختار)، وإلى ربط رسالة الخطأ بها لتُعلَن — ويغطي دليل النماذج القابلة للوصول ذلك بالتفصيل. وتحتاج الصور إلى بديل نصي يؤدي الغرض نفسه (1.1.1 Non-text Content): نص alt ذو معنى للصور المعلوماتية، وalt فارغ للصور الزخرفية ليتخطاها قارئ الشاشة؛ ويغطي دليل إمكانية الوصول البصرية نص alt بالتفصيل.
ARIA: الأدوار والحالات والخصائص وقواعد استخدامها
تعرّف WAI-ARIA 1.2 (توصية W3C) الأدوار (Roles: ما هو العنصر، مثل tab وdialog وmenu وalert)، والحالات (States: ظروف تتغير، مثل aria-expanded وaria-checked وaria-selected)، والخصائص (Properties: سمات أكثر ثباتاً، مثل aria-label وaria-controls وaria-required). ولا تغيّر ARIA إلا ما يُكشف في شجرة إمكانية الوصول؛ فهي لا تغيّر السلوك. ودليل ممارسات تأليف ARIA صريح في أن أدوار ARIA لا تجعل المتصفحات توفر سلوك لوحة المفاتيح أو التنسيق — فعنصر div بدور role="button" ما زال يحتاج إلى tabindex ومعالجات للمفاتيح.
قطعتان من إرشادات W3C تلخصان طريقة استخدامها. «القاعدة الأولى لاستخدام ARIA» المعروفة منذ زمن تقول إنه إذا أمكنك استخدام عنصر أو سمة HTML أصلية فيها الدلالات والسلوك المطلوبان مدمجين، فافعل ذلك بدلاً من إضافة ARIA إلى عنصر آخر. ويحذّر مبدأ APG «No ARIA is better than bad ARIA» (غياب ARIA أفضل من ARIA السيئة) من أن ARIA الخاطئة تشوّه تمثيل ما على الشاشة، مما قد يجعل التجربة أسوأ من عدم استخدامها أصلاً. وفي الاختبار، أكثر عيوب ARIA شيوعاً:
- دور بلا سلوك — role="button" أو role="tab" أو role="checkbox" على عناصر لا يمكن التركيز عليها أو تشغيلها من لوحة المفاتيح.
- حالات لا تتغير أبداً — تبقى aria-expanded على "false" بعد فتح القائمة؛ ولا تنتقل aria-selected عند اختيار تبويب آخر.
- aria-hidden="true" على محتوى يحوي عناصر قابلة للتركيز، فيقع تركيز لوحة المفاتيح على شيء لا يدركه قارئ الشاشة.
- aria-label على div أو span عادي بلا دور — إذ تحظر WAI-ARIA 1.2 تسمية الدور generic، فقد لا يُنطق الاسم.
- اسم يناقض التسمية المرئية، وهو إخفاق في 2.5.3 Label in Name.
- أدوار تطبيقات على محتوى عادي — role="menu" على قائمة تنقل الموقع، أو role="application" على منطقة من الصفحة، مما يغيّر طريقة تعامل قارئ الشاشة مع المفاتيح.
المحتوى الديناميكي والمناطق الحية ورسائل الحالة
كل ما يتغير دون تحميل صفحة يبقى غير مرئي لمستخدم قارئ الشاشة ما لم يُعلَن أو ينتقل التركيز إليه. فاختر بين الأمرين عن قصد. انقل التركيز عندما يجب على المستخدم التعامل مع المحتوى الجديد (فتح نافذة حوار، أو تحميل عرض صفحة جديد). وأعلن دون نقل التركيز عندما يكفي أن يعرف المستخدم أن شيئاً حدث: «تم الحفظ»، «3 نتائج»، «أُضيف المنتج إلى السلة»، «جارٍ الرفع 40%». والحالة الثانية هي بالضبط المعيار 4.1.3 Status Messages، الذي يشترط أن تكون رسائل الحالة قابلة للتحديد برمجياً عبر دور أو خصائص حتى تعرضها التقنيات المساعدة دون أن تتلقى التركيز.
الأدوات هنا هي المناطق الحية (Live regions). يناسب role="status" (مهذّب: يُعلَن عندما يكون المستخدم خاملاً) أعداد النتائج والتأكيدات؛ ويُخصَّص role="alert" (حازم: يقاطع) للرسائل المهمة والحساسة للوقت كالأخطاء؛ ويناسب role="log" المحادثات وسجلات النشاط. وعند الاختبار، أطلق كل تغيير واستمع. الإخفاقات المعتادة: تُدرَج المنطقة الحية في الصفحة في اللحظة نفسها مع نصها فلا يُعلَن شيء؛ أو تُخفى المنطقة بـ display: none؛ أو يعلن مؤشر التحميل «جارٍ التحميل» كل نصف ثانية؛ أو يكون كل شيء تنبيهاً فيُقاطَع المستخدم باستمرار.
ثنائيات قارئ الشاشة والمتصفح
تُختبر قارئات الشاشة والمتصفحات أزواجاً، لأن كليهما يشارك في إنتاج النتيجة. اختر الثنائيات بناءً على بيانات جمهورك وخط الأساس لدعم إمكانية الوصول في عقدك، واجعل القائمة قصيرة، وتناوب عليها عبر الإصدارات بدلاً من اختبار كل شيء في كل سبرنت.
- Windows — NVDA (مجاني ومفتوح المصدر) مع Firefox أو Chrome؛ وJAWS (تجاري) مع Chrome أو Edge؛ وNarrator المدمج في Windows مع Edge.
- macOS — VoiceOver المدمج، ويُختبر عادةً مع Safari.
- iOS وiPadOS — VoiceOver مع Safari ومع التطبيقات الأصلية.
- Android — TalkBack مع Chrome ومع التطبيقات الأصلية.
- سجّل إصدارات قارئ الشاشة والمتصفح ونظام التشغيل مع كل نتيجة؛ فالسلوك يتغير بين الإصدارات.
روتين عملي لاختبار قارئ الشاشة
تعلّم مجموعة صغيرة من الأوامر جيداً بدلاً من تعلّمها كلها. يغطي هذا الروتين معظم الصفحات في خمس عشرة إلى ثلاثين دقيقة على ثنائية واحدة؛ اجعل سرعة النطق مريحة في البداية، ودوّن بدقة ما تسمعه.
- 1. حمّل الصفحة — هل يُعلَن عنوانها؟ وهل اللغة والصوت صحيحان؟
- 2. قائمة العناوين — في NVDA: NVDA+F7 (قائمة العناصر)؛ وفي JAWS: Insert+F6؛ وفي VoiceOver على macOS: VO+U (الدوّار Rotor). هل يطابق المخطط البنية المرئية؟
- 3. المعالم — في NVDA: المفتاح D؛ وفي JAWS: المفتاح R؛ وفي VoiceOver: الدوّار ثم Landmarks.
- 4. قائمة الروابط — في NVDA: NVDA+F7؛ وفي JAWS: Insert+F7. هل لكل رابط معنى مفهوم؟
- 5. القراءة بالترتيب — في NVDA وJAWS: Down Arrow؛ وفي VoiceOver على macOS: VO+Right Arrow؛ وفي VoiceOver على iOS وTalkBack: السحب إلى اليمين.
- 6. تشغيل عناصر التحكم — انتقل بـ Tab إلى كل عنصر: هل يُعلَن الاسم والدور والحالة؟ فعّله بـ Enter أو Space، وعلى iOS وAndroid بالنقر المزدوج.
- 7. النماذج — هل تُعلَن التسميات والحقول الإلزامية والأخطاء عند الإرسال؟
- 8. التغييرات الديناميكية — أطلق الإشعارات والمرشحات والتحميل: هل تُعلَن دون نقل التركيز؟
- 9. نوافذ الحوار — هل تُعلَن على أنها نافذة حوار مع اسمها؟ وهل تصمت الصفحة خلفها؟ وهل يعود التركيز عند إغلاقها؟
- 10. أكمل مهمة حقيقية — أنهِ عملية واحدة (بحثاً أو إتمام شراء) بقارئ الشاشة وحده.
- مفتاح NVDA هو Insert (ويمكن ضبط Caps Lock أيضاً)، وVO هو Control+Option؛ ويبدّل NVDA+Space بين وضعي التصفح والتركيز، ويوقف Ctrl النطق.
1. Load the page Title announced? Language/voice correct?
2. Headings list NVDA: NVDA+F7 (Elements list) · JAWS: Insert+F6 · VoiceOver macOS: VO+U (rotor)
Does the outline match the visual structure?
3. Landmarks NVDA: D · JAWS: R · VoiceOver: rotor > Landmarks
4. Links list NVDA: NVDA+F7 · JAWS: Insert+F7 — does each link make sense?
5. Read in order NVDA/JAWS: Down Arrow · VoiceOver macOS: VO+Right Arrow
iOS VoiceOver / TalkBack: swipe right
6. Operate controls Tab to each control: name + role + state announced?
Activate: Enter/Space · iOS/Android: double-tap
7. Forms Labels, required, errors announced on submit?
8. Dynamic changes Trigger toasts, filters, loading: announced without focus move?
9. Dialogs Announced as dialog with its name? Background silent? Focus returns on close?
10. Complete task Finish one real process (search, checkout) with the screen reader only
NVDA key = Insert (Caps Lock can also be set) · VO = Control+Option
NVDA: NVDA+Space toggles browse/focus mode · Ctrl stops speechحالات اختبار قارئ الشاشة
استخدمها نتائجَ متوقعة لكل نوع صفحة وكل عملية كاملة ضمن النطاق، مع تسجيل الثنائية المستخدمة مع كل نتيجة.
- SR-01 — يُعلَن عنوان الصفحة عند التحميل ويصف الصفحة (2.4.2).
- SR-02 — لغة الصفحة صحيحة والنص يُقرأ بالصوت الصحيح؛ والمقاطع بلغة أخرى تبدّل الصوت (3.1.1 و3.1.2).
- SR-03 — قائمة العناوين تعكس البنية المرئية بمستويات منطقية (1.3.1 و2.4.6).
- SR-04 — توجد معالم main والتنقل والترويسة والتذييل؛ والأنواع المتكررة من المعالم مسمّاة.
- SR-05 — غرض كل رابط واضح من نصه أو سياقه (2.4.4).
- SR-06 — كل زر وعنصر تحكم يعلن الاسم والدور والحالة؛ وأزرار التبديل تعلن الضغط أو التوسيع (4.1.2).
- SR-07 — للصور المعلوماتية بدائل ذات معنى؛ والصور الزخرفية صامتة (1.1.1).
- SR-08 — العناصر المخصصة تعلن الدور الصحيح وكل تغيير في الحالة (4.1.2).
- SR-09 — رسائل الحالة تُعلَن دون نقل التركيز (4.1.3).
- SR-10 — تُعلَن النافذة المشروطة كنافذة حوار باسمها، ولا تُقرأ الصفحة خلفها ما دامت مفتوحة.
- SR-11 — لا شيء مرئي مخفي عن قارئ الشاشة، ولا شيء مخفي يُقرأ.
- SR-12 — يمكن إتمام عملية كاملة واحدة على الأقل بقارئ الشاشة وحده.
أمثلة على العيوب
مصاغة كعناوين تقارير أخطاء. وفي التقرير أضف الثنائية مع الإصدارات، والخطوات، والإعلان المسموع بنصه — مثلاً: NVDA 2026.x مع Firefox، الانتقال بـ Tab إلى أيقونة البحث، سُمع «button»، والمتوقع «Search, button».
- «زر أيقونة البحث يُعلَن كـ button دون اسم» — 4.1.2 Name, Role, Value.
- «عناوين أكورديون الأسئلة الشائعة لا تعلن حالة التوسيع أو الطي» — 4.1.2 Name, Role, Value.
- «صفحة العروض فيها اثنا عشر رابطاً تُعلَن جميعها «اقرأ المزيد»» — 2.4.4 Link Purpose (In Context).
- «عناوين الأقسام عناصر div منسقة؛ وقائمة العناوين فارغة» — 1.3.1 Info and Relationships.
- «عدد النتائج بعد تطبيق المرشحات لا يُعلَن» — 4.1.3 Status Messages.
- «aria-hidden على الترويسة يخفي زر القائمة القابل للتركيز عن قارئ الشاشة» — 4.1.2 Name, Role, Value.
- «زر «إرسال» يحمل aria-label بقيمة «تقديم النموذج»؛ والأمر الصوتي «انقر إرسال» لا يفعل شيئاً» — 2.5.3 Label in Name.
- «شعار الشركة يُعلَن كـ logo-final-v2.png» — 1.1.1 Non-text Content.
جرّبها: مولّد عناوين الأخطاء بالذكاء الاصطناعي جرّبها: مولّد وصف الأخطاء بالذكاء الاصطناعي
الأسئلة الشائعة
بأي قارئ شاشة يجب أن أختبر؟
بالثنائيات التي يتطلبها مستخدموك وخط الأساس للدعم في عقدك. والحد الأدنى الشائع ثنائية واحدة على Windows مثل NVDA مع Firefox أو Chrome، إضافة إلى VoiceOver على iOS وTalkBack على Android للجوال. وتناوب على الثنائيات الأخرى عبر الإصدارات.
هل نضيف aria-label إلى كل شيء؟
لا. تأخذ معظم العناصر أسماءها من النص المرئي أو التسميات الأصلية، وهذا يُبقي مستخدمي قارئات الشاشة والمستخدمين المبصرين على المعلومات نفسها. استخدم aria-label أساساً لعناصر التحكم التي بلا نص مرئي كأزرار الأيقونات، ولا تدعه يناقض التسمية المرئية أبداً.
هل ARIA ضرورية لجعل الصفحة قابلة للوصول؟
لا. الصفحة المبنية من عناصر HTML أصلية بتسميات مرئية وعناوين ومعالم حقيقية قابلة للوصول إلى حد كبير دون أي ARIA. وARIA مخصصة لما لا تستطيع HTML التعبير عنه، كالتبويبات وحالات التوسيع والمناطق الحية، ويجب اختبارها كأي شيفرة أخرى.
لماذا لا تعلن منطقتي الحية شيئاً؟
غالباً لأن المنطقة أُضيفت إلى الصفحة مع رسالتها في اللحظة نفسها، أو لأنها مخفية بـ display: none، أو لأن النص لم يتغير. اعرض المنطقة فارغة عند تحميل الصفحة وحدّث نصها لاحقاً، وتحقق من أن الدور (status أو alert) يناسب الرسالة.
هل تقرأ قارئات الشاشة العربية؟
تستطيع قارئات الشاشة الرئيسية نطق العربية عند توفر صوت عربي، وتعتمد على سمة lang في الصفحة لتطبيق قواعد النطق الصحيحة. تحقق من أن الصفحات العربية تعلن lang="ar"، وأن المقاطع الإنجليزية داخلها معلَّمة، وأن الأرقام والسلاسل المختلطة تُقرأ بترتيب منطقي.
المراجع
- Accessible Rich Internet Applications (WAI-ARIA) 1.2توصية W3C التي تعرّف أدوار ARIA وحالاتها وخصائصها — أي كيف تُعلن عناصر الواجهة المخصّصة معناها للتقنيات المساعدة.
- ARIA Authoring Practices Guide (APG)أنماط للعناصر الشائعة (التبويبات والقوائم ونوافذ الحوار والقوائم المنسدلة) مع تفاعل لوحة المفاتيح المتوقع واستخدام ARIA — المرجع الذي تُقارَن به المكونات المخصصة.
- Accessible Name and Description Computation 1.2كيف تحسب المتصفحات الاسم والوصف الميسَّرين لعنصرٍ من التسميات وسمات ARIA والمحتوى (مسودة عمل من W3C).
- Web Content Accessibility Guidelines (WCAG) 2.2توصية W3C التي تحدد معايير النجاح القابلة للاختبار لإتاحة محتوى الويب، مرتّبةً تحت أربعة مبادئ وثلاثة مستويات مطابقة (A وAA وAAA).
- Understanding WCAG 2.2الشرح التوضيحي لكل إرشاد ومعيار نجاح في WCAG 2.2: الغرض، ومن يستفيد، والأمثلة والتقنيات (غير إلزامي).
- Accessibility — MDNأدلة عملية لبناء صفحات ويب ميسّرة وفحصها: HTML الدلالي وARIA ودعم لوحة المفاتيح والاختبار.
- Accessibility — Human Interface Guidelinesإرشادات Apple لتصميم إمكانية الوصول في iOS وغيره: VoiceOver والنص الديناميكي والتباين وأهداف اللمس والحركة.
- Test your app's accessibilityكيف تُختبر إمكانية الوصول في تطبيق Android يدوياً باستخدام TalkBack وغيره، وآلياً بأدوات الاختبار في المنصة.
تمرين عملي
راجع جلسة اختبار بقارئ الشاشة على صفحة نتائج بحث
أنت تختبر الواجهة الإنجليزية لتطبيق الويب Dawa، وهو صيدلية إلكترونية (مثال خيالي). أجرى زميلك عمر روتين الاختبار الوارد في الدليل على صفحة نتائج البحث بثنائية واحدة هي NVDA مع Firefox، ودوّن بدقة ما سمعه. وقبل أن يسجّل تقارير الأخطاء، تراجع أنت سجلّه مقابل شيفرة الصفحة. تعرض المادة أدناه المهمة ضمن النطاق، ومقتطفاً من الشيفرة، وما تفعله السكربتات، والسجل. والإعلانات المسموعة مقتبسة بالإنجليزية لأن الصفحة المختبَرة هي الواجهة الإنجليزية.
اعمل على الورق مستعيناً بترتيب حساب الاسم في الدليل، وبحالات الاختبار من SR-01 إلى SR-12، وبمعايير WCAG 2.2 التي يستشهد بها. ليس كل صف إخفاقاً، وليست كل مشكلة إخفاقاً في WCAG؛ فبيّن نوع كل ملاحظة. وإن توفر لديك NVDA أو VoiceOver فيمكنك حفظ المقتطف ملفَّ HTML محلياً والاستماع إلى الأسماء والأدوار بنفسك؛ ستختلف الصياغة، أما الملاحظات فلا ينبغي أن تختلف. خصّص لذلك 30–45 دقيقة.
Dawa - تطبيق ويب لصيدلية إلكترونية (مثال خيالي). واجهة إنجليزية، وتوجد واجهة عربية أيضاً.
الصفحة المختبَرة: نتائج البحث، بيئة Staging، البناء 3.8.0، وهي تطبيق صفحة واحدة.
في الصفحة ترويسة ومحتوى رئيسي فقط: لا قائمة تنقل ولا تذييل ولا نافذة حوار.
المهمة ضمن النطاق: في نتائج «vitamin D» رشّح إلى 1000 IU، وأضف عبوة واحدة
من المنتج الأول إلى السلة.
الثنائية: NVDA مع Firefox على Windows 11 (لم يدوّن المختبِر الإصدارات).
الإعلانات مكتوبة بصيغة الاسم، الدور، الحالة كما في الدليل؛ والصياغة والترتيب
الفعليان يختلفان بين قارئات الشاشة وإصداراتها.
مقتطف من الشيفرة (بطاقة منتج واحدة؛ والبطاقات الإحدى عشرة الأخرى بالقالب نفسه)
<html lang="ar">
<head><title>Dawa</title></head>
<body>
<header>
<a href="/"><img src="/img/logo.svg" alt="Dawa home"></a>
<button class="icon" onclick="openSearch()"><svg class="i-search"></svg></button>
</header>
<main>
<h1>Results for vitamin D</h1>
<p id="count">12 products</p>
<div class="toggle" role="button" tabindex="0" aria-expanded="false"
onclick="toggleFilters()">Filters</div>
<div id="filters" hidden>
<label><input type="checkbox" onchange="applyFilter()"> 1000 IU</label>
</div>
<ul class="products">
<li>
<img src="/p/IMG_4021.jpg" alt="IMG_4021.jpg">
<div class="card-title">Vitamin D3 1000 IU, 60 tablets</div>
<p>SAR 39.00</p>
<a href="/p/4021">Details</a>
<button aria-label="Buy now" onclick="addToCart(4021)">Add to cart</button>
</li>
</ul>
</main>
</body>
</html>
ما تفعله السكربتات (حسب المطوّر)
toggleFilters() تُظهر #filters أو تخفيها، ولا تغيّر شيئاً آخر
applyFilter() تعيد تحميل القائمة وتستبدل نص #count، مثلاً «4 products»
addToCart(id) عند النجاح تُلحق هذا العنصر بـ body وتزيله بعد 3 ثوانٍ:
<div class="toast" role="status">Added to cart</div>
على الشاشة يظهر اسم المنتج (card-title) كبيراً وعريضاً ويبدو عنواناً.
سجل الجلسة (المختبِر: عمر)
1 حمّل الصفحة: فتح النتائج من الصفحة الرئيسية، ثم NVDA+T (قراءة العنوان).
المسموع: «Dawa» واسم المتصفح. والنص الإنجليزي الذي يليه يُقرأ بصوت عربي
ويصعب فهمه.
2 قائمة العناوين: NVDA+F7 ثم Headings. عنصر واحد: «Results for vitamin D»، المستوى 1.
3 المعالم: D ثم D. المسموع: «banner landmark» و«main landmark».
4 قائمة الروابط: NVDA+F7 ثم Links. المسموع: «Dawa home»، ثم «Details» 12 مرة.
5 القراءة بالترتيب: Down Arrow عبر البطاقة الأولى. المسموع: «list, 12 items»،
«IMG_4021.jpg, graphic»، «Vitamin D3 1000 IU, 60 tablets»، «SAR 39.00»،
«Details, link»، «Buy now, button».
6 تشغيل عناصر التحكم: Tab إلى أيقونة البحث. المسموع: «button».
Tab إلى «Filters». المسموع: «Filters, button, collapsed».
Enter: تُفتح لوحة المرشحات على الشاشة.
Shift+Tab ثم Tab. المسموع: «Filters, button, collapsed».
7 التغييرات الديناميكية: Space على مربع الاختيار «1000 IU».
المسموع: «1000 IU, checkbox, checked». وعلى الشاشة يتغير العدد إلى «4 products»،
ولا يُسمع شيء آخر.
8 التغييرات الديناميكية: Enter على «Buy now» في البطاقة الأولى. على الشاشة:
«Added to cart» لمدة 3 ثوانٍ. لم يُسمع شيء، فضغط عمر Enter مرة أخرى.
9 أكمل المهمة: صفحة السلة: «Vitamin D3 1000 IU, 60 tablets» x 2.
ملاحظة عمر: «لم يخبرني شيء بأن الإضافة نجحت».- قبل قراءة السجل، اكتب من الشيفرة وحدها ما تكشفه كل صورة وكل عنصر تحكم — الاسم والدور والحالة: رابط الشعار، وأيقونة البحث، وزر «Filters» قبل الفتح وبعده، وصورة المنتج، ورابط «Details»، وزر «Add to cart». اتبع ترتيب الاسم في الدليل:
aria-labelledbyثمaria-labelثم التسمية الأصلية ثم المحتوى ثم البدائل الاحتياطية. - قارن السجل بتوقعاتك صفاً صفاً. ولكل صف اكتب: النتيجة (ناجح أو فشل)، وحالة الاختبار SR المعنية، ومعيار نجاح WCAG 2.2 إن انطبق أحدها، والسبب في الشيفرة، والإعلان الذي كنت تتوقعه.
- اكتب عنوان تقرير خطأ بأسلوب الدليل لكل إخفاق، ونصَّ تقرير كاملاً لأيقونة البحث: الثنائية مع الإصدارات، والخطوات، وما سُمع، وما كان متوقعاً.
- قرّر نتيجة SR-12 للمهمة ضمن النطاق، وسمِّ الملاحظات التي تُفشل المهمة أو تجعلها تنتهي بنتيجة خاطئة.
- اكتب ما يجب إضافته أو التحقق منه قبل تسجيل العيوب، وما الذي تختبره بعد ذلك.
إظهار الإجابة النموذجية
التوقعات من الشيفرة. رابط الشعار: يأتي اسمه من سمة alt في الصورة، فيُعلَن «Dawa home, link». أيقونة البحث: عنصر button لا يحوي إلا svg، بلا aria-labelledby ولا aria-label ولا نص ولا title، فلا اسم له ويُعلَن «button» فقط. زر «Filters»: يُعلَن «Filters, button, collapsed» ويبقى كذلك، لأن toggleFilters() لا تغيّر aria-expanded أبداً. صورة المنتج: قيمة alt هي اسم الملف، فتُعلَن «IMG_4021.jpg, graphic». اسم المنتج: نص عادي وليس عنواناً. رابط «Details»: يُعلَن «Details, link»، وهو متطابق في البطاقات الاثنتي عشرة كلها. زر «Add to cart»: تأتي aria-label قبل المحتوى في ترتيب الاسم، فيكون الاسم «Buy now» لا النص الظاهر «Add to cart». عدد النتائج والإشعار: لا توجد منطقة حية في الصفحة قبل تغيّر النص، فلا يُعلَن شيء. ويطابق سجل عمر كل توقع. ولهذا ينصح الدليل بالنظر إلى الاسم والدور والحالات المحسوبة في لوحة إمكانية الوصول قبل الاستماع: فالشيفرة تفسّر ما تسمعه.
في الصف 1 إخفاقان. يفشل SR-01، والمعيار 2.4.2 Page Titled: ما زال عرض النتائج، الذي فُتح من الصفحة الرئيسية، يحمل عنوان هيكل التطبيق «Dawa»، وهو يسمّي الموقع لا العرض؛ والمتوقع عنوان يسمّي العرض، مثل «Results for vitamin D - Dawa»، يُضبط مع كل تغيير في المسار. ويفشل SR-02، والمعيار 3.1.1 Language of Page: تعلن الواجهة الإنجليزية lang="ar"، فيقرأ NVDA النص الإنجليزي بصوت عربي؛ والمتوقع lang="en" في الواجهة الإنجليزية وlang="ar" في الواجهة العربية، مع تحديثها عندما يبدّل المستخدم اللغة. وكلاهما مصدره هيكل التطبيق، فالأرجح أنهما يؤثران في كل العروض ويُصلَحان في موضع واحد.
الصفوف من 2 إلى 4. الصف 2: يفشل SR-03، والمعيار 1.3.1 Info and Relationships: أسماء المنتجات تبدو عناوين لكنها عناصر div، فلا تحوي قائمة العناوين إلا h1؛ والمتوقع h1 تليه أسماء المنتجات الاثنا عشر عناوينَ من المستوى 2. الصف 3: ينجح SR-04، فليس في الصفحة إلا ترويسة ومحتوى رئيسي، وكلاهما معلم، ولا يتكرر أي نوع من المعالم، فلا يحتاج أي منها إلى تسمية. الصف 4: الرابط «Dawa home» ناجح في SR-05. أما «Details» اثنتي عشرة مرة فمسألة تقدير. فكل رابط يقع في عنصر القائمة نفسه مع اسم منتجه، وهذا سياق قابل للتحديد برمجياً، فيتحقق المعيار 2.4.4 Link Purpose (In Context)، وهو من المستوى A؛ أما الروابط الواضحة من نصها وحده فلا يشترطها إلا المعيار 2.4.9 Link Purpose (Link Only) من المستوى AAA. وما لم يشمل هدفك المستوى AAA، فسجّلها تحسيناً لا إخفاقاً في WCAG، لأن قائمة الروابط تبقى عديمة الفائدة في اختيار منتج، واقترح اسماً يبدأ بالنص الظاهر، مثل «Details: Vitamin D3 1000 IU, 60 tablets». أما اثنا عشر رابط «Read more» بلا سياق كهذا، كما في مثال الدليل، فتخفق في 2.4.4.
الصف 5: تُقرأ القائمة بعناصرها الاثني عشر واسم المنتج والسعر بالترتيب، والنتيجة ناجح. وتفشل الصورة في SR-07، والمعيار 1.1.1 Non-text Content: فاسم الملف ليس بديلاً نصياً. والمتوقع alt يؤدي غرض الصورة، مثل «Vitamin D3 1000 IU, 60 tablets, pack»، أو alt="" إن قرر الفريق أن الصورة لا تفعل سوى تكرار اسم المنتج المجاور لها. وكلاهما مقبول، أما اسم الملف فلا. وهو عيب واحد في قالب البطاقة، لا اثنا عشر عيباً. والإعلانان الآخران في الصف 5، «Details, link» و«Buy now, button»، مغطّيان في الصف 4 وفي فقرة زر «Add to cart» أدناه.
الصف 6. تفشل أيقونة البحث في SR-06، والمعيار 4.1.2 Name, Role, Value: والمتوقع «Search, button»، مثلاً عبر aria-label="Search" أو نص مخفي بصرياً؛ والترويسة موجودة في كل صفحة، فكل الصفحات متأثرة. ويفشل زر «Filters» في SR-08 وفي المعيار نفسه: تُفتح اللوحة لكن الحالة تبقى «collapsed»؛ والمتوقع «Filters, button, expanded» بعد الفتح و«collapsed» بعد الإغلاق. وتكشف الشيفرة خطراً ثانياً: عنصر div يحمل role="button" ومعه onclick فقط لا يعالج المفاتيح، لأن أدوار ARIA لا تضيف سلوكاً. وفي وضع التصفح يستطيع NVDA تفعيل العنصر بإرسال نقرة إليه، فقد يعمل الزر مع قارئ الشاشة ويبقى معطلاً لمستخدمي لوحة المفاتيح. أعد المحاولة وقارئ الشاشة متوقف؛ فإن لم يفعل Enter ولا Space شيئاً، فسجّل عيباً منفصلاً تحت المعيار 2.1.1 Keyboard، كما يشرح دليل اختبار إمكانية الوصول بلوحة المفاتيح. وإصلاح واحد يغطي الأمرين: عنصر button أصلي يحدّث السكربت سمته aria-expanded، وهذه هي القاعدة الأولى لاستخدام ARIA.
يفشل زر «Add to cart» (الصفان 5 و8) في SR-06، والمعيار 2.5.3 Label in Name: التسمية الظاهرة «Add to cart» لكن الاسم «Buy now»، لأن aria-label تتقدم على نص الزر. فمستخدم التحكم الصوتي الذي يقول «Click Add to cart» لا يجد تطابقاً، ومستخدم قارئ الشاشة يسمع إجراءً يبدو شراءً فورياً. والمتوقع اسم يبدأ بالتسمية الظاهرة: «Add to cart, button» حداً أدنى، أو «Add to cart: Vitamin D3 1000 IU, 60 tablets, button» الذي يميّز أيضاً بين الأزرار الاثني عشر.
يفشل الصفان 7 و8 في SR-09، والمعيار 4.1.3 Status Messages، لسببين مختلفين. مربع الاختيار نفسه ناجح («1000 IU, checkbox, checked»)، لكن العدد فقرة عادية بلا دور status، فلا يُعلَن تغيّره أبداً؛ والمتوقع أن يُعلَن «4 products» إعلاناً مهذّباً (polite) بينما يبقى التركيز على مربع الاختيار، مثلاً بإعطاء العدد role="status" منذ تحميل الصفحة. أما الإشعار فيحمل role="status"، لكن السكربت يضيف المنطقة ونصها في اللحظة نفسها، فلا يُعلَن بشكل موثوق؛ والمتوقع أن يُعلَن «Added to cart» إعلاناً مهذّباً بينما يبقى التركيز على الزر، وذلك بإبقاء منطقة حالة فارغة في الصفحة منذ التحميل وكتابة الرسالة فيها.
الصف 9: سجّل نتيجة SR-12: فشل. يمكن إضافة المنتج، لكن لا شيء يؤكد الإضافة، فأضافه عمر مرتين ولم يكتشف الكمية الخاطئة إلا في صفحة السلة؛ والمستخدم الذي يثق بالصفحة يطلب عبوتين. والملاحظات وراء ذلك: الإشعار الصامت، واسم «Buy now» الذي يجعل أثر الزر غامضاً، وقبل ذلك في المهمة: عدد النتائج الصامت وحالة «Filters» الخاطئة. وأيقونة البحث التي بلا اسم ليست على مسار هذه المهمة، لكنها تمنع مستخدم قارئ الشاشة من بدء بحث جديد من هذه الصفحة.
عناوين تقارير الأخطاء: (1) «زر أيقونة البحث في الترويسة يُعلَن كـ button دون اسم» — 4.1.2. (2) «أزرار Add to cart تُعلَن باسم Buy now» — 2.5.3. (3) «رسالة Added to cart لا تُعلَن، فيضيف المستخدمون المنتج مرتين» — 4.1.3. (4) «عدد النتائج لا يُعلَن بعد تطبيق مرشح» — 4.1.3. (5) «زر Filters يُعلَن مطوياً (collapsed) بعد فتح اللوحة» — 4.1.2. (6) «أسماء المنتجات عناصر div منسقة؛ وقائمة العناوين لا تحوي إلا h1» — 1.3.1. (7) «صور المنتجات تُعلَن باسم الملف، مثل IMG_4021.jpg» — 1.1.1. (8) «الواجهة الإنجليزية تعلن lang="ar"، فيقرأ NVDA النص الإنجليزي بصوت عربي» — 3.1.1. (9) «عنوان الصفحة يبقى Dawa في عرض نتائج البحث» — 2.4.2. وتحسين: «روابط Details في بطاقات المنتجات لا يمكن التمييز بينها في قائمة الروابط». وبعد فحص لوحة المفاتيح، إن تأكد: «زر Filters لا يستجيب لـ Enter ولا لـ Space» — 2.1.1.
نص التقرير للعيب (1). البيئة: NVDA (الإصدار) مع Firefox (الإصدار) على Windows 11 (الإصدار)، بيئة Staging، البناء 3.8.0. الخطوات: افتح صفحة نتائج vitamin D، واضغط Tab حتى يصل التركيز إلى أيقونة البحث في الترويسة. المسموع: «button». المتوقع: «Search, button» (SR-06، والمعيار 4.1.2 Name, Role, Value). الدليل: لوحة إمكانية الوصول تُظهر الدور button واسماً فارغاً. النطاق: الترويسة موجودة في كل صفحة.
قبل التسجيل: أضف إصدارات NVDA وFirefox وWindows التي أغفلها السجل، لأن السلوك يتغير بين الإصدارات؛ وتحقق من كل اسم محسوب في لوحة إمكانية الوصول؛ وافحص العنوان واللغة في عرض آخر، كالصفحة الرئيسية، لتأكيد نطاق العيبين (8) و(9)؛ وأجرِ فحص زر «Filters» بلوحة المفاتيح وحدها. وبعد ذلك: كرر الروتين على الثنائيات الأخرى في خط الأساس للدعم، مثل VoiceOver مع Safari على iOS وTalkBack مع Chrome على Android لموقع الويب على الجوال، وعلى الواجهة العربية، حيث تكون lang="ar" صحيحة، فتتحقق من أن النص العربي يُقرأ بالصوت العربي، وأن الأسعار والسلاسل المختلطة بين العربية والإنجليزية تُقرأ بترتيب منطقي. وبعد الإصلاحات: اختبار التأكيد (Confirmation testing) لكل عيب على الثنائية نفسها، واختبار الانحدار للصفحات الأخرى التي تستخدم الترويسة وبطاقة المنتج.
إن اختلفت إجاباتك فافحص كل ملاحظة في أربعة أجزاء: ما سُمع، وما كان متوقعاً، والسبب في الشيفرة، والمعيار. ومن الاختلافات المقبولة: alt="" بدلاً من alt وصفي لصورة المنتج، أو نتيجة «ناجح مع ملاحظات» لـ SR-12 إن كان فريقك يستخدمها، ما دامت الإضافة المزدوجة مسجلة في التقرير. أما الإجابتان غير الصحيحتين هنا فهما: تسجيل «Details» إخفاقاً في 2.4.4، لأن عنصر القائمة يوفّر السياق، وعدم تسجيل شيء عنه، لأن مستخدمي قائمة الروابط ما زالوا عاجزين عن التمييز بين الروابط.
تقدّمك في هذا الموضوع
سجّل الدخول لتتابع تقدّمك
علّم الموضوعات مكتملة، وتابع من حيث توقفت، وافتح امتحانات التخصص.
جزء من مسار تعلم ضمان الجودة
قبل هذا الموضوع
الموضوعات التالية
الأدوات المذكورة في هذا الدليل
ولّد قائمة تحقق QA مخصّصة (وظيفية وواجهة مستخدم وAPI وأمان وأداء وإمكانية وصول وإصدار) لأي ميزة باستخدام الذكاء الاصطناعي من متقن.
ولّد عناوين أخطاء واضحة وقابلة للبحث من وصف غير مرتّب باستخدام الذكاء الاصطناعي من متقن.
حوّل الملاحظات الأولية إلى تقرير خطأ كامل: خطوات إعادة الإنتاج، والمتوقّع مقابل الفعلي، والبيئة، ودرجة الخطورة، وقائمة تحقق للمرفقات.