تنسيق النماذج والمدخلات
تنسيق النماذج والمدخلات في Tailwind CSS
النماذج هي عناصر واجهة مستخدم حرجة تتطلب تنسيقاً دقيقاً لسهولة الاستخدام وإمكانية الوصول. يوفر Tailwind أدوات شاملة لتنسيق عناصر النماذج، والإضافة الرسمية @tailwindcss/forms توفر إعدادات افتراضية جميلة وقابلة للوصول لجميع أنواع المدخلات.
إمكانية الوصول للنموذج أولاً
استخدم دائماً دلالة النماذج المناسبة: تسميات مرتبطة بالمدخلات عبر سمات for و id، مجموعات حقول للتجميع، وأنواع مدخلات مناسبة. إمكانية الوصول تضمن تفاعل جميع المستخدمين مع نماذجك بشكل فعال.
إضافة @tailwindcss/forms
توفر إضافة النماذج الرسمية أنماط أساسية موجهة وقابلة للوصول لعناصر التحكم في النماذج. تعيد تعيين أنماط المتصفح الافتراضية وتوفر أساساً صلباً للتخصيص.
تثبيت @tailwindcss/forms
<!-- التثبيت عبر npm -->
npm install -D @tailwindcss/forms
<!-- الإضافة إلى tailwind.config.js -->
module.exports = {
plugins: [
require('@tailwindcss/forms'),
],
}
<!-- أو مع خيار الاستراتيجية -->
module.exports = {
plugins: [
require('@tailwindcss/forms')({
strategy: 'base', // 'base' أو 'class'
}),
],
}
<!-- الاستراتيجية 'base': تطبق الأنماط على جميع المدخلات عالمياً
الاستراتيجية 'class': تتطلب فئات form-{type} على المدخلات -->
استراتيجيات الإضافة
استخدم strategy: 'base' (افتراضي) لتنسيق جميع عناصر النماذج تلقائياً. استخدم strategy: 'class' إذا كنت بحاجة إلى مزيد من التحكم وتريد الاشتراك في عناصر محددة باستخدام فئات مثل form-input، form-select، إلخ.
مدخلات النص
تنسيق مدخلات النص الأساسية
<!-- مدخل نص بسيط -->
<div class="mb-4">
<label for="name" class="block text-sm font-medium text-gray-700 mb-2">
الاسم الكامل
</label>
<input type="text"
id="name"
name="name"
class="w-full px-4 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="أدخل اسمك">
</div>
<!-- مدخل البريد الإلكتروني -->
<div class="mb-4">
<label for="email" class="block text-sm font-medium text-gray-700 mb-2">
عنوان البريد الإلكتروني
</label>
<input type="email"
id="email"
name="email"
required
class="w-full px-4 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="you@example.com">
</div>
<!-- مدخل كلمة المرور -->
<div class="mb-4">
<label for="password" class="block text-sm font-medium text-gray-700 mb-2">
كلمة المرور
</label>
<input type="password"
id="password"
name="password"
required
class="w-full px-4 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="••••••••">
</div>
أحجام المدخلات
<!-- مدخل صغير -->
<input type="text"
class="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="مدخل صغير">
<!-- مدخل متوسط (افتراضي) -->
<input type="text"
class="w-full px-4 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="مدخل متوسط">
<!-- مدخل كبير -->
<input type="text"
class="w-full px-5 py-3 text-lg border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="مدخل كبير">
حلقات التركيز والحالات
أنماط تركيز مخصصة
<!-- حلقة تركيز زرقاء (افتراضي) -->
<input type="text"
class="w-full px-4 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
<!-- حلقة تركيز أرجوانية -->
<input type="text"
class="w-full px-4 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-purple-500 focus:border-purple-500">
<!-- بدون حلقة تركيز (غير موصى به لإمكانية الوصول) -->
<input type="text"
class="w-full px-4 py-2 border border-gray-300 rounded-lg
focus:outline-none focus:border-blue-500">
<!-- حلقة تركيز مع إزاحة -->
<input type="text"
class="w-full px-4 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">
حالات التحقق
<!-- حالة النجاح -->
<div class="mb-4">
<label for="valid-input" class="block text-sm font-medium text-green-700 mb-2">
البريد الإلكتروني (صالح)
</label>
<input type="email"
id="valid-input"
class="w-full px-4 py-2 border-2 border-green-500 rounded-lg
focus:ring-2 focus:ring-green-500 focus:border-transparent
bg-green-50"
value="user@example.com">
<p class="mt-2 text-sm text-green-600">
✓ عنوان البريد الإلكتروني صالح
</p>
</div>
<!-- حالة الخطأ -->
<div class="mb-4">
<label for="error-input" class="block text-sm font-medium text-red-700 mb-2">
البريد الإلكتروني (غير صالح)
</label>
<input type="email"
id="error-input"
class="w-full px-4 py-2 border-2 border-red-500 rounded-lg
focus:ring-2 focus:ring-red-500 focus:border-transparent
bg-red-50"
value="invalid-email">
<p class="mt-2 text-sm text-red-600">
✗ الرجاء إدخال عنوان بريد إلكتروني صالح
</p>
</div>
<!-- حالة التحذير -->
<div class="mb-4">
<label for="warning-input" class="block text-sm font-medium text-yellow-700 mb-2">
كلمة المرور
</label>
<input type="password"
id="warning-input"
class="w-full px-4 py-2 border-2 border-yellow-500 rounded-lg
focus:ring-2 focus:ring-yellow-500 focus:border-transparent
bg-yellow-50">
<p class="mt-2 text-sm text-yellow-600">
⚠ كلمة المرور ضعيفة، فكر في استخدام أحرف خاصة
</p>
</div>
معطل مقابل للقراءة فقط
لا يمكن التركيز على مدخلات disabled أو إرسالها وتظهر باهتة. يمكن التركيز على مدخلات readonly وإرسالها لكن لا يمكن تحريرها. اختر بناءً على حالة استخدامك: استخدم معطل للحقول غير المتاحة، للقراءة فقط للحقول التي تعرض بيانات لكن لا ينبغي تغييرها.
مناطق النص
تنسيق منطقة النص
<!-- منطقة نص أساسية -->
<div class="mb-4">
<label for="message" class="block text-sm font-medium text-gray-700 mb-2">
الرسالة
</label>
<textarea id="message"
name="message"
rows="4"
class="w-full px-4 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500 focus:border-transparent
resize-none"
placeholder="أدخل رسالتك هنا..."></textarea>
<p class="mt-2 text-sm text-gray-500">
بحد أقصى 500 حرف
</p>
</div>
<!-- منطقة نص ذاتية تغيير الحجم (مع أدوات تغيير الحجم) -->
<textarea class="w-full px-4 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500
resize-y"
placeholder="قابل لتغيير الحجم عمودياً"></textarea>
<textarea class="w-full px-4 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500
resize-x"
placeholder="قابل لتغيير الحجم أفقياً"></textarea>
<textarea class="w-full px-4 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500
resize"
placeholder="قابل لتغيير الحجم في كلا الاتجاهين"></textarea>
القوائم المنسدلة
تنسيق القائمة المنسدلة
<!-- قائمة منسدلة أساسية -->
<div class="mb-4">
<label for="country" class="block text-sm font-medium text-gray-700 mb-2">
الدولة
</label>
<select id="country"
name="country"
class="w-full px-4 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500 focus:border-transparent
bg-white">
<option value="">اختر دولة</option>
<option value="us">الولايات المتحدة</option>
<option value="uk">المملكة المتحدة</option>
<option value="ca">كندا</option>
<option value="au">أستراليا</option>
</select>
</div>
<!-- قائمة منسدلة مع سهم مخصص -->
<div class="relative">
<select class="w-full px-4 py-2 pl-10 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500 focus:border-transparent
appearance-none bg-white">
<option>الخيار 1</option>
<option>الخيار 2</option>
<option>الخيار 3</option>
</select>
<div class="absolute inset-y-0 left-0 flex items-center px-2 pointer-events-none">
<svg class="w-5 h-5 text-gray-400" fill="none" stroke="currentColor">
<path d="M19 9l-7 7-7-7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
</div>
<!-- قائمة منسدلة متعددة -->
<select multiple
size="5"
class="w-full px-4 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500">
<option>الخيار 1</option>
<option>الخيار 2</option>
<option>الخيار 3</option>
<option>الخيار 4</option>
<option>الخيار 5</option>
</select>
خانات الاختيار وأزرار الراديو
تنسيق خانة الاختيار
<!-- خانة اختيار أساسية -->
<div class="flex items-center mb-4">
<input type="checkbox"
id="terms"
name="terms"
class="w-4 h-4 text-blue-600 border-gray-300 rounded
focus:ring-2 focus:ring-blue-500">
<label for="terms" class="mr-2 text-sm text-gray-700">
أوافق على الشروط والأحكام
</label>
</div>
<!-- خانة اختيار منسقة مخصصة -->
<div class="flex items-center mb-4">
<input type="checkbox"
id="custom-check"
class="w-5 h-5 text-purple-600 border-gray-300 rounded-md
focus:ring-2 focus:ring-purple-500">
<label for="custom-check" class="mr-3 text-sm font-medium text-gray-900">
اشترك في النشرة الإخبارية
</label>
</div>
<!-- مجموعة خانات اختيار -->
<fieldset class="mb-4">
<legend class="text-sm font-medium text-gray-700 mb-3">
اختر اهتماماتك
</legend>
<div class="space-y-2">
<div class="flex items-center">
<input type="checkbox" id="tech" value="tech"
class="w-4 h-4 text-blue-600 border-gray-300 rounded
focus:ring-2 focus:ring-blue-500">
<label for="tech" class="mr-2 text-sm text-gray-700">
التكنولوجيا
</label>
</div>
<div class="flex items-center">
<input type="checkbox" id="design" value="design"
class="w-4 h-4 text-blue-600 border-gray-300 rounded
focus:ring-2 focus:ring-blue-500">
<label for="design" class="mr-2 text-sm text-gray-700">
التصميم
</label>
</div>
<div class="flex items-center">
<input type="checkbox" id="business" value="business"
class="w-4 h-4 text-blue-600 border-gray-300 rounded
focus:ring-2 focus:ring-blue-500">
<label for="business" class="mr-2 text-sm text-gray-700">
الأعمال
</label>
</div>
</div>
</fieldset>
تنسيق زر الراديو
<!-- أزرار راديو أساسية -->
<fieldset class="mb-4">
<legend class="text-sm font-medium text-gray-700 mb-3">
اختر خطة
</legend>
<div class="space-y-2">
<div class="flex items-center">
<input type="radio"
id="basic"
name="plan"
value="basic"
class="w-4 h-4 text-blue-600 border-gray-300
focus:ring-2 focus:ring-blue-500">
<label for="basic" class="mr-2 text-sm text-gray-700">
أساسي - 9 ريال/شهر
</label>
</div>
<div class="flex items-center">
<input type="radio"
id="pro"
name="plan"
value="pro"
checked
class="w-4 h-4 text-blue-600 border-gray-300
focus:ring-2 focus:ring-blue-500">
<label for="pro" class="mr-2 text-sm text-gray-700">
محترف - 29 ريال/شهر
</label>
</div>
<div class="flex items-center">
<input type="radio"
id="enterprise"
name="plan"
value="enterprise"
class="w-4 h-4 text-blue-600 border-gray-300
focus:ring-2 focus:ring-blue-500">
<label for="enterprise" class="mr-2 text-sm text-gray-700">
مؤسسي - 99 ريال/شهر
</label>
</div>
</div>
</fieldset>
<!-- أزرار راديو بأسلوب البطاقة -->
<div class="space-y-3">
<label class="flex items-center p-4 border-2 border-gray-200 rounded-lg
cursor-pointer hover:border-blue-500 transition-colors
has-[:checked]:border-blue-500 has-[:checked]:bg-blue-50">
<input type="radio" name="plan-card" value="basic"
class="w-4 h-4 text-blue-600">
<div class="mr-3 flex-1">
<div class="font-medium text-gray-900">الخطة الأساسية</div>
<div class="text-sm text-gray-500">مثالية للأفراد</div>
</div>
<div class="text-xl font-bold text-gray-900">9 ريال</div>
</label>
<label class="flex items-center p-4 border-2 border-gray-200 rounded-lg
cursor-pointer hover:border-blue-500 transition-colors
has-[:checked]:border-blue-500 has-[:checked]:bg-blue-50">
<input type="radio" name="plan-card" value="pro"
class="w-4 h-4 text-blue-600">
<div class="mr-3 flex-1">
<div class="font-medium text-gray-900">الخطة الاحترافية</div>
<div class="text-sm text-gray-500">الأفضل للفرق</div>
</div>
<div class="text-xl font-bold text-gray-900">29 ريال</div>
</label>
</div>
تنسيق مدخل الملف
مدخل ملف مخصص
<!-- مدخل ملف أساسي (صعب التنسيق) -->
<input type="file"
class="block w-full text-sm text-gray-500
file:ml-4 file:py-2 file:px-4
file:rounded-lg file:border-0
file:text-sm file:font-semibold
file:bg-blue-50 file:text-blue-700
hover:file:bg-blue-100">
<!-- رفع ملف مخصص مع مدخل مخفي -->
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-2">
رفع مستند
</label>
<div class="flex items-center justify-center w-full">
<label class="flex flex-col items-center justify-center w-full h-32
border-2 border-gray-300 border-dashed rounded-lg
cursor-pointer bg-gray-50 hover:bg-gray-100">
<div class="flex flex-col items-center justify-center pt-5 pb-6">
<svg class="w-8 h-8 mb-4 text-gray-500" fill="none" stroke="currentColor">
<path d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<p class="mb-2 text-sm text-gray-500">
<span class="font-semibold">انقر للرفع</span> أو اسحب وأفلت
</p>
<p class="text-xs text-gray-500">PDF، DOC، أو DOCX (بحد أقصى 10 ميجا)</p>
</div>
<input type="file" class="hidden" accept=".pdf,.doc,.docx">
</label>
</div>
</div>
أنماط تخطيط النماذج
نموذج تسجيل كامل
<form class="max-w-lg mx-auto bg-white rounded-lg shadow-lg p-8">
<h2 class="text-2xl font-bold text-gray-900 mb-6">إنشاء حساب</h2>
<!-- الاسم الكامل -->
<div class="mb-4">
<label for="fullname" class="block text-sm font-medium text-gray-700 mb-2">
الاسم الكامل
</label>
<input type="text"
id="fullname"
required
class="w-full px-4 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="أحمد محمد">
</div>
<!-- البريد الإلكتروني -->
<div class="mb-4">
<label for="email-reg" class="block text-sm font-medium text-gray-700 mb-2">
عنوان البريد الإلكتروني
</label>
<input type="email"
id="email-reg"
required
class="w-full px-4 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="ahmed@example.com">
</div>
<!-- كلمة المرور -->
<div class="mb-4">
<label for="password-reg" class="block text-sm font-medium text-gray-700 mb-2">
كلمة المرور
</label>
<input type="password"
id="password-reg"
required
class="w-full px-4 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="••••••••">
<p class="mt-2 text-xs text-gray-500">
يجب أن تكون 8 أحرف على الأقل مع أحرف كبيرة وصغيرة وأرقام
</p>
</div>
<!-- خانة اختيار الشروط -->
<div class="mb-6">
<div class="flex items-start">
<input type="checkbox"
id="terms-reg"
required
class="w-4 h-4 mt-1 text-blue-600 border-gray-300 rounded
focus:ring-2 focus:ring-blue-500">
<label for="terms-reg" class="mr-2 text-sm text-gray-700">
أوافق على <a href="#" class="text-blue-600 hover:underline">شروط الخدمة</a>
و <a href="#" class="text-blue-600 hover:underline">سياسة الخصوصية</a>
</label>
</div>
</div>
<!-- زر الإرسال -->
<button type="submit"
class="w-full bg-blue-600 text-white py-3 px-4 rounded-lg font-medium
hover:bg-blue-700 focus:ring-4 focus:ring-blue-300
transition-colors duration-200">
إنشاء حساب
</button>
<p class="mt-4 text-center text-sm text-gray-600">
لديك حساب بالفعل؟
<a href="#" class="text-blue-600 hover:underline font-medium">تسجيل الدخول</a>
</p>
</form>
تخطيط نموذج من عمودين
<form class="max-w-4xl mx-auto bg-white rounded-lg shadow-lg p-8">
<h2 class="text-2xl font-bold text-gray-900 mb-6">معلومات الاتصال</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- الاسم الأول -->
<div>
<label for="firstname" class="block text-sm font-medium text-gray-700 mb-2">
الاسم الأول
</label>
<input type="text" id="firstname"
class="w-full px-4 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500 focus:border-transparent">
</div>
<!-- اسم العائلة -->
<div>
<label for="lastname" class="block text-sm font-medium text-gray-700 mb-2">
اسم العائلة
</label>
<input type="text" id="lastname"
class="w-full px-4 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500 focus:border-transparent">
</div>
<!-- البريد الإلكتروني (عرض كامل) -->
<div class="md:col-span-2">
<label for="email-contact" class="block text-sm font-medium text-gray-700 mb-2">
عنوان البريد الإلكتروني
</label>
<input type="email" id="email-contact"
class="w-full px-4 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500 focus:border-transparent">
</div>
<!-- الهاتف -->
<div>
<label for="phone" class="block text-sm font-medium text-gray-700 mb-2">
رقم الهاتف
</label>
<input type="tel" id="phone"
class="w-full px-4 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500 focus:border-transparent">
</div>
<!-- الشركة -->
<div>
<label for="company" class="block text-sm font-medium text-gray-700 mb-2">
الشركة
</label>
<input type="text" id="company"
class="w-full px-4 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500 focus:border-transparent">
</div>
</div>
<div class="mt-6">
<button type="submit"
class="bg-blue-600 text-white py-3 px-8 rounded-lg font-medium
hover:bg-blue-700 focus:ring-4 focus:ring-blue-300
transition-colors duration-200">
إرسال
</button>
</div>
</form>
تمرين 1: نموذج تسجيل دخول مع التحقق
أنشئ نموذج تسجيل دخول كامل مع التحقق المرئي:
- حقول البريد الإلكتروني وكلمة المرور مع تسميات مناسبة
- خانة اختيار "تذكرني"
- رابط "نسيت كلمة المرور؟"
- إظهار حالات التحقق: صالح (أخضر)، غير صالح (أحمر)
- عرض رسائل خطأ أسفل الحقول غير الصالحة
- زر إرسال يعطل أثناء الإرسال
- تخطيط مستجيب (موبايل أولاً)
تمرين 2: نموذج متعدد الخطوات
ابنِ معالج تسجيل من 3 خطوات:
- الخطوة 1: معلومات شخصية (الاسم، البريد الإلكتروني، الهاتف)
- الخطوة 2: اختيار الخطة (أزرار راديو بتنسيق البطاقة)
- الخطوة 3: تفاصيل الدفع (رقم البطاقة، الانتهاء، CVV)
- مؤشر تقدم يظهر الخطوة الحالية
- أزرار تنقل السابق/التالي
- التحقق من النموذج في كل خطوة
- مراجعة ملخص في الخطوة النهائية
تمرين 3: نموذج بحث متقدم
أنشئ نموذج بحث شامل:
- مدخل بحث نصي مع أيقونة
- قائمة منسدلة للفئة
- نطاق السعر مع مدخلين رقميين (الحد الأدنى/الأقصى)
- مجموعة خانات اختيار للمرشحات (اختيارات متعددة)
- منتقي نطاق التاريخ (مدخلا تاريخ)
- قائمة منسدلة للترتيب حسب
- زر مسح المرشحات وزر البحث
- قابل للطي على الموبايل (إظهار/إخفاء المرشحات)
أفضل ممارسات النماذج
- ربط التسميات دائماً بالمدخلات باستخدام سمات
forوid - استخدام أنواع مدخلات مناسبة (
email،tel،number) للوحات مفاتيح أفضل للموبايل - إضافة
required،pattern،min،maxللتحقق من HTML5 - توفير رسائل خطأ واضحة بجوار الحقول غير الصالحة
- استخدام نص العنصر النائب لأمثلة التنسيق، وليس كبديل للتسمية
- التأكد من تباين لون كافٍ لجميع النصوص (WCAG AA: 4.5:1 كحد أدنى)
- جعل حالات التركيز مرئية جداً للتنقل بلوحة المفاتيح
- اختبار النماذج مع التنقل بلوحة المفاتيح فقط
- تجميع الحقول ذات الصلة بـ
<fieldset>و<legend> - استخدام سمات الإكمال التلقائي لمساعدة المستخدمين على ملء النماذج بشكل أسرع
الخلاصة
يوفر Tailwind أدوات شاملة لإنشاء نماذج جميلة وقابلة للوصول:
- إضافة @tailwindcss/forms: توفر أنماط أساسية متسقة وقابلة للوصول لجميع عناصر النماذج
- مدخلات النص: تحكم كامل في التنسيق مع حلقات التركيز والأحجام والحالات
- إدارة التركيز: حلقات تركيز قابلة للتخصيص لإمكانية وصول أفضل (
focus:ring-{n}) - حالات التحقق: ملاحظات مرئية لحالات النجاح والخطأ والتحذير
- مناطق النص: التحكم في تغيير الحجم باستخدام أدوات
resize-{direction} - القوائم المنسدلة: تنسيق القوائم المنسدلة مع أسهم مخصصة باستخدام
appearance-none - خانات الاختيار وأزرار الراديو: تخصيص كامل مع أدوات اللون والحجم
- مدخلات الملفات: التنسيق بمعدل
file:أو إنشاء مناطق رفع مخصصة - تخطيطات النماذج: Grid وFlexbox لهياكل نماذج مستجيبة ومنظمة
النماذج المصممة جيداً ضرورية للتحويلات ورضا المستخدم. أعط دائماً الأولوية لإمكانية الوصول، وفر ملاحظات واضحة، وتأكد من عمل النماذج بسلاسة عبر جميع الأجهزة وطرق الإدخال.