إطار Tailwind CSS

أساسيات Utility-First

20 دقيقة الدرس 3 من 35

التفكير في الأدوات

Utility-First CSS يمثل تحولًا جوهريًا في كيفية تعاملنا مع تصميم الويب. بدلاً من التفكير "ما الذي يجب أن أسمي هذا المكون؟" تفكر "ما الأنماط التي يحتاجها هذا العنصر؟" دعنا نستكشف كيفية تطوير هذه العقلية Utility-First.

التحول العقلي

CSS التقليدي: "أحتاج إلى مكون بطاقة" → إنشاء فئة .card → كتابة خصائص CSS
Utility-First CSS: "أحتاج padding، خلفية بيضاء، ظل، زوايا دائرية" → تركيب الأدوات مباشرة في HTML

من التصميم إلى الأدوات

لنأخذ نمط تصميم شائع ونقسمه إلى أدوات. تخيل أنك تنظر إلى نموذج تصميم لبطاقة ملف تعريف مستخدم:

متطلبات التصميم

  • خلفية بيضاء
  • ظل خفيف للعمق
  • زوايا دائرية (8px)
  • Padding بمقدار 24px
  • عرض أقصى 384px
  • محاذاة في المنتصف على الشاشات الأكبر
  • تخطيط Flexbox للصورة الرمزية والمحتوى

نهج CSS التقليدي

CSS المكون التقليدي

<!-- HTML -->
<div class="profile-card">
    <img class="profile-card__avatar" src="avatar.jpg" alt="User">
    <div class="profile-card__content">
        <h3 class="profile-card__name">Sarah Johnson</h3>
        <p class="profile-card__title">Product Designer</p>
    </div>
</div>

<!-- CSS -->
<style>
.profile-card {
    background-color: white;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
    border-radius: 8px;
    padding: 24px;
    max-width: 384px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    gap: 16px;
}

.profile-card__avatar {
    width: 64px;
    height: 64px;
    border-radius: 50%;
}

.profile-card__content {
    flex: 1;
}

.profile-card__name {
    font-size: 18px;
    font-weight: 600;
    color: #111827;
    margin-bottom: 4px;
}

.profile-card__title {
    font-size: 14px;
    color: #6B7280;
}
</style>

نهج Utility-First

تنفيذ Utility-First

<div class="bg-white shadow-md rounded-lg p-6 max-w-sm mx-auto flex items-center gap-4">
    <img class="w-16 h-16 rounded-full" src="avatar.jpg" alt="User">
    <div class="flex-1">
        <h3 class="text-lg font-semibold text-gray-900 mb-1">Sarah Johnson</h3>
        <p class="text-sm text-gray-600">Product Designer</p>
    </div>
</div>

لاحظ كيف يتم التعبير عن كل خاصية بصرية من خلال فئة أداة. دعنا نفكك كل أداة:

تفكيك الأدوات

  • bg-white → background-color: white;
  • shadow-md → box-shadow: medium preset;
  • rounded-lg → border-radius: 0.5rem; (8px)
  • p-6 → padding: 1.5rem; (24px)
  • max-w-sm → max-width: 24rem; (384px)
  • mx-auto → margin-left: auto; margin-right: auto;
  • flex → display: flex;
  • items-center → align-items: center;
  • gap-4 → gap: 1rem; (16px)

بناء مكون كامل بالأدوات

لنبني مكونًا أكثر تعقيدًا من الصفر باستخدام الأدوات فقط. سننشئ بطاقة ميزة مع رمز وعنوان ووصف ورابط.

بطاقة الميزة - مثال كامل

<div class="max-w-md mx-auto p-8">
    <!-- بطاقة الميزة -->
    <div class="bg-white rounded-xl shadow-lg p-8 hover:shadow-2xl transition-shadow duration-300">

        <!-- حاوية الرمز -->
        <div class="w-16 h-16 bg-blue-100 rounded-lg flex items-center justify-center mb-6">
            <svg class="w-8 h-8 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                      d="M13 10V3L4 14h7v7l9-11h-7z"></path>
            </svg>
        </div>

        <!-- المحتوى -->
        <h3 class="text-2xl font-bold text-gray-900 mb-3">
            سريع كالبرق
        </h3>

        <p class="text-gray-600 leading-relaxed mb-6">
            قم ببناء ونشر مشاريعك بسرعات لا تصدق مع بنيتنا التحتية المحسنة
            والأدوات الصديقة للمطور.
        </p>

        <!-- الرابط -->
        <a href="#" class="inline-flex items-center gap-2 text-blue-600 font-semibold
                          hover:text-blue-700 transition-colors">
            اعرف المزيد
            <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                      d="M9 5l7 7-7 7"></path>
            </svg>
        </a>

    </div>
</div>

يستخدم هذا المكون أكثر من 30 فئة أداة لإنشاء بطاقة ميزة مصقولة وتفاعلية. دعنا نحلل الأنماط الرئيسية:

أدوات التخطيط

  • max-w-md - يقيد العرض لسهولة القراءة
  • mx-auto - يحاذي أفقيًا في المنتصف
  • p-8 - Padding متسق
  • flex items-center justify-center - يحاذي الرمز تمامًا

الأدوات المرئية

  • bg-white - خلفية بيضاء نظيفة
  • rounded-xl - نصف قطر حدود أكبر لمظهر حديث
  • shadow-lg - ظل بارز للعمق
  • bg-blue-100 - خلفية زرقاء فاتحة لحاوية الرمز

الأدوات التفاعلية

  • hover:shadow-2xl - يزداد الظل عند التحويم
  • transition-shadow - انتقال ظل سلس
  • duration-300 - مدة انتقال 300ms
  • hover:text-blue-700 - يصبح الرابط أغمق عند التحويم

اصطلاحات ترتيب الفئات

بينما لا يفرض Tailwind ترتيبًا محددًا، اتباع نمط متسق يحسن القراءة. هذا ترتيب موصى به:

ترتيب الفئات الموصى به

<!-- 1. التخطيط (display, position, flex/grid) -->
<!-- 2. نموذج الصندوق (width, height, padding, margin) -->
<!-- 3. الطباعة (font, خصائص النص) -->
<!-- 4. المرئي (background, border, shadow) -->
<!-- 5. التفاعلي (transitions, transforms, hover states) -->

<div class="
    flex items-center justify-between
    w-full max-w-4xl p-6 m-4
    text-lg font-semibold text-gray-900
    bg-white rounded-lg shadow-md border border-gray-200
    hover:shadow-xl transition-shadow duration-200
">
    أدوات مرتبة
</div>

إضافة Prettier لـ Tailwind

قم بتثبيت prettier-plugin-tailwindcss لترتيب فئات الأدوات تلقائيًا وفقًا للتوصيات الرسمية. يتكامل مع إعداد Prettier ويرتب الفئات عند الحفظ!

npm install -D prettier prettier-plugin-tailwindcss

دمج الأدوات بفعالية

النمط 1: اتساق التباعد

استخدم مقياس التباعد الخاص بـ Tailwind بشكل متسق لإنشاء إيقاع بصري:

تباعد متسق

<!-- سيء: قيم تباعد عشوائية -->
<div class="p-[13px] mb-[22px]">
    <h2 class="mb-[9px]">العنوان</h2>
    <p class="mb-[15px]">الفقرة</p>
</div>

<!-- جيد: مقياس التباعد (4, 6, 8, إلخ.) -->
<div class="p-6 mb-8">
    <h2 class="mb-4">العنوان</h2>
    <p class="mb-6">الفقرة</p>
</div>

النمط 2: اتساق اللون

التزم بظلال لون متسقة للعناصر المرتبطة:

لوحة ألوان متسقة

<div class="bg-white border border-gray-200">
    <h3 class="text-gray-900">عنوان أساسي</h3>
    <p class="text-gray-700">نص ثانوي</p>
    <span class="text-gray-500">معلومات ثالثية</span>
    <button class="bg-blue-600 hover:bg-blue-700 text-white">إجراء</button>
</div>

النمط 3: محددات متجاوبة

طبق متغيرات responsive بشكل منهجي:

تصميم متجاوب Mobile-First

<!-- تكديس على الموبايل، جنبًا إلى جنب على التابلت+ -->
<div class="flex flex-col md:flex-row gap-4">
    <div class="w-full md:w-1/2">العمود 1</div>
    <div class="w-full md:w-1/2">العمود 2</div>
</div>

<!-- نص صغير على الموبايل، أكبر على الديسكتوب -->
<h1 class="text-2xl md:text-4xl lg:text-5xl font-bold">
    عنوان متجاوب
</h1>

<!-- إخفاء على الموبايل، إظهار على التابلت+ -->
<aside class="hidden md:block md:w-64 lg:w-80">
    محتوى الشريط الجانبي
</aside>

عندما تصبح سمات class طويلة

بينما تقوم بتركيب المزيد من الأدوات، يمكن أن تصبح سمات class طويلة. إليك استراتيجيات لإدارة هذا:

الاستراتيجية 1: تنسيق متعدد الأسطر

تقسيم الفئات الطويلة إلى أسطر متعددة

<button class="
    px-6 py-3
    bg-gradient-to-r from-blue-600 to-purple-600
    text-white font-semibold
    rounded-lg shadow-lg
    hover:from-blue-700 hover:to-purple-700
    focus:outline-none focus:ring-4 focus:ring-purple-300
    transform hover:scale-105
    transition-all duration-200
">
    زر متدرج
</button>

الاستراتيجية 2: الاستخراج إلى المكونات (مثال React)

استخراج مكون React

// Button.jsx
export function Button({ children, variant = 'primary' }) {
    const baseClasses = "px-6 py-3 font-semibold rounded-lg transition-all duration-200";
    const variants = {
        primary: "bg-blue-600 hover:bg-blue-700 text-white",
        secondary: "bg-gray-200 hover:bg-gray-300 text-gray-900",
        danger: "bg-red-600 hover:bg-red-700 text-white"
    };

    return (
        <button className={`${baseClasses} ${variants[variant]}`}>
            {children}
        </button>
    );
}

// الاستخدام
<Button variant="primary">انقر هنا</Button>

الاستراتيجية 3: توجيه @apply

استخراج الأنماط المتكررة بـ @apply

/* styles.css */
@layer components {
    .btn {
        @apply px-6 py-3 font-semibold rounded-lg transition-all duration-200;
    }

    .btn-primary {
        @apply bg-blue-600 hover:bg-blue-700 text-white;
    }

    .btn-secondary {
        @apply bg-gray-200 hover:bg-gray-300 text-gray-900;
    }
}

<!-- HTML -->
<button class="btn btn-primary">انقر هنا</button>

استخدم @apply بحذر

يجب استخدام توجيه @apply بحذر. الإفراط في استخدامه يهزم الغرض من Utility-First CSS. استخرج إلى المكونات (React، Vue) أولاً، واستخدم @apply فقط للأنماط المتكررة حقًا التي لا يمكن جعلها مكونات.

Utility-First مقابل BEM والنهج التقليدية

مقارنة المنهجيات

لنبني نفس مكون البطاقة باستخدام منهجيات CSS مختلفة لفهم المقايضات:

BEM (Block Element Modifier)

<!-- HTML -->
<div class="card card--featured">
    <img class="card__image" src="product.jpg">
    <div class="card__content">
        <h3 class="card__title">اسم المنتج</h3>
        <p class="card__price card__price--sale">$49.99</p>
    </div>
</div>

<!-- CSS -->
<style>
.card {
    background: white;
    border-radius: 8px;
    overflow: hidden;
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

.card--featured {
    border: 2px solid gold;
}

.card__image {
    width: 100%;
    height: 200px;
    object-fit: cover;
}

.card__content {
    padding: 16px;
}

.card__title {
    font-size: 20px;
    font-weight: 600;
    margin-bottom: 8px;
}

.card__price {
    font-size: 18px;
    color: #666;
}

.card__price--sale {
    color: #e53e3e;
    font-weight: bold;
}
</style>

Utility-First (Tailwind)

<div class="bg-white rounded-lg overflow-hidden shadow-md border-2 border-yellow-500">
    <img class="w-full h-48 object-cover" src="product.jpg">
    <div class="p-4">
        <h3 class="text-xl font-semibold mb-2">اسم المنتج</h3>
        <p class="text-lg text-red-600 font-bold">$49.99</p>
    </div>
</div>

تحليل المقارنة

الجانب BEM Utility-First
طول HTML أسماء فئات أقصر فئات أكثر، سمات أطول
ملف CSS CSS مخصص مطلوب لا حاجة لـ CSS مخصص
الصيانة تحديث ملف CSS بشكل منفصل التغييرات موضعية في HTML
إعادة الاستخدام إعادة استخدام الفئات الدلالية إعادة استخدام تركيبات الأدوات
منحنى التعلم تعلم منهجية BEM تعلم أسماء فئات الأدوات
المرونة محدود بالفئات المحددة مسبقًا تركيبات مرنة بشكل لا نهائي

مثال واقعي: بناء نموذج النشرة الإخبارية

لنطبق مبادئ Utility-First لبناء نموذج اشتراك نشرة إخبارية كامل وجاهز للإنتاج:

نموذج النشرة الإخبارية - التنفيذ الكامل

<div class="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100 flex items-center justify-center p-4">

    <div class="w-full max-w-md">

        <!-- حاوية البطاقة -->
        <div class="bg-white rounded-2xl shadow-2xl p-8">

            <!-- الرأس -->
            <div class="text-center mb-8">
                <div class="inline-flex items-center justify-center w-16 h-16 bg-blue-100 rounded-full mb-4">
                    <svg class="w-8 h-8 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                              d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path>
                    </svg>
                </div>

                <h2 class="text-3xl font-bold text-gray-900 mb-2">
                    ابق على اطلاع
                </h2>

                <p class="text-gray-600">
                    اشترك في نشرتنا الإخبارية للحصول على أحدث التحديثات والعروض الحصرية.
                </p>
            </div>

            <!-- النموذج -->
            <form class="space-y-4">

                <!-- إدخال الاسم -->
                <div>
                    <label for="name" class="block text-sm font-medium text-gray-700 mb-2">
                        الاسم الكامل
                    </label>
                    <input
                        type="text"
                        id="name"
                        class="w-full px-4 py-3 border border-gray-300 rounded-lg
                               focus:ring-2 focus:ring-blue-500 focus:border-transparent
                               outline-none transition-all"
                        placeholder="أحمد محمد"
                    >
                </div>

                <!-- إدخال البريد الإلكتروني -->
                <div>
                    <label for="email" class="block text-sm font-medium text-gray-700 mb-2">
                        عنوان البريد الإلكتروني
                    </label>
                    <input
                        type="email"
                        id="email"
                        class="w-full px-4 py-3 border border-gray-300 rounded-lg
                               focus:ring-2 focus:ring-blue-500 focus:border-transparent
                               outline-none transition-all"
                        placeholder="ahmad@example.com"
                    >
                </div>

                <!-- خانة الاختيار -->
                <div class="flex items-start gap-3">
                    <input
                        type="checkbox"
                        id="terms"
                        class="mt-1 w-4 h-4 text-blue-600 border-gray-300 rounded
                               focus:ring-2 focus:ring-blue-500"
                    >
                    <label for="terms" class="text-sm text-gray-600">
                        أوافق على تلقي رسائل البريد الإلكتروني التسويقية وأقبل
                        <a href="#" class="text-blue-600 hover:text-blue-700 underline">
                            شروط الخدمة
                        </a>
                    </label>
                </div>

                <!-- زر الإرسال -->
                <button
                    type="submit"
                    class="w-full py-3 px-6 bg-blue-600 hover:bg-blue-700
                           text-white font-semibold rounded-lg shadow-lg
                           hover:shadow-xl transform hover:-translate-y-0.5
                           active:translate-y-0 transition-all duration-200">
                    اشترك الآن
                </button>

            </form>

            <!-- التذييل -->
            <p class="text-center text-xs text-gray-500 mt-6">
                نحن نحترم خصوصيتك. إلغاء الاشتراك في أي وقت.
            </p>

        </div>

    </div>

</div>

يوضح هذا النموذج عدة أنماط Utility-First متقدمة:

  • خلفيات متدرجة: bg-gradient-to-br from-blue-50 to-indigo-100
  • حالات التركيز: focus:ring-2 focus:ring-blue-500
  • انتقالات سلسة: transition-all duration-200
  • تأثيرات التحويم: hover:-translate-y-0.5 (رفع خفيف)
  • تباعد متسق: space-y-4 للإيقاع الرأسي

تمرين عملي 1: مكون البطاقة

قم ببناء بطاقة منشور مدونة بالأدوات فقط. المتطلبات:

  • صورة مميزة في الأعلى (عرض كامل، ارتفاع ثابت)
  • شارة الفئة (صغيرة، ملونة)
  • عنوان ومقتطف
  • معلومات المؤلف مع الصورة الرمزية
  • وقت القراءة وتاريخ النشر
  • تأثير التحويم (ينمو الظل)

تمرين عملي 2: التنقل المتجاوب

أنشئ شريط تنقل متجاوب باستخدام الأدوات:

  • الشعار على اليسار، القائمة على اليمين
  • قائمة الهامبرغر على الموبايل (مخفية على الديسكتوب)
  • قائمة كاملة على الديسكتوب (مخفية على الموبايل)
  • تحديد موضع ثابت
  • تأثير ضبابية الخلفية
  • حالة نشطة للصفحة الحالية

تمرين عملي 3: إعادة بناء CSS التقليدي

خذ مكونًا قمت ببنائه بـ CSS التقليدي وأعد بناءه باستخدام الأدوات:

  1. حدد جميع خصائص CSS
  2. ابحث عن أدوات Tailwind المكافئة
  3. قم بتركيب الأدوات في HTML
  4. قارن أسطر الكود وقابلية الصيانة
  5. اختبر إجراء التغييرات (أيهما أسرع؟)

الملخص

في هذا الدرس، تعلمنا كيفية التفكير في الأدوات وتطبيق مبادئ Utility-First على المكونات الواقعية:

  • التحول العقلي: فكر من حيث الأنماط المطلوبة، وليس أسماء المكونات
  • التركيب: بناء تصميمات معقدة من خلال دمج أدوات بسيطة
  • الاتساق: استخدام مقاييس التباعد ولوحات الألوان بشكل منهجي
  • التنظيم: اتباع اصطلاحات ترتيب الفئات لسهولة القراءة
  • الفئات الطويلة: الإدارة بالتنسيق متعدد الأسطر، استخراج المكونات، أو @apply
  • المقارنة: Utility-First يوفر مرونة أكثر من BEM أو CSS التقليدي

النقاط الرئيسية:

  • كل فئة أداة تتوافق مباشرة مع خصائص CSS
  • قم بتركيب الأدوات لبناء أي تصميم دون CSS مخصص
  • الاتساق ينبثق من استخدام مجموعات أدوات مقيدة
  • الحالات المتجاوبة والتفاعلية هي مواطنون من الدرجة الأولى
  • استخراج المكونات يحدث بشكل طبيعي عندما تتكرر الأنماط

الآن بعد أن فهمت أساسيات Utility-First، أنت مستعد للغوص بشكل أعمق في فئات الأدوات المحددة. في الدرس التالي، سنستكشف نظام الألوان الخاص بـ Tailwind وأدوات الخلفية بالتفصيل.