اسمحوا لي أن أبدأ بقصة حدثت معي قبل بضع سنوات، قصة غيّرت نظرتي لتطوير الواجهات الأمامية إلى الأبد. كنت وقتها قد انتهيت من تطوير لوحة تحكم جديدة لعميل، يا الله شو كنت فخور فيها! رسوم بيانية تفاعلية، انتقالات ناعمة، تصميم عصري… كل شيء كان يبدو مثالياً. أطلقنا المشروع، وبدأت التهاني تصل من الفريق والعميل.
بعد أسبوع، وصلني بريد إلكتروني من قسم الدعم الفني، يحمل عنوان “مشكلة في استخدام لوحة التحكم”. فتحت الرسالة بضجر، متوقعاً شكوى بسيطة. لكن محتوى الرسالة صعقني. كانت من مستخدم اسمه “أحمد”، وهو كفيف ويستخدم قارئ الشاشة لتصفح الويب. كتب أحمد بلغة مهذبة ولكن حاسمة: “لوحة التحكم الجديدة جميلة بصرياً كما وصفها زملائي، لكنها بالنسبة لي صفحة فارغة. لا أسمع شيئاً، لا أفهم شيئاً. الأزرار لا تتحدث، والرسوم البيانية صامتة. أشعر وكأنني أقف أمام جدار أملس في غرفة مظلمة”.
كلماته كانت كالصفعة. “جدار أملس في غرفة مظلمة”… يا له من وصف! أنا، أبو عمر، الذي أفتخر بخبرتي، بنيت جداراً رقمياً عزل أحمد وغيره. في ذلك اليوم، أغلقت كل شيء، قمت بتثبيت قارئ شاشة على جهازي، وأغمضت عينيّ… لأول مرة، “سمعتُ” تطبيقي. وكان ما سمعته… صمتاً مطبقاً. هنا بدأت رحلتي الحقيقية مع “إمكانية الوصول” (Accessibility)، وهنا أدركت أن عملنا كمطورين يتجاوز بكثير الألوان المتباينة.
ما هو الجحيم الصامت؟ ولماذا نقع فيه؟
المشكلة التي واجهتها مع أحمد ليست نادرة. في عالم تطوير الويب الحديث، ومع انتشار أطر العمل مثل React و Vue و Angular، أصبحنا نبني مكونات معقدة وتفاعلية باستخدام عناصر HTML بسيطة مثل <div> و <span>. هذه العناصر، رغم مرونتها في التصميم، إلا أنها “صماء” من الناحية الدلالية (Semantically Mute).
المتصفح يراها كصناديق لا معنى لها. وبالتالي، قارئ الشاشة لا يجد ما يخبره للمستخدم. تخيل أنك بنيت نظام تبويبات (Tabs) باستخدام <div>. بصرياً، هو رائع. لكن لقارئ الشاشة، هو مجرد مجموعة من النصوص غير المترابطة. لا يفهم أن هذا “زر تبويب” وهذا “محتوى مرتبط به”. هذه هي الواجهة الصامتة: جميلة للعين، لكنها بلا روح وبلا معنى للآلات المساعدة.
المنقذ: سمات ARIA (Accessible Rich Internet Applications)
هنا يأتي دور ARIA لتكون بمثابة المترجم بين واجهتنا التفاعلية الغنية وقارئ الشاشة. ARIA هي مجموعة من السمات (Attributes) التي يمكنك إضافتها إلى عناصر HTML لتزويدها بالمعنى والسياق الذي تفتقر إليه.
باختصار، ARIA لا تغير شكل العنصر أو وظيفته في المتصفح، بل تصف وظيفته وسياقه للتقنيات المساعدة. هي أشبه بوضع لافتات برايل في مبنى زجاجي حديث.
تنقسم ARIA إلى ثلاثة أجزاء رئيسية:
1. الأدوار (Roles): من أنت؟
الـ role يخبر قارئ الشاشة عن طبيعة العنصر. هل هذا <div> هو زر؟ أم قائمة؟ أم مربع حوار؟
<!-- سيء: مجرد صندوق نصي -->
<div class="custom-button">اضغط هنا</div>
<!-- جيد: الآن قارئ الشاشة يعرف أنه زر -->
<div class="custom-button" role="button" tabindex="0">اضغط هنا</div>
لاحظ إضافة tabindex="0" لجعل الـ div قابلاً للوصول عبر لوحة المفاتيح، وهو أمر أساسي للأزرار المخصصة.
2. الخصائص (Properties): ماذا تملك؟
الخصائص تصف علاقات العنصر أو ميزاته التي لا تتغير عادةً. أشهرها وأهمها:
aria-label: لإعطاء اسم للعنصر لا يظهر على الشاشة. مثالي للأزرار التي تحتوي على أيقونة فقط.aria-labelledby: لربط العنصر بتسمية موجودة بالفعل على الشاشة.aria-describedby: لربط العنصر بوصف إضافي.
<!-- زر إغلاق عبارة عن أيقونة فقط -->
<button aria-label="إغلاق النافذة">
<svg>...أيقونة X...</svg>
</button>
بدون aria-label، سيقرأ قارئ الشاشة “زر، فارغ”. معها، سيقرأ “زر، إغلاق النافذة”. فرق شاسع!
3. الحالات (States): كيف حالك الآن؟
الحالات تصف الوضع الحالي للعنصر، وهي ديناميكية وتتغير عادةً باستخدام JavaScript.
aria-expanded: هل القائمة المنسدلة مفتوحة (true) أم مغلقة (false)؟aria-selected: هل هذا التبويب هو المحدد حالياً (true) أم لا (false)؟aria-disabled: هل الزر معطل (true) أم لا (false)؟aria-busy: هل هذا الجزء من الصفحة يقوم بتحميل محتوى (true)؟
ورشة عمل سريعة: إنقاذ مكون “التبويبات” الصامت
لنرَ مثالاً عملياً. لدينا مكون التبويبات (Tabs) الشهير. هذا هو الكود “الصامت” الذي يكتبه الكثيرون:
المشكلة: تبويبات “خَرْساء”
<!-- HTML -->
<div class="tabs">
<div class="tab active">الرئيسية</div>
<div class="tab">الملف الشخصي</div>
<div class="tab">الإعدادات</div>
</div>
<div class="panels">
<div class="panel active">محتوى الرئيسية...</div>
<div class="panel">محتوى الملف الشخصي...</div>
<div class="panel">محتوى الإعدادات...</div>
</div>
هذا الكود كارثي لقارئ الشاشة. لا يفهم العلاقة بين “الرئيسية” و “محتوى الرئيسية”. المستخدم سيسمع قائمة من الكلمات ثم كتلة من النصوص، دون أي سياق.
الحل: إضافة الحياة مع ARIA
الآن، لنقم بترميم هذا المكون ونعطيه صوتاً. سنستخدم عناصر HTML الدلالية أولاً، ثم نعززها بـ ARIA.
<!-- HTML معزز بـ ARIA -->
<div role="tablist" aria-label="لوحة التحكم الرئيسية">
<button role="tab" aria-selected="true" aria-controls="panel-1" id="tab-1">
الرئيسية
</button>
<button role="tab" aria-selected="false" aria-controls="panel-2" id="tab-2" tabindex="-1">
الملف الشخصي
</button>
<button role="tab" aria-selected="false" aria-controls="panel-3" id="tab-3" tabindex="-1">
الإعدادات
</button>
</div>
<div>
<div role="tabpanel" aria-labelledby="tab-1" id="panel-1">
<p>محتوى الرئيسية...</p>
</div>
<div role="tabpanel" aria-labelledby="tab-2" id="panel-2" class="hidden">
<p>محتوى الملف الشخصي...</p>
</div>
<div role="tabpanel" aria-labelledby="tab-3" id="panel-3" class="hidden">
<p>محتوى الإعدادات...</p>
</div>
</div>
ماذا فعلنا هنا؟
role="tablist": أخبرنا قارئ الشاشة أن هذا الـdivهو حاوية لمجموعة من التبويبات.role="tab": حولنا أزرار التبويبات إلى<button>(أفضل منdiv!) وأعطيناها دور “تبويب”.role="tabpanel": حددنا كل جزء من المحتوى على أنه “لوحة تبويب”.aria-selected: هذه هي الحالة الديناميكية! قيمتهاtrueللتبويب النشط وfalseللبقية. يجب أن يغيرها كود JavaScript عند النقر.aria-controlsوid: هذا هو السحر!aria-controlsعلى الزر يخبر قارئ الشاشة: “أنا أتحكم في اللوحة التي تحمل الـ ID الفلاني”. هذا يخلق الرابط الدلالي المفقود.aria-labelledby: على لوحة المحتوى، هذه السمة تربطها بالزر الذي يسميها.tabindex: لإدارة التنقل عبر لوحة المفاتيح بشكل احترافي. التبويب النشط فقط هو الذي يمكن الوصول إليه بـ Tab (tabindex="0"أو لا يوجد)، والبقية بـtabindex="-1".
الآن، عندما يصل المستخدم “أحمد” إلى هذه الواجهة، سيسمع شيئاً مثل: “قائمة تبويبات، الرئيسية، تبويب، محدد، 1 من 3”. وعندما يضغط Enter، يعرف أن المحتوى الذي سيُقرأ تالياً هو المتعلق بالرئيسية. لقد حولنا الجدار الصامت إلى حوار تفاعلي.
نصائح من قلب الميدان (من أخوكم أبو عمر)
بعد سنوات من الغوص في هذا العالم، اسمحوا لي أن أقدم لكم خلاصة خبرتي في نقاط عملية:
- القاعدة الذهبية الأولى: “لا ARIA أفضل من ARIA سيئة” (No ARIA is better than bad ARIA). إذا وضعت
roleأو حالة خاطئة، فأنت تضلل المستخدم وتجعل تجربته أسوأ من لو لم تضع شيئاً. تعلم قبل أن تطبق. - استخدموا العناصر الأصلية يا جماعة: قبل أن تفكر في
<div role="button">، اسأل نفسك: لماذا لا أستخدم<button>مباشرة؟ HTML5 غني بالعناصر الدلالية (<nav>,<main>,<details>). استخدمها أولاً، ثم الجأ لـ ARIA عند الضرورة للمكونات المعقدة. - اختبروا شغلكم بأيديكم (وأذانكم): لا تعتمد على التخمين. قم بتنزيل قارئ شاشة مجاني مثل NVDA، وأغلق الشاشة أو أغمض عينيك، وحاول استخدام موقعك. ستكتشف مشاكل لم تخطر لك على بال.
- إمكانية الوصول ليست “ميزة إضافية”: هي جزء لا يتجزأ من جودة المنتج، تماماً مثل الأمان والأداء. يجب أن تكون في ذهنك من مرحلة التصميم وليس في النهاية كإصلاح.
الخلاصة: لنجعل الويب مكاناً للجميع 🤝
في النهاية، تطوير الويب ليس مجرد كتابة كود، بل هو بناء جسور تواصل بين الناس والمعلومات. عندما نتجاهل إمكانية الوصول، نحن لا نكتب كوداً سيئاً فحسب، بل نبني جدراناً تعزل شريحة مهمة من مجتمعنا. سمات ARIA ليست مجرد أدوات تقنية، بل هي لغة التعاطف في عالم التطوير.
في المرة القادمة التي تبني فيها مكوناً جديداً، تذكر قصة “أحمد” والجدار الصامت. اسأل نفسك: هل واجهتي تتحدث؟ هل هي غنية بالحوار أم صامتة؟ الإجابة الصحيحة لا تجعل منك مطوراً أفضل فحسب، بل تجعل منك إنساناً أفضل. ولنجعل من الويب مكاناً مرحباً بالجميع، دون استثناء.