Content Description هي خاصية إمكانية وصول تنقل وصفاً نصياً للمحتوى غير النصي إلى التقنيات المساعدة. في iOS هي السمة accessibilityHint لـ UIView، وفي Android — contentDescription في ترميز XML. وفقاً لمعيار W3C WCAG 2.2، 2023، فإن غياب البدائل النصية للمحتوى غير النصي يُعد أحد أكثر انتهاكات إمكانية الوصول شيوعاً في تطبيقات المحمول. الأوصاف المعبأة بشكل صحيح تجعل التطبيق متاحاً للأشخاص ذوي الإعاقات البصرية الذين يستخدمون VoiceOver و TalkBack.
الخلاصة
Content Description هي خاصية نصية لعنصر واجهة المستخدم توفر تمثيلاً نصياً للمحتوى المرئي للتقنيات المساعدة. يقرأ قارئ الشاشة (VoiceOver في iOS، TalkBack في Android) الوصف بصوت عالٍ بدلاً من محاولة التعرف على العنصر بصرياً. تُطبق الأوصاف على الصور بدون طبقة نصية والأيقونات والرسوم البيانية وعناصر التحكم المخصصة وأي عناصر غير نصية.
وفقاً لـ Google Material Design، 2024، العناصر بدون contentDescription تنتهك WCAG 1.1.1 (Non-text Content). تظهر فحوصات Accessibility Scanner أن ما يصل إلى 40% من الأيقونات في تطبيقات التسوق تفتقر إلى الأوصاف. مستخدم VoiceOver يسمع «صورة» أو «زر» دون تفاصيل — تصبح هذه الواجهة غير قابلة للاستخدام للملاحة.
Content Description لا تحل محلالنص المرئي للعنصر. إذا كان الزر يحتوي على تسمية نصية «إرسال»، فلا حاجة لتعيين وصف إضافي — سيقرأ قارئ الشاشة النص. للصور والأيقونات وحقول الإدخال، الوصف إلزامي.
أداتا Accessibility Scanner (Android) و Xcode Accessibility Inspector (iOS) تتحققان تلقائياً من وجود الأوصاف. يُنصح بتشغيل هذه الفحوصات على كل شاشة قبل الإصدار.
المستخدم ضعيف البصر يعتمد على VoiceOver لفهم الواجهة. إذا كانت أيقونة سلة التسوق لا تحتوي على وصف، سيسمع فقط «زر». لمعرفة ما يفعله الزر، عليه الضغط عليه بشكل أعمى — مخاطراً باتخاذ إجراء لا رجعة فيه. وصف مثل «إزالة العنصر من السلة» يحل هذه المشكلة في ثانية واحدة.
المستخدم ذو القيود المؤقتة(شمس ساطعة بالخارج، شاشة مكسورة) يستخدم أيضاً VoiceOver. وفقاً لتقرير Apple Accessibility، 2023، حوالي 20% من مستخدمي VoiceOver ليس لديهم إعاقات بصرية دائمة — بل يشغلون الميزة في مواقف معينة.
معيار WCAG 1.1.1 (المستوى A) يتطلب أن يكون لكل محتوى غير نصي بديل نصي. الاستثناء: المحتوى الزخرفي المستخدم فقط للعرض المرئي أو الذي لا ينقل معلومات. اختبار الزخرفية: إذا أزلت العنصر، هل يتغير معنى الصفحة؟ إذا لم يتغير — يمكن إخفاؤه عن قارئ الشاشة.
Accessibility Label(accessibilityLabel في iOS) هو اسم العنصر الذي ينطقه قارئ الشاشة عند التركيز عليه. Content Description (accessibilityHint في iOS) هو توضيح إضافي يُعلن بعد الاسم ويخبر بنتيجة الإجراء.
الفرق واضح في مثال زر «السلة». Label: «سلة». Description: «سيفتح شاشة الدفع». VoiceOver يقول: «سلة. سيفتح شاشة الدفع». إذا تم تعيين Label فقط، لن يعرف المستخدم ماذا سيحدث بعد الضغط.
| الخاصية | iOS | Android | الغرض |
|---|---|---|---|
| Label | accessibilityLabel | contentDescription | اسم العنصر (زر، حقل، صورة) |
| Description | accessibilityHint | contentDescription (موسعة) | توضيح الإجراء أو المعنى |
| Trait | accessibilityTraits | role / className | دور العنصر (زر، عنوان) |
القاعدة: Label يجيب عن «ما هذا؟»، Description يجيب عن «ماذا سيحدث؟». في Android، يمكن لـ contentDescription أداء كلا الدورين، لكن من الأفضل عملياً فصلهما: استخدام تسلسل «[الاسم]، [التوضيح]».
لـ الإيماءات المعقدة(التمرير للحذف، الضغط المطول للقائمة السياقية)، accessibilityHint إلزامي. مستخدم VoiceOver لا يعرف عن الإيماءات المخفية ما لم تكن موصوفة. حدد: «اسحب لليسار للحذف» في hint العنصر.
في منصة iOS، يتم تعيين accessibilityHint عبر الخاصية التي تحمل الاسم نفسه لـ UIView أو NSObject. القيمة هي سلسلة نصية تصل إلى 80 حرفاً. يقرأ VoiceOver الـ hint بعد الـ label عند تفعيل وضع الأوصاف التفصيلية (في إعدادات VoiceOver — «Verbosity»).
مثال لتعيين hint لزر مخصص:
import UIKit
class CustomButton: UIButton {
override func awakeFromNib() {
super.awakeFromNib()
self.accessibilityLabel = "إضافة إلى المفضلة"
self.accessibilityHint = "سيحفظ العنصر في قائمة المفضلة"
}
}
لـ UIImageView بدون محتوى نصي، يجب تعيين isAccessibilityElement = true و accessibilityHint:
let imageView = UIImageView(image: UIImage(named: "chart-sales"))
imageView.isAccessibilityElement = true
imageView.accessibilityHint = "الرسم البياني للمبيعات للربع الأخير"
VoiceOver يقرأ: «الرسم البياني للمبيعات للربع الأخير». إذا كان الـ hint فارغاً — فقط «صورة». Apple HIG، 2024 يوصي بعدم استخدام أفعال مثل «اضغط» أو «المس» في الـ hints — VoiceOver يضيف تعليمة الإيماءة تلقائياً.
في SwiftUI، يُعيّن الـ hint عبر معدِّل تسلسلي:
Image(systemName: "trash")
.accessibilityLabel("حذف")
.accessibilityHint("سيحذف العنصر المحدد بشكل دائم")
SwiftUI يجمع تلقائياًالمعدِّلات للعروض المركبة. إذا كانت Image داخل Button، يستخدم SwiftUI تسمية الزر كـ accessibilityLabel أساسي.
في Android، تُعيّن contentDescription إما في ترميز XML أو برمجياً عبر setContentDescription(). يعلن TalkBack الوصف عند تركيز العنصر.
مثال في XML:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_search"
android:contentDescription="البحث عن المنتجات" />
التعيين البرمجي للعناصر الديناميكية:
binding.iconSearch.contentDescription =
"بحث. سيفتح شاشة البحث مع الفلاتر"
لـ الصور الزخرفية(الفواصل، الخلفيات، الأيقونات الزخرفية) عيِّن contentDescription = "@null" أو setContentDescription(null) — سيتخطى TalkBack هذه العناصر. في XML: android:contentDescription="@null". السلسلة الفارغة "" لا تعمل — سيظل TalkBack يعلن «صورة».
لـ ImageButton، عيِّن دائماً contentDescription — TalkBack لا يرى النص على الصور. لـ CheckBox، يجب أن يتغير الوصف ديناميكياً: «محدد» / «غير محدد» بدلاً من وصف ثابت. استخدم setContentDescription في مستمع الحالة.
الإفادة — يجب أن ينقل الوصف المعنى، لا المظهر. ليس «أيقونة زرقاء بعلامة صح»، بل «تمت إضافة العنصر إلى السلة». قارئ الشاشة لا يهتم بالألوان — بل يهتم بالنتيجة.
الإيجاز — الطول الأمثل 2–4 كلمات (حتى 80 حرفاً). الأوصاف الطويلة تبطئ الملاحة: VoiceOver يقرأ بتسلسل، كل كلمة هي ثانية من وقت المستخدم. وفقاً لـ Apple WWDC 2023، «Accessibility by Design»، العبارة التي تستغرق أكثر من 5 ثوانٍ للقراءة تقطع التدفق المعرفي.
التفرد — لا يجب أن يكون هناك عنصران على نفس الشاشة بنفس الوصف. لن يتمكن المستخدم من تمييز أي نتيجة سيسببها التركيز على العنصر الأول مقابل الثاني. إذا كان هناك عدة أزرار «اشترِ»، أضف معرفاً: «اشترِ iPhone 15»، «اشترِ iPhone 15 Pro».
التعريب — يجب ترجمة Content Description إلى جميع اللغات التي يدعمها التطبيق. خطأ تعريب الأوصاف هو أحد الأسباب الشائعة لفشل Accessibility Review في App Store.
أظهر بحث Nielsen Norman Group، 2024 أن الطول الأمثل للوصف لقارئات الشاشة هو 3–5 كلمات (حتى 50 حرفاً). الأوصاف الأطول تقلل سرعة الملاحة بنسبة 30%، حيث يضطر المستخدم لانتظار انتهاء الإعلان قبل الخطوة التالية.
التكرار — الوصف يكرر النص المرئي. إذا كان الزر يحتوي على نص «إرسال»، لا تعيّن accessibilityHint = «زر إرسال». سيقرأ VoiceOver النص تلقائياً، وسيضيف الـ hint ضوضاء غير ضرورية.
الخلط مع Label — استخدام contentDescription بدلاً من label للأزرار النصية. في iOS، يجب أن يتطابق accessibilityLabel مع نص الزر (أو يكون فارغاً إذا كان النص مرئياً بالفعل)، ويجب أن يوضح الـ hint الإجراء فقط. وفقاً لمدونة Google Testing، 2024، 23% من التطبيقات التي تمت مراجعتها في Play Store تحتوي على أوصاف مكررة.
تجاهل الديناميكية — لا يتم تحديث الوصف عند تغير الحالة. على سبيل المثال، وصف مفتاح «Wi-Fi» يظل «تشغيل Wi-Fi» حتى بعد تشغيله. النهج الصحيح: تغيير الوصف ديناميكياً إلى «إيقاف Wi-Fi» عبر مراقبة الحالة.
بعد تحديث التصميم (تغيير الأيقونات، إعادة ترتيب العناصر)، غالباً ما يُفقد Content Description. السبب: المصمم يستبدل الصورة ولا يتحقق المطور من خصائص إمكانية الوصول للأصل الجديد. الحل: جعل فحص إمكانية الوصول خطوة إلزامية في مراجعة الكود — أضف عنصر قائمة تحقق: «هل تم تحديث Content Description؟».
func testContentDescriptionExists() {
let app = XCUIApplication()
app.launch()
let image = app.images["chart-sales"]
XCTAssertNotNil(image.label)
XCTAssertGreaterThan(image.label.count, 0)
}
الأسئلة المتكررة
سيعلن VoiceOver أو TalkBack ببساطة «صورة» أو «زر» دون تحديد الغرض. هذا ينتهك WCAG 1.1.1 ويجعل التطبيق غير متاح للأشخاص ذوي الإعاقات البصرية.
لا. إذا كان الزر يحتوي على تسمية نصية، يقرأها VoiceOver تلقائياً. يمكن إضافة وصف (accessibilityHint) لتوضيح نتيجة الضغط، لكن Label غير مطلوب.
في iOS عيِّن isAccessibilityElement = false. في Android عيِّن contentDescription = "@null". سيتخطى قارئ الشاشة هذه العناصر تماماً دون إصدار صوت.
في iOS استخدم NSLocalizedString لـ accessibilityHint، في Android — موارد نصية عبر @string/. ترجمة الأوصاف إلزامية لجميع اللغات المدعومة.
أضف اختبارات واجهة مستخدم تتحقق من وجود أوصاف لكل ImageView. في iOS — XCUIApplication، في Android — AccessibilityCheckRule من Espresso. يمكن تشغيل Accessibility Scanner في CI عبر سطر الأوامر.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا