واجهات متجاوبة بـ Tailwind
صفحة واحدة تناسب الجوال والحاسب. ⏱ نحو 30 دقيقة.
- تطبّق مبدأ الجوال أولًا ونقاط التوقف في
Tailwind. - تبني شبكات وتخطيطات تتبدل مع الشاشة.
- تبني قائمة تنقل متجاوبة بـ
ReactوTailwind. - تراعي الاتجاه العربي والوضع الداكن وقائمة فحص التجاوب.
١الجوال أولًا
أغلب زوار المواقع اليوم من الجوال. لذلك يتبع Tailwind قاعدة الجوال أولًا Mobile first: الصنف العادي للشاشات الصغيرة، ثم تضيف بادئة لتغيّره في الشاشات الأكبر:
| البادئة | يطبّق من عرض | الجهاز تقريبًا |
|---|---|---|
| (بلا بادئة) | 0 | كل الأجهزة، والجوال أساسًا |
sm: | 640px | جوال كبير بالعرض |
md: | 768px | جهاز لوحي |
lg: | 1024px | حاسب محمول |
xl: | 1280px | شاشة كبيرة |
جرّب أزرار العرض في شريط المعاينة (📱 و ▭ و 🖥) لترى البطاقات تتراتب:
const courses = ['أطر الويب', 'أمن الويب', 'علم البيانات', 'ضمان الجودة', 'الأجهزة الذكية', 'تحليل البرمجيات']; export default function App() { return ( <div className="p-3 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3"> {courses.map(c => ( <div key={c} className="p-4 rounded-xl bg-sky-50 border border-sky-200 font-semibold text-sky-900">{c}</div> ))} </div> );}
grid-cols-1 عمود واحد للجوال، و sm:grid-cols-2 عمودان من 640 بكسل، و lg:grid-cols-3 ثلاثة من 1024 بكسل.
٢إخفاء وإظهار وتبديل الاتجاه
export default function App() { return ( <div className="p-3 space-y-3"> <div className="flex flex-col md:flex-row gap-3"> <aside className="md:w-48 p-3 rounded-lg bg-slate-100">القائمة الجانبية</aside> <main className="flex-1 p-3 rounded-lg bg-white border">المحتوى الرئيسي</main> </div> <p className="block md:hidden text-rose-700">📱 أنت على شاشة صغيرة</p> <p className="hidden md:block text-emerald-700">🖥 أنت على شاشة كبيرة</p> <h1 className="text-xl md:text-3xl font-bold">عنوان يكبر مع الشاشة</h1> </div> );}
| الحاجة | الأصناف |
|---|---|
| عمودي في الجوال، أفقي في الكبير | flex flex-col md:flex-row |
| يظهر في الجوال فقط | block md:hidden |
| يظهر في الكبير فقط | hidden md:block |
| حجم خط متدرج | text-xl md:text-3xl |
| عرض محدود في المنتصف | max-w-5xl mx-auto |
٣قائمة تنقل متجاوبة بـ React
نمط ستراه في كل موقع: في الشاشة الكبيرة روابط ظاهرة، وفي الجوال زر «☰» يفتح القائمة. Tailwind للشكل، و useState للفتح والإغلاق:
import { useState } from 'react'; const links = ['الرئيسية', 'الدورات', 'الجدول', 'تواصل']; export default function App() { const [open, setOpen] = useState(false); return ( <nav className="bg-sky-700 text-white rounded-xl p-3"> <div className="flex items-center justify-between"> <b>🎓 الكلية التقنية</b> <button className="md:hidden text-2xl" onClick={() => setOpen(!open)} aria-label="القائمة"> {open ? '✕' : '☰'} </button> <ul className="hidden md:flex gap-4"> {links.map(l => <li key={l}><a href="#" className="hover:underline">{l}</a></li>)} </ul> </div> {open && ( <ul className="md:hidden mt-3 space-y-2"> {links.map(l => <li key={l}><a href="#" className="block p-2 rounded bg-sky-800">{l}</a></li>)} </ul> )} </nav> );}
اضغط 📱 في شريط المعاينة ثم «☰».
٤الوضع الداكن والاتجاه
البادئة dark: تطبّق الصنف حين يكون الجهاز على الوضع الداكن. والبادئتان rtl: و ltr: للحالات النادرة التي تختلف حسب الاتجاه (مثل سهم يشير للأمام):
<div className="bg-white text-slate-900 dark:bg-slate-900 dark:text-slate-100"> <p>يتبع وضع الجهاز تلقائيًّا</p> <span className="inline-block rtl:rotate-180">➜</span></div>
توقّع وتحقّق
الصنف md:grid-cols-3 يطبّق:
Mobile first.عنصر يظهر في الجوال فقط:
md.flex flex-col md:flex-row تعني:
البادئة التي تتبع وضع الجهاز الداكن:
dark:الخلاصة
- بلا بادئة = الجوال، ثم
smوmdوlgوxlتعني «من هذا العرض فما فوق». grid-cols-1 sm:grid-cols-2 lg:grid-cols-3لشبكة متدرجة.flex-col md:flex-row، وblock md:hidden، وhidden md:block.- القائمة المتجاوبة: روابط ظاهرة في الكبير، وزر ☰ بحالة في الجوال.
dark: للوضع الداكن، وrtl: للحالات الخاصة بالاتجاه.
تحدٍّ برمجي: معرض منتجات متجاوب
متوسطاعرض المنتجات في شبكة تتكيف مع الشاشة.
- حاوية الشبكة
<div id="grid">: عمود واحد في الجوال، وعمودان منsm، وأربعة منlg، بفجوةgap-4. - كل منتج بطاقة
<div className="… item">بحشو p-4 وزواياrounded-lg. - عنوان
<h1>بحجمtext-xlفي الجوال و text-3xl من md.
👀 اعرض الناتج المطلوب (وجرّبه)
- الكود يعمل بلا أخطاء في Console
- الشبكة grid بفجوة 16px
- عمود واحد ثم
sm:2ثمlg:4 - البطاقات بحشو 16px وزوايا
- العنوان
text-xlثمmd:text-3xl
💡 تلميح 1
grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4💡 تلميح 2
حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.
const items = ['قهوة', 'تمر', 'عسل', 'شاي', 'هيل', 'زعفران', 'بخور', 'دلة']; export default function App() { return ( <div className="p-3"> <h1 className="text-xl md:text-3xl font-bold mb-3">منتجاتنا</h1> <div id="grid" className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4"> {items.map(i => <div key={i} className="item p-4 rounded-lg bg-amber-50 border">{i}</div>)} </div> </div> );}