حالات التمرير والتركيز والمتغيرات
حالات التمرير والتركيز والمتغيرات في Tailwind CSS
يوفر Tailwind CSS متغيرات حالة قوية تسمح لك بتطبيق الأنماط بشكل شرطي بناءً على حالات تفاعل المستخدم وحالات العنصر وغيرها. تجعل هذه المتغيرات من السهل بشكل لا يصدق إنشاء واجهات مستخدم تفاعلية وسهلة الوصول دون كتابة CSS مخصص.
حالات التفاعل الأساسية
أكثر متغيرات الحالة شيوعاً هي لتفاعلات الماوس. يجعل Tailwind من السهل تغيير الأنماط عندما يقوم المستخدمون بالتمرير فوق العناصر أو النقر عليها أو التركيز عليها.
حالة التمرير
يطبق معدل hover: الأنماط عندما يقوم المستخدم بتمرير الماوس فوق العنصر:
أمثلة التمرير الأساسية
<!-- تغيير الخلفية عند التمرير -->
<button class="bg-blue-500 hover:bg-blue-700 text-white px-4 py-2 rounded">
مرر فوقي
</button>
<!-- تغيير لون النص عند التمرير -->
<a href="#" class="text-blue-600 hover:text-blue-800 underline">
رابط التمرير
</a>
<!-- تأثيرات متعددة عند التمرير -->
<div class="bg-white hover:bg-gray-100 hover:shadow-lg transition-all p-4">
مرر للحصول على تأثيرات متعددة
</div>
<!-- تأثير التكبير عند التمرير -->
<img src="image.jpg" class="hover:scale-110 transition-transform" alt="صورة">
hover: مع أي فئة أداة. يمكنك دمجه مع الألوان والمسافات والتحويلات والظلال والمزيد.
حالة التركيز
يطبق معدل focus: الأنماط عندما يحصل العنصر على التركيز من لوحة المفاتيح، وهو ضروري لإمكانية الوصول:
أمثلة حالة التركيز
<!-- حقل إدخال مع أنماط التركيز -->
<input
type="text"
class="border border-gray-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-200 px-4 py-2 rounded"
placeholder="ركز علي"
>
<!-- زر مع حلقة التركيز -->
<button class="bg-green-500 text-white px-4 py-2 rounded focus:outline-none focus:ring-4 focus:ring-green-300">
انقر علي
</button>
<!-- رابط مع أنماط التركيز -->
<a href="#" class="text-blue-600 focus:text-blue-800 focus:underline">
اضغط Tab للتركيز
</a>
focus:ring مثالية لهذا.
حالة النشاط
يطبق معدل active: الأنماط عندما يتم النقر على العنصر أو الضغط عليه:
أمثلة الحالة النشطة
<!-- زر مع حالة نشطة -->
<button class="bg-blue-500 hover:bg-blue-600 active:bg-blue-700 text-white px-6 py-3 rounded">
اضغط علي
</button>
<!-- تصغير عند النقر -->
<button class="bg-green-500 active:scale-95 transition-transform px-4 py-2 rounded text-white">
انقر للتصغير
</button>
<!-- حالات مدمجة -->
<button class="bg-purple-500 hover:bg-purple-600 active:bg-purple-800 focus:ring-4 focus:ring-purple-300 text-white px-4 py-2 rounded">
جميع الحالات
</button>
متغيرات التركيز المتقدمة
التركيز داخلياً
يطبق معدل focus-within: الأنماط على العنصر الأب عندما يحصل أي من أطفاله على التركيز:
أمثلة التركيز داخلياً
<!-- حاوية نموذج تبرز عندما يكون أي إدخال مركزاً -->
<div class="border-2 border-gray-300 focus-within:border-blue-500 focus-within:shadow-lg p-4 rounded">
<label class="block mb-2">الاسم</label>
<input type="text" class="border px-3 py-2 rounded w-full">
</div>
<!-- حاوية البحث مع التركيز داخلياً -->
<div class="flex items-center bg-gray-100 focus-within:bg-white focus-within:ring-2 focus-within:ring-blue-300 rounded-lg px-4 py-2">
<svg class="w-5 h-5 text-gray-400">...</svg>
<input type="search" class="bg-transparent focus:outline-none ml-2" placeholder="بحث...">
</div>
التركيز المرئي
يطبق معدل focus-visible: الأنماط فقط عندما يحصل العنصر على تركيز لوحة المفاتيح، وليس تركيز النقر بالماوس:
أمثلة التركيز المرئي
<!-- يظهر حلقة التركيز فقط عند استخدام Tab، وليس عند النقر -->
<button class="bg-blue-500 text-white px-4 py-2 rounded focus:outline-none focus-visible:ring-4 focus-visible:ring-blue-300">
اضغط Tab لرؤية الحلقة
</button>
<!-- رابط مع مؤشر تركيز لوحة المفاتيح فقط -->
<a href="#" class="text-blue-600 focus-visible:underline focus-visible:ring-2 focus-visible:ring-blue-300 rounded">
تركيز لوحة المفاتيح فقط
</a>
focus-visible: أفضل لتجربة المستخدم لأنه لا يظهر حلقات التركيز عند النقر بالماوس، لكنه لا يزال يوفرها لمستخدمي لوحة المفاتيح.
معدلات المجموعة والنظير
تمرير المجموعة
تسمح أدوات group و group-hover: بتنسيق العناصر الفرعية بناءً على حالة تمرير الأب:
أمثلة تمرير المجموعة
<!-- بطاقة مع تأثيرات تمرير المجموعة -->
<div class="group bg-white hover:bg-blue-50 p-6 rounded-lg shadow transition-all">
<h3 class="text-gray-800 group-hover:text-blue-600 text-xl font-bold">
عنوان البطاقة
</h3>
<p class="text-gray-600 group-hover:text-gray-800 mt-2">
مرر فوق البطاقة لرؤية التغييرات
</p>
<button class="bg-blue-500 group-hover:bg-blue-600 text-white px-4 py-2 rounded mt-4">
اعرف المزيد
</button>
</div>
<!-- تنقل مع تمرير المجموعة -->
<a href="#" class="group flex items-center gap-3 p-3 rounded hover:bg-gray-100">
<svg class="w-6 h-6 text-gray-400 group-hover:text-blue-600">...</svg>
<span class="text-gray-700 group-hover:text-gray-900 group-hover:font-semibold">
لوحة التحكم
</span>
<svg class="w-4 h-4 text-gray-400 group-hover:translate-x-1 transition-transform ml-auto">←</svg>
</a>
<!-- بطاقة صورة مع تراكب -->
<div class="group relative overflow-hidden rounded-lg">
<img src="image.jpg" class="group-hover:scale-110 transition-transform duration-300" alt="صورة">
<div class="absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-50 transition-all">
<div class="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity">
<button class="bg-white text-gray-900 px-6 py-3 rounded-lg font-semibold">
عرض التفاصيل
</button>
</div>
</div>
</div>
معدلات النظير
تسمح أدوات peer و peer-*: بتنسيق عنصر بناءً على حالة عنصر شقيق:
أمثلة معدلات النظير
<!-- إدخال تسمية عائمة -->
<div class="relative">
<input
type="text"
id="email"
class="peer w-full border-2 border-gray-300 focus:border-blue-500 px-4 py-3 rounded outline-none"
placeholder=" "
>
<label
for="email"
class="absolute left-4 top-3 text-gray-500 peer-focus:text-blue-500 peer-focus:text-sm peer-focus:-top-6 peer-focus:left-0 transition-all peer-[:not(:placeholder-shown)]:text-sm peer-[:not(:placeholder-shown)]:-top-6 peer-[:not(:placeholder-shown)]:left-0"
>
عنوان البريد الإلكتروني
</label>
</div>
<!-- خانة اختيار مع تنسيق النظير -->
<div class="flex items-center gap-3">
<input type="checkbox" id="terms" class="peer w-5 h-5">
<label for="terms" class="text-gray-600 peer-checked:text-blue-600 peer-checked:font-semibold">
أوافق على الشروط والأحكام
</label>
</div>
<!-- زر راديو مع تنسيق مخصص -->
<div class="flex items-start gap-3">
<input type="radio" id="option1" name="option" class="peer sr-only">
<label for="option1" class="flex items-center gap-3 p-4 border-2 border-gray-300 peer-checked:border-blue-500 peer-checked:bg-blue-50 rounded-lg cursor-pointer">
<div class="w-6 h-6 rounded-full border-2 border-gray-300 peer-checked:border-blue-500 flex items-center justify-center">
<div class="w-3 h-3 rounded-full bg-blue-500 hidden peer-checked:block"></div>
</div>
<div>
<div class="font-semibold text-gray-900">الخيار 1</div>
<div class="text-sm text-gray-600">وصف الخيار 1</div>
</div>
</label>
</div>
متغيرات الفئة الزائفة الهيكلية
الأول والأخير والفردي والزوجي
يوفر Tailwind متغيرات لتنسيق العناصر بناءً على موضعها داخل الأب:
أمثلة المتغيرات الهيكلية
<!-- قائمة مع تنسيق الأول والأخير -->
<ul class="divide-y divide-gray-200">
<li class="py-3 first:pt-0 last:pb-0">العنصر الأول</li>
<li class="py-3 first:pt-0 last:pb-0">العنصر الثاني</li>
<li class="py-3 first:pt-0 last:pb-0">العنصر الثالث</li>
<li class="py-3 first:pt-0 last:pb-0">العنصر الأخير</li>
</ul>
<!-- جدول مع ألوان صفوف فردية/زوجية -->
<table class="w-full">
<tbody>
<tr class="odd:bg-white even:bg-gray-50">
<td class="px-4 py-3">الصف 1</td>
</tr>
<tr class="odd:bg-white even:bg-gray-50">
<td class="px-4 py-3">الصف 2</td>
</tr>
<tr class="odd:bg-white even:bg-gray-50">
<td class="px-4 py-3">الصف 3</td>
</tr>
</tbody>
</table>
<!-- شبكة مع عنصر أول مختلف -->
<div class="grid grid-cols-3 gap-4">
<div class="first:col-span-3 first:row-span-2 bg-gray-200 p-4 rounded">
العنصر المميز
</div>
<div class="bg-gray-100 p-4 rounded">العنصر 2</div>
<div class="bg-gray-100 p-4 rounded">العنصر 3</div>
<div class="bg-gray-100 p-4 rounded">العنصر 4</div>
</div>
متغيرات حالة النموذج
الحالة المعطلة
ينسق معدل disabled: عناصر النموذج عندما تكون معطلة:
أمثلة الحالة المعطلة
<!-- زر معطل -->
<button
disabled
class="bg-blue-500 disabled:bg-gray-300 disabled:text-gray-500 disabled:cursor-not-allowed text-white px-4 py-2 rounded"
>
زر معطل
</button>
<!-- إدخال معطل -->
<input
type="text"
disabled
value="إدخال معطل"
class="border border-gray-300 disabled:bg-gray-100 disabled:text-gray-500 disabled:cursor-not-allowed px-4 py-2 rounded w-full"
>
<!-- معطل شرطياً -->
<button
class="bg-green-500 hover:bg-green-600 disabled:bg-gray-300 disabled:hover:bg-gray-300 disabled:cursor-not-allowed text-white px-6 py-3 rounded transition-colors"
disabled
>
إرسال
</button>
الحالة المطلوبة
ينسق معدل required: عناصر النموذج المحددة كمطلوبة:
أمثلة الحالة المطلوبة
<!-- إدخال مطلوب مع مؤشر -->
<div class="relative">
<input
type="text"
required
class="border-2 border-gray-300 required:border-blue-300 focus:border-blue-500 px-4 py-2 rounded w-full"
>
<span class="absolute right-3 top-3 text-red-500 required:block hidden">*</span>
</div>
<!-- نموذج مع حقول مطلوبة -->
<form class="space-y-4">
<div>
<label class="block text-gray-700 mb-2">
الاسم <span class="text-red-500">*</span>
</label>
<input
type="text"
required
class="border border-gray-300 required:border-l-4 required:border-l-blue-500 focus:border-blue-500 px-4 py-2 rounded w-full"
>
</div>
</form>
حالة العنصر النائب
ينسق معدل placeholder: نص العنصر النائب في حقول الإدخال:
أمثلة حالة العنصر النائب
<!-- تنسيق مخصص للعنصر النائب -->
<input
type="text"
placeholder="أدخل بريدك الإلكتروني"
class="border border-gray-300 focus:border-blue-500 placeholder:text-gray-400 placeholder:italic px-4 py-2 rounded w-full"
>
<!-- عنصر نائب مع لون مخصص -->
<input
type="search"
placeholder="بحث..."
class="bg-gray-100 placeholder:text-gray-500 px-4 py-2 rounded-full w-full"
>
<!-- منطقة نص مع عنصر نائب منسق -->
<textarea
placeholder="اكتب رسالتك هنا..."
class="border border-gray-300 placeholder:text-gray-400 placeholder:text-sm focus:border-blue-500 px-4 py-2 rounded w-full h-32"
></textarea>
حالة إدخال الملف
ينسق معدل file: زر إدخال الملف:
أمثلة إدخال الملف
<!-- إدخال ملف منسق -->
<input
type="file"
class="block w-full text-sm text-gray-500
file:mr-4 file:py-2 file:px-4
file:rounded-full file:border-0
file:text-sm file:font-semibold
file:bg-blue-50 file:text-blue-700
hover:file:bg-blue-100
file:cursor-pointer cursor-pointer"
>
<!-- رفع ملفات متعددة -->
<input
type="file"
multiple
class="block w-full text-sm text-gray-600
file:mr-4 file:py-3 file:px-6
file:rounded-lg file:border file:border-gray-300
file:text-sm file:font-medium
file:bg-white file:text-gray-700
hover:file:bg-gray-50
file:transition-colors"
>
متغيرات حالة الرابط
الحالة المزارة
ينسق معدل visited: الروابط التي تمت زيارتها:
أمثلة الحالة المزارة
<!-- روابط مع حالة مزارة -->
<a href="#page1" class="text-blue-600 visited:text-purple-600 hover:underline">
الرابط 1 (يتغير اللون عند الزيارة)
</a>
<a href="#page2" class="text-blue-600 visited:text-gray-600 visited:line-through">
الرابط 2 (يظهر كمقروء)
</a>
<!-- روابط المقالات -->
<ul class="space-y-2">
<li>
<a href="#article1" class="text-blue-600 visited:text-purple-700 visited:opacity-75 hover:underline">
المقالة 1 - مقدمة إلى Tailwind
</a>
</li>
<li>
<a href="#article2" class="text-blue-600 visited:text-purple-700 visited:opacity-75 hover:underline">
المقالة 2 - تقنيات متقدمة
</a>
</li>
</ul>
تكديس متغيرات الحالة
يمكنك دمج متغيرات حالة متعددة لإنشاء تفاعلات معقدة:
أمثلة الحالات المدمجة
<!-- زر مع جميع الحالات -->
<button class="
bg-blue-500
hover:bg-blue-600
active:bg-blue-700
focus:outline-none
focus:ring-4
focus:ring-blue-300
disabled:bg-gray-300
disabled:cursor-not-allowed
disabled:hover:bg-gray-300
text-white
font-semibold
px-6
py-3
rounded-lg
transition-all
">
زر تفاعلي
</button>
<!-- بطاقة مع حالات المجموعة والفردية -->
<div class="group relative bg-white hover:shadow-2xl transition-shadow rounded-lg overflow-hidden">
<img
src="image.jpg"
class="w-full group-hover:scale-105 transition-transform duration-300"
alt="بطاقة"
>
<div class="p-6">
<h3 class="text-xl font-bold text-gray-900 group-hover:text-blue-600 transition-colors">
عنوان البطاقة
</h3>
<p class="text-gray-600 mt-2 group-hover:text-gray-800">
نص وصف البطاقة
</p>
<button class="
mt-4
bg-blue-500
hover:bg-blue-600
active:scale-95
focus:ring-4
focus:ring-blue-300
text-white
px-4
py-2
rounded
transition-all
">
اعرف المزيد
</button>
</div>
</div>
<!-- إدخال النموذج مع حالات متعددة -->
<input
type="email"
required
placeholder="أدخل البريد الإلكتروني"
class="
w-full
border-2
border-gray-300
focus:border-blue-500
focus:ring-2
focus:ring-blue-200
invalid:border-red-500
invalid:focus:ring-red-200
disabled:bg-gray-100
disabled:cursor-not-allowed
placeholder:text-gray-400
placeholder:italic
px-4
py-3
rounded-lg
outline-none
transition-all
"
>
hover:bg-blue-600 focus:bg-blue-700 active:bg-blue-800
تمرين 1: قائمة تنقل تفاعلية
أنشئ قائمة تنقل جانبية بالميزات التالية:
- استخدم تمرير المجموعة لتسليط الضوء على العنصر بأكمله عند التمرير
- تغيير لون الأيقونة عند تمرير المجموعة
- أضف مؤشر منزلق يظهر عند التمرير
- نسق الصفحة النشطة/الحالية بشكل مختلف
- قم بتضمين حالات التركيز للتنقل بلوحة المفاتيح
تمرين 2: نموذج متقدم مع متغيرات الحالة
قم ببناء نموذج تسجيل يتضمن:
- تسميات عائمة تتحرك عندما يكون الإدخال مركزاً أو يحتوي على محتوى
- خانات اختيار مخصصة باستخدام معدلات النظير
- ألوان حدود مختلفة للحالات المطلوبة والمركزة وغير الصالحة
- زر إرسال معطل حتى يصبح النموذج صالحاً
- زر رفع الملف المنسق
تمرين 3: شبكة بطاقات المنتج
أنشئ شبكة بطاقات منتج متجاوبة حيث كل بطاقة:
- تكبر قليلاً عند التمرير مع انتقال سلس
- تظهر تراكب مع زر "عرض سريع" عند التمرير
- لها زر "أضف إلى السلة" يتغير عند التمرير والتركيز والحالات النشطة
- تعرض شارة "تخفيض" على العنصر الأول فقط
- تظهر الروابط المزارة بلون مختلف
الملخص
في هذا الدرس، تعلمت عن نظام متغيرات الحالة القوي في Tailwind:
- حالات التفاعل الأساسية: hover، focus، active، visited
- متغيرات التركيز المتقدمة: focus-within، focus-visible
- معدلات المجموعة والنظير: التنسيق بناءً على حالة الأب أو الشقيق
- المتغيرات الهيكلية: first، last، odd، even
- حالات النموذج: disabled، required، placeholder، إدخال الملف
- تكديس المتغيرات: دمج حالات متعددة للتفاعلات المعقدة
متغيرات الحالة ضرورية لإنشاء واجهات مستخدم تفاعلية وسهلة الوصول. إنها تسمح لك بإضافة سلوكيات متطورة دون كتابة CSS مخصص، مما يجعل عملية التطوير الخاصة بك أسرع وأكثر قابلية للصيانة.