كيفية بناء والتحقق من صحة نماذج ويب جذابة باستخدام HTML و CSS وجافاسكريبت النقية
تُعد النماذج (Forms) جزءًا أساسيًا ومعقدًا في تطوير الويب. إن إتقان جمع بيانات المستخدم والتحقق من صحتها بشكل صحيح هو إحدى أهم المهارات التي يجب أن يمتلكها مطور الواجهة الأمامية. تكمن الصعوبة في كثرة الحالات الهامشية (edge cases)؛ حيث يجب عليك توقع جميع الطرق التي قد يحاول بها المستخدم “كسر” نموذجك الجذاب، مع توفير تجربة مستخدم (UX) ممتازة في الوقت ذاته. تُعتبر تجربة المستخدم حاسمة لأن النماذج هي البوابة الرئيسية للتحويلات (conversions) للمنتجات والخدمات. أي خطأ من جانب مطور الواجهة الأمامية قد يؤدي إلى عواقب مالية وخيمة.
لهذا السبب، توجد آلاف (مع بعض المبالغة) من مكتبات النماذج التي تُطبق أفضل الممارسات الصناعية. لا عيب في استخدام هذه المكتبات، لكن المشكلة تظهر عندما يستخدمها المطورون دون فهم كيفية عمل النماذج في الأساس ولماذا تُعتبر أنماط معينة معايير قياسية. في هذا المقال، سأوضح لك كيفية بناء نموذج تسجيل (signup form) من الصفر، باستخدام HTML و CSS و JavaScript النقية فقط. لنبدأ!
فخ الحالة الافتراضية الواحدة: رؤية أعمق لتصميم النماذج
عندما تُعرض عليك تصميمات لنماذج مثل هذه، يجب أن يكون سؤالك الأول: “كم عدد الحالات التي لم يتم تمثيلها هنا؟” الأمثلة أعلاه تُظهر حالة واحدة فقط (عندما يزور المستخدم صفحة تسجيل الدخول، هذا ما سيراه على سطح المكتب وعلى الجوال).

حالات النموذج الأساسية التي يجب مراعاتها:
- حالة الخطأ (
Error State): ماذا يحدث إذا أدخلت بريدًا إلكترونيًا موجودًا بالفعل؟ - حالة التحميل (
Loading State): ماذا يحدث عند إرسال النموذج؟
عند التخطيط لعملك، تأكد من مراعاة جميع الجوانب غير الممثلة في التصميم والتي يجب أخذها في الاعتبار. عليك مراجعة متطلبات الميزات (feature requirements) بعناية وطرح الأسئلة إذا كنت تعتقد أن هناك شيئًا مفقودًا.
متطلبات الميزات الأساسية لنموذج التسجيل
بالحديث عن المتطلبات… كمطور، غالبًا ما ستُقدم لك وثيقة متطلبات المنتج (PRD - Product Requirements Document) من مدير المنتج أو المصمم أو مدير المشروع. تُقسم هذه الوثائق عادةً إلى قصص مستخدم فردية (user stories) ستنفذها خلال دورة تطوير (sprint). بوضع قبعة مدير المنتج، إليك متطلبات الميزات لنموذجنا:
- يجب على المستخدم تقديم عنوان بريد إلكتروني.
- يجب أن تتكون كلمة المرور من 10 أحرف على الأقل، وأن تحتوي على حرف كبير واحد على الأقل، ورقم واحد، وحرف خاص واحد.
- يجب أن نعرض رسائل خطأ واضحة للمستخدم عندما لا يفي بالمتطلبات.
بناء الهيكل الأساسي: ترميز HTML و CSS الأولي
أول جزء من الكود سنكتبه سيكون HTML مع لمسة بسيطة من CSS. قد لا يبدو الأمر كثيرًا بعد، لكن هناك عمل جيد هنا. لقد قمنا بإعداد عناصر جانبية ورئيسية بالإضافة إلى نموذجنا. أستخدم منهجية BEM كدليل لإنشاء أسماء الفئات (class names) وعناصر HTML دلالية لتحسين قابلية القراءة (readability).
تعتمد صفحة التسجيل لدينا على نهج “الجوال أولاً” (mobile-first approach)، مما يعني أننا نكتب أنماط الجوال أولاً ثم نضيف نقاط التوقف (breakpoints) لأنماط سطح المكتب. أستفيد من CSS Grid للتخطيط العام و Flexbox لوضع العناصر في القسم الرئيسي. لقد أضفت مستمع حدث الإرسال (submit event listener) للنموذج جنبًا إلى جنب مع دالة معالج الحدث (event handler function) التي تسجل كائن الحدث (event object) في الوقت الحالي.
التحقق من صحة البيانات: الاستفادة من ميزات المتصفح
دعنا نستفيد من منطق التحقق المدمج (built-in validation logic) باختيار أنواع المدخلات (input types) بحكمة. سنستخدم ما يلي:
- نوع إدخال البريد الإلكتروني (
Email input type) - نوع إدخال كلمة المرور (
Password input type)
يوفر لنا نوع إدخال البريد الإلكتروني (type="email") بعض عمليات التحقق اللطيفة مجانًا. فهو يتحقق من استخدام رمز @ ويتأكد أيضًا من وجود نص بعد الرمز. نظرًا لأن كلاً من البريد الإلكتروني وكلمة المرور مطلوبان، فلنضف السمة required إلى كلا العنصرين. سنضيف أيضًا السمة minlength إلى إدخال كلمة المرور.
< form id = "dkh-signup-form" >
< div class = "dkh-form-header" >
< div >
< small > Sign up with </ small >
< div class = "dkh-form-header__social-wrapper" >
< button type = "button" class = "dkh-btn dkh-btn-icon dkh-btn-github" > Github </ button >
< button type = "button" class = "dkh-btn dkh-btn-icon dkh-btn-twitter" > Twitter </ button >
</ div >
</ div >
</ div >
< div class = "dkh-form-body" >
< small > Or sign in with email and password </ small >
< div class = "dkh-form-field" >
< fieldset >
< input autofocus class = "dkh-form-field__input" name = "email" type = "email" id = "email" required placeholder = "Email" >
</ fieldset >
< div class = "dkh-form-field__messages" >
</ div >
</ div >
< div class = "dkh-form-field" >
< fieldset >
< input class = "dkh-form-field__input" name = "password" type = "password" id = "password" required minlength = "10" placeholder = "Password" >
</ fieldset >
< div class = "dkh-form-field__messages" >
</ div >
</ div >
</ div >
< div class = "dkh-form-footer" >
< button class = "dkh-btn dkh-btn-primary" type = "submit" > Sign Up </ button >
</ div >
</ form >
تخبر السمة type="email" المتصفح بأنه يجب التحقق من صحة الإدخال كبريد إلكتروني.

تمنحنا السمة minlength في إدخال كلمة المرور رسالة الخطأ المفيدة هذه:

الآن، في دالة handleSignupFormSubmit الخاصة بنا، يمكننا استخدام واجهة FormData API للحصول على القيم من نموذجنا، وفي النهاية إرسالها إلى واجهة برمجة تطبيقات (API).
function handleSignupFormSubmit ( e ) {
// prevent default browser behaviour
e.preventDefault();
const formDataEntries = new FormData(signupForm).entries();
const { email, password } = Object .fromEntries(formDataEntries);
// submit email and password to an API
}
رسائل الخطأ المخصصة: تحكم كامل في تجربة المستخدم
تُعد رسائل الخطأ التي يعرضها المتصفح مفيدة في البداية، ولكن ماذا لو أردت عرض هذه الرسائل أسفل حقل الإدخال الخاص بها؟ وماذا لو أردت التحكم في مظهرها؟ للأسف، لا يمنحنا المتصفح أي تحكم في كيفية عرض رسائل الخطأ الافتراضية. هنا يأتي دور عناصر <div> ذات الفئة dkh-form-field__messages. يمكننا عرض رسائل الخطأ المخصصة داخل هذه العناصر.
دعنا نكتب دالتين مخصصتين للتحقق من صحة كلمة مرور المستخدم وقيمه البريد الإلكتروني لتلبية المتطلبات.
function validatePassword ( password, minlength ) {
if (!password) return 'Password is required' ;
if (password.length < minlength) {
return `Please enter a password that's at least ${minlength} characters long` ;
}
const hasCapitalLetter = /[A-Z]/g ;
if (!hasCapitalLetter.test(password)) {
return 'Please use at least one capital letter.' ;
}
const hasNumber = /\d/g ;
if (!hasNumber.test(password)) {
return 'Please use at least one number.' ;
}
return '' ;
}
function validateEmail ( email ) {
if (!email) return 'Email is required' ;
const isValidEmail = /^\S+@\S+$/g
if (!isValidEmail.test(email)) {
return 'Please enter a valid email' ;
}
return '' ;
}
التعبير النمطي (regex) /^\S+@\S+$/g بعيد عن أن يكون مثاليًا، لكنه على الأقل يتحقق من وجود أحرف قبل وبعد الرمز @. أفضل طريقة للتحقق من صحة البريد الإلكتروني هي إرسال بريد إلكتروني للتأكيد إلى أي مستخدم يسجل. سيتعين على المستخدم بعد ذلك فتح هذا البريد الإلكتروني والنقر على رابط لتأكيد أن عنوان بريده الإلكتروني صالح. إذا كنت ترغب في التعمق أكثر في التحقق من صحة البريد الإلكتروني من جانب العميل (client-side email validation)، فهذا الموضوع رائع.
الآن، دعنا نكتشف كيفية عرض رسائل الخطأ على الصفحة.
function handleSignupFormSubmit ( e ) {
// prevent default browser behaviour
e.preventDefault();
const formDataEntries = new FormData(signupForm).entries();
const { email, password } = Object .fromEntries(formDataEntries);
const emailErrorMessage = validateEmail(email);
const passowrdErrorMessage = validatePassword(password);
if (!emailErrorMessage) {
// select the email form field message element
const emailErrorMessageElement = document .querySelector(
'.email .dkh-form-field__messages'
);
// show email error message to user
emailErrorMessageElement.innerText = emailErrorMessage;
}
if (passowrdErrorMessage) {
// select the email form field message element
const passwordErrorMessageElement = document .querySelector(
'.password .dkh-form-field__messages'
);
// show password error message to user
passwordErrorMessageElement.innerText = passowrdErrorMessage;
}
}
شيء إضافي سأشير إليه: لكي تظهر هذه الرسائل، نحتاج إلى إزالة السمتين required من مدخلات البريد الإلكتروني وكلمة المرور. نحتاج أيضًا إلى تغيير قيمة السمة type لإدخال البريد الإلكتروني.
< input autofocus class = "dkh-form-field__input" type = "text" name = "email" id = "email" placeholder = "Email" >
نحتاج أيضًا إلى إزالة السمة minlength من إدخال كلمة المرور.
< input class = "dkh-form-field__input" name = "password" type = "password" id = "password" placeholder = "Password" >
يؤدي تحديث هذه السمات إلى إزالة التحقق المستند إلى المتصفح لصالح منطق التحقق الخاص بنا. إليك كيف ستظهر رسائل الخطأ المخصصة لدينا:

تطبيق الأنماط (CSS): لمسة جمالية ووظيفية
أترك CSS حتى النهاية لأنه، في تجربتي الشخصية، يكون من الصعب التركيز على المنطق عندما يكون التصميم المرئي مكتملًا. عندما يبدو المكون أو الصفحة “منتهيًا” للعين، يمكن أن يخلق شعورًا زائفًا بأنه قد تم الانتهاء منه بالفعل. ليس لدي أي بحث يدعم هذا، مجرد رأيي الشخصي. إليك حالة الكود بعد إضافة قدر كبير من CSS.
حالة النموذج بعد تطبيق الأنماط:

حالة الخطأ بعد تطبيق الأنماط:

لقد قمت بتضمين أيقونات Font Awesome لأزرار Github و Twitter.
< div class = "dkh-form-header" >
< div >
< small > Sign up with </ small >
< div class = "dkh-form-header__social-wrapper" >
< button type = "button" class = "dkh-btn dkh-btn-icon dkh-btn-github" >
< i class = "fab fa-github fa-lg" > </ i > Github
</ button >
< button type = "button" class = "dkh-btn dkh-btn-icon dkh-btn-twitter" >
< i class = "fab fa-twitter fa-lg" > </ i > Twitter
</ button >
</ div >
</ div >
</ div >
خلاصة عملية: بناء نماذج قوية بدون مكتبات خارجية
لقد قمنا بإنشاء اللبنات الأساسية لبناء نماذج التسجيل وتسجيل الدخول دون الحاجة إلى مكتبات خارجية.
إذا كنت تستخدم إطار عمل (framework) مثل React أو Vue، فهناك الكثير من مكتبات النماذج والتحقق الرائعة. يمكنك الاعتماد عليها لإنجاز المهمة بسرعة. ومع ذلك، إذا كنت جديدًا في تطوير البرمجيات، فإنني أشجعك على التركيز على الأساسيات أولاً قبل استخدام هذه الأدوات.
لقد حصلت على وظيفتي الأولى كمطور قبل خمس سنوات، وقد غيرت رحلتي في مجال التكنولوجيا حياتي إلى الأفضل. أعتقد أنه من المهم التركيز على الأساسيات وإتقانها حتى تتمكن من فهم أدوات مثل React و Vue بسهولة أكبر. إحدى المشكلات التي لاحظتها عند إدارتي لاجتماعات المطورين لسنوات هي أن الأشخاص الجدد في البرمجة كانوا يلجأون إلى المكتبات وأطر العمل بسرعة كبيرة جدًا. انتهى الأمر بإيذائهم وعانى الكثير منهم خلال المقابلات.
إذا كنت تتعلم البرمجة وتحتاج إلى مساعدة، فإن التركيز على بناء الفهم العميق للمفاهيم الأساسية سيمهد لك الطريق لإتقان الأدوات المتقدمة. تذكر أن إتقان الأساسيات هو مفتاح النجاح في عالم تطوير البرمجيات المتغير باستمرار.
الخلاصة التقنية
يُظهر هذا المقال ببراعة أن بناء نماذج ويب قوية وجميلة لا يتطلب بالضرورة الاعتماد على مكتبات خارجية معقدة. من خلال التركيز على HTML الدلالي، و CSS المُحسّن، و JavaScript النقية، يمكن للمطورين تحقيق تحكم كامل في تجربة المستخدم والتحقق من صحة البيانات. الأهم من ذلك هو فهم حالات النموذج المختلفة (الافتراضي، الخطأ، التحميل) وتخطيطها بعناية لتقديم واجهة مستخدم سلسة وفعالة. إن إتقان هذه الأساسيات لا يعزز فقط مهارات المطورين، بل يضمن أيضًا بناء تطبيقات ويب أكثر استقرارًا وأمانًا وقابلية للتوسع، مما يقلل من التبعيات ويزيد من مرونة المشروع.