الوحدة 4 · التصميم البصري والمحتوى
الأسماء والأوصاف المتاحة (Accessible Names)
18 دقراءة 4 دبيئة تجريب الكود
الدرس في لمحة
توقّع الاسم المتاح والوصف اللذين يحسبهما المتصفّح لأي عنصر تحكّم، وأعطِ أزرار الأيقونات والأزرار المكرّرة أسماء فريدة تطابق تسميتها المرئية.
لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.
في صفحة الفعالية في Ticketly ثلاثة أزرار كلها تقول “Book now”، وزر إغلاق يُظهر “×”، وزر بحث لا يحتوي إلا أيقونة SVG لعدسة مكبّرة، وزر للنشرة البريدية ضبط أحد المطوّرين اسمه إلى “newsletter-cta” لأغراض التحليلات. في قائمة الأزرار لدى قارئ الشاشة، تُقرأ الصفحة هكذا: “Book now, Book now, Book now, times, button, newsletter-cta”. كل واحدة من هذه مشكلة تسمية، وتُصلحها كلها بفهم خوارزمية واحدة.
كيف يحسب المتصفّح الاسم
تحدّد مواصفة Accessible Name and Description Computation الصادرة عن W3C بدقة كيف يختار المتصفّح الاسم المتاح (accessible name). وبتبسيط، يجرّب هذه المصادر بالترتيب ويأخذ أول مصدر يُنتج نصًا:
aria-labelledby: نص العناصر المُشار إليها، مضمومًا بمسافات، بترتيب الـ ids.aria-label: النص المكتوب في الخاصية.- التسمية الأصلية: عنصر
<label>لحقول النماذج، وaltللصور، و<legend>للـ fieldset، و<caption>للجدول، و<title>للـ SVG. - المحتوى، للأدوار التي تسمح بذلك: الأزرار، والروابط، والعناوين، والتبويبات، وخلايا الجداول، وعناصر القوائم، والخيارات. النص الداخلي، مضافًا إليه
altالصور الداخلية، ومستبعدًا منه كل ما عليهaria-hidden="true". title(وplaceholderلحقول الإدخال) كملاذ أخير.
نتيجتان تهمّان كل يوم. أولًا، تسمية ARIA تتجاوز النص المرئي: ما إن تضيف aria-label حتى يُتجاهَل محتوى الزر نفسه. ثانيًا، الأسماء لا تندمج: إن وُجدت aria-labelledby، تُتخطّى aria-label الخاصة بالعنصر. مع استثناء واحد: إن ضمّت aria-labelledby معرّف العنصر نفسه، فإن هذه الإشارة الذاتية تُحسب بقيمة aria-label إن وُجدت، لا بمحتوى العنصر. ويمكنك التحقّق من أي نتيجة في المتصفّح: لوحة Accessibility في Chrome وAccessibility Inspector في Firefox كلتاهما تعرضان الاسم المحسوب.
أزرار الأيقونات فقط
الزر الذي لا يحتوي إلا أيقونة ليس له محتوى نصي، فليس له اسم، إلا إن أعطيته واحدًا. ثلاثة خيارات، بترتيب الأفضلية:
<!-- 1. Visible text next to the icon: best for everyone -->
<button type="button" class="search">
<svg aria-hidden="true" viewBox="0 0 24 24">…</svg>
Search
</button>
<!-- 2. Visually hidden text: the design stays icon-only -->
<button type="button" class="close">
<span aria-hidden="true">×</span>
<span class="visually-hidden">Close banner</span>
</button>
<!-- 3. aria-label: fine, but invisible to translation tools that skip attributes -->
<button type="button" class="close" aria-label="Close banner">
<span aria-hidden="true">×</span>
</button>لاحظ aria-hidden="true" على الرمز “×”. من دونها، سيكون اسم الخيار 2 هو “× Close banner”، وتقرؤه بعض قارئات الشاشة “times Close banner”.
الأزرار المكرّرة ومعيار Label in Name
ثلاثة أزرار “Book now” مقبولة بصريًا، لأن كل واحد منها يقع في بطاقته. لكنها في قائمة الأزرار لا يمكن التمييز بينها. تريد أسماء مثل “Book now, Friday pass” دون تغيير التصميم المرئي. يمكن لـ aria-labelledby أن تشير إلى الزر نفسه إضافةً إلى عنوان البطاقة:
<article>
<h3 id="fri-title">Friday pass</h3>
<button type="button" id="fri-book" aria-labelledby="fri-book fri-title">Book now</button>
</article>يصبح الاسم “Book now Friday pass”. تأتي الكلمات المرئية أولًا، وهذا مهم لمعيار 2.5.3 Label in Name (A): يجب أن يحتوي الاسم المتاح التسمية المرئية، وأفضل ممارسة أن يبدأ بها. تقول دينا، التي تستخدم التحكّم الصوتي، “click Book now”؛ فيجد برنامجها التطابقات الثلاثة ويرقّمها لتختار منها. لو كان الاسم “Reserve Friday” لما كان أمامها أي طريقة لنقره بنطق ما تراه. وهذا بالضبط ما كان خاطئًا في زر “newsletter-cta”: الكلمة المرئية “Subscribe” ليست في الاسم إطلاقًا. احذف الـ aria-label فيعود المحتوى ليمنح الاسم الصحيح.
الأوصاف
الوصف (description) معلومات ثانوية تُعلَن بعد الاسم والدور، عادةً بعد توقّف قصير. تعمل aria-describedby مثل aria-labelledby لكنها تغذّي الوصف بدلًا من الاسم:
<label for="promo">Promo code</label>
<input id="promo" aria-describedby="promo-hint">
<p id="promo-hint">Codes are 8 letters, for example HARBOUR8.</p>يقرأ NVDA: “Promo code, edit text, Codes are 8 letters, for example HARBOUR8.” استخدم الأوصاف للتلميحات والصيغ ورسائل الخطأ، كما فعلت في درس النماذج. اجعل الاسم قصيرًا والوصف اختياريًا: يستطيع المستخدمون تخطّي الوصف، لكنهم لا يستطيعون تخطّي الاسم.
صار لكل عنصر تحكّم في Ticketly اسم يستطيع الإنسان نطقه. وينظر الدرس الأخير في هذا القسم في الكلمات نفسها: اللغة البسيطة، وخصائص اللغة التي تجعل محتوى Ticketly العربي يُنطق بشكل صحيح.
أهم النقاط
- يحسب المتصفّح اسم عنصر التحكّم بترتيب ثابت: aria-labelledby، ثم aria-label، ثم التسمية الأصلية (label وalt وlegend وcaption)، ثم محتوى العنصر، ثم title.
- aria-labelledby وaria-label تتجاوزان كل ما سواهما، بما في ذلك النص المرئي، فاستخدمهما بحذر.
- يجب أن تظهر التسمية المرئية داخل الاسم المتاح (2.5.3 Label in Name)، ويُفضَّل أن تكون في بدايته، ليستطيع مستخدمو التحكّم الصوتي نطق ما يرونه.
- aria-describedby تضيف معلومات ثانوية تُقرأ بعد الاسم والدور؛ وهي للتلميحات والأخطاء، لا للاسم نفسه.