يبني هذا المشروع على النماذج (Forms)، والنماذج المتقدمة، وإمكانية الوصول. راجعها أولًا إن لم تكن قد أتممتها — هذا المشروع يفترض أنك تعرف أنواع input الأساسية وسمة label for.
المهمة: بناء نموذج تسجيل حساب حقيقي متعدد الحقول، بلا أي CSS أو JavaScript — HTML فقط، صحيح دلاليًا وقابل للوصول بالكامل.
المتطلبات
النموذج يجب أن يجمع:
- الاسم الكامل (نص).
- البريد الإلكتروني.
- كلمة مرور، مع حقل تأكيد كلمة المرور.
- رقم الهاتف بصيغة محلية محددة (استخدم
pattern). - تاريخ الميلاد.
- الدولة — عبر
<select>بخيارات متعددة. - نبذة قصيرة عن المستخدم — عبر
<textarea>. - صورة شخصية — عبر رفع ملف.
- مربّع اختيار للموافقة على الشروط (إلزامي).
- زر إرسال وزر إعادة تعيين.
نقطة البداية
هيكل مقترح لتبدأ منه — أكمله بنفسك، لا تنسخه كحلّ نهائي:
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>إنشاء حساب جديد</title>
</head>
<body>
<h1>إنشاء حساب جديد</h1>
<form action="/register" method="post" novalidate>
<fieldset>
<legend>البيانات الشخصية</legend>
<!-- الاسم، البريد، الهاتف، تاريخ الميلاد هنا -->
</fieldset>
<fieldset>
<legend>بيانات الدخول</legend>
<!-- كلمة المرور وتأكيدها هنا -->
</fieldset>
<!-- الدولة، النبذة، الصورة الشخصية، والموافقة على الشروط هنا -->
<button type="submit">إنشاء الحساب</button>
<button type="reset">تفريغ النموذج</button>
</form>
</body>
</html>
🔑 لاحظ
novalidateعلى<form>أعلاه: تركناها عمدًا كنقطة نقاش — بمشروعك النهائي احذفها لتفعيل التحقق المدمج للمتصفح، فهذا بالضبط ما يختبره هذا المشروع.
البنية المتوقعة
- كل حقل إدخال له
<label for="...">مرتبط بـidمطابق تمامًا — لا تعتمد علىplaceholderكبديل عنlabelأبدًا. - حقول "البيانات الشخصية" مجمّعة داخل
<fieldset>مع<legend>يصف المجموعة، وكذلك حقول "بيانات الدخول" فيfieldsetمنفصل. - أنواع
inputمناسبة لكل بيانة:emailللبريد،passwordلكلمتي المرور،telللهاتف معpattern،dateلتاريخ الميلاد،fileللصورة الشخصية (معaccept="image/*"). - كل حقل إلزامي يحمل
requiredفعليًا، لا مجرد نجمة*في النص. - كل حقل له سمة
autocompleteمناسبة:name،email،new-password(وليسcurrent-password— هذا تسجيل حساب جديد لا دخول)،tel،bday،country. - كل حقل له نص مساعد أو رسالة خطأ محتملة مرتبطة به عبر
aria-describedbyيشير إلىidعنصر النص المساعد. - الحقول الإلزامية غير الصحيحة (افتراضيًا أو بعد محاولة إرسال فاشلة) تحمل
aria-invalid="true". - زر الإرسال بنوع
submit، وزر التفريغ بنوعreset— لا تستخدم<div>أو<a>كأزرار.
متطلبات الوصول
- تسميات حقيقية دائمًا:
<label for="email">البريد الإلكتروني</label>مع<input id="email">— لا نص placeholder بديل عن label. - تجميع منطقي:
fieldset/legendلكل مجموعة حقول مترابطة (البيانات الشخصية، بيانات الدخول)، لا حقول متناثرة بلا سياق. - رسائل مساعدة مرتبطة برمجيًا: كل نص مساعد أو رسالة خطأ (مثل "8 أحرف على الأقل" تحت حقل كلمة المرور) موصول بـ
aria-describedby، لا مجرد فقرة عائمة بجانب الحقل بصريًا فقط. - ترتيب تركيز منطقي: ترتيب الحقول في HTML نفسه يطابق الترتيب البصري المتوقع بالتنقل بمفتاح Tab — بلا أي
tabindexيدوي لإعادة الترتيب. - علامات إلزامية واضحة: الحقول الإلزامية تحمل
requiredفعليًا، مع إشارة نصية مرئية أيضًا (مثل "*" مذكورة صراحة فيlabelأو بجانبه، لا لونًا فقط).
الأخطاء الشائعة في هذا المشروع
- ❌ استخدام
placeholderبدلlabel— يختفي النص فور الكتابة، وقارئ الشاشة قد لا يقرأه أصلًا. - ❌ نسيان
for/idمطابقين — يبدوlabelصحيحًا بصريًا لكنه غير مرتبط برمجيًا بالحقل. - ❌
autocomplete="current-password"في نموذج تسجيل جديد — هذه القيمة لتسجيل الدخول، لا لإنشاء حساب؛ استخدمnew-password. - ❌ الاعتماد على
required/patternكحماية أمنية — هي تحقق واجهة فقط لتحسين التجربة؛ أي بيانات تصل الخادم يجب التحقق منها هناك مجددًا مهما كان HTML صارمًا. - ❌ وضع بيانات حسّاسة كبيانات تسجيل بطريقة
method="get"— استخدمmethod="post"دائمًا لنماذج فيها كلمات مرور أو بيانات شخصية؛getيضع القيم ظاهرة في الرابط نفسه.
قائمة التحقق
- كل حقل
input/textarea/selectله<label for>مرتبط بـidمطابق. - حقلا كلمة المرور وتأكيدها من نوع
password. - حقل البريد من نوع
email، وحقل الهاتف من نوعtelمعpatternيفرض صيغة محددة. - حقل تاريخ الميلاد من نوع
date. - حقل الدولة
<select>بعدة<option>حقيقية، وخيار افتراضي غير صالح للاختيار (disabled selected). - حقل النبذة
<textarea>بعدد أسطر معقول (rows). - حقل الصورة الشخصية
<input type="file" accept="image/*">. - مربّع موافقة على الشروط
<input type="checkbox" required>معlabelواضح ورابط حقيقي لصفحة شروط (وهمي يكفي هنا). - حقول "البيانات الشخصية" و"بيانات الدخول" كل منها داخل
fieldset/legendمنفصل. - كل حقل إلزامي يحمل
requiredفعليًا، لا نجمة نصية فقط. - كل حقل له
autocompleteمناسب لطبيعته (وليسcurrent-passwordهنا). - كل حقل له نص مساعد مرتبط بـ
aria-describedby. - النموذج بأكمله يعمل بلوحة المفاتيح فقط (Tab بترتيب منطقي، Enter يرسل).
- تشغيل الصفحة على مدقّق W3C بلا أخطاء بنيوية.
معايير الإتمام
المشروع مكتمل حين:
- النموذج يحتوي كل الحقول العشرة المطلوبة، كل واحد بالنوع الصحيح.
- محاولة الإرسال بحقل إلزامي فارغ تُظهر رسالة تحقق المتصفح المدمجة (لأن
requiredمفعّلة فعليًا، بلاnovalidate). - اختبار الصفحة بلوحة المفاتيح فقط (بلا فأرة) يسمح بالوصول لكل حقل وإرسال النموذج بنجاح.
- تشغيل مدقّق W3C على الصفحة يعيد صفر أخطاء.
- لا يوجد أي
placeholderيعمل كبديل وحيد عنlabel.
إرشادات للحل المقترح
- ابدأ بكتابة الحقول العشرة بلا أي تجميع أو تحقق، تأكد أن كل واحد يعمل ويُرسل قيمته (افحص بأداة المطوّر أو خدمة اختبار نماذج بسيطة).
- بعدها أضف
required/pattern/minlengthحقلًا حقلًا، واختبر كل واحد بإدخال خاطئ متعمّد لترى رسالة التحقق تظهر فعليًا. - ثم أضف
fieldset/legendحول المجموعتين المنطقيتين — لاحظ كيف يعلن قارئ الشاشة اسم المجموعة قبل كل حقل بداخلها. - أخيرًا أضف نصوص المساعدة وربطها بـ
aria-describedby، وتحقق يدويًا بالتنقل بـ Tab أن الترتيب منطقي من أعلى الصفحة لأسفلها. - نمط
patternمعقول لهاتف محلي من 10 أرقام:pattern="[0-9]{10}"— عدّله حسب صيغة الأرقام في بلدك إن لزم.
خلاصة
نموذج التسجيل هو الاختبار الحقيقي لكل ما تعلمته عن النماذج: أنواع input الصحيحة، label مرتبط فعليًا لا شكليًا، fieldset/legend للتجميع المنطقي، تحقق مدمج بـ required/pattern، ورسائل مساعدة متاحة عبر aria-describedby — كل هذا بلا أي CSS أو JavaScript. النموذج الذي يعمل بالكامل بلوحة المفاتيح ويجتاز مدقّق W3C بلا أخطاء هو نموذج جاهز فعليًا للعالم الحقيقي.