إطار Tailwind CSS

توسيع السمة والقيم المخصصة

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

توسيع السمة والقيم المخصصة

في الدرس السابق، تعلمنا أساسيات ملف tailwind.config.js. الآن سنغوص بشكل أعمق في theme.extend، ونستكشف القيم الاعتباطية للتخصيصات الفردية، ونتقن التقنيات المتقدمة لإنشاء أنظمة تصميم مخصصة حقًا.

فهم كيفية توسيع سمتك بشكل صحيح أمر بالغ الأهمية لبناء مشاريع Tailwind قابلة للصيانة والتوسع تتماشى تمامًا مع متطلبات التصميم الخاصة بك.

قوة theme.extend

كائن theme.extend هو أفضل صديق لك في تخصيص Tailwind. يسمح لك بإضافة قيم جديدة إلى نظام التصميم الموجود دون فقدان أي من إعدادات Tailwind الافتراضية المصممة بعناية:

نمط التوسيع الأساسي

module.exports = {
  theme: {
    extend: {
      // كل شيء هنا يضيف إلى الافتراضيات
      colors: {
        // يضيف ألوانًا جديدة، يحتفظ بجميع الألوان الافتراضية
      },
      spacing: {
        // يضيف قيم مسافات جديدة، يحتفظ بجميع الافتراضيات
      },
    }
  }
}

غوص عميق: توسيع الألوان

دعنا نستكشف تقنيات تخصيص الألوان المتقدمة:

توسيع الألوان المتقدم

module.exports = {
  theme: {
    extend: {
      colors: {
        // قيم ألوان فردية
        'brand': '#3b82f6',
        'accent': '#f59e0b',

        // لوحة ألوان مع درجات
        primary: {
          DEFAULT: '#3b82f6',  // يستخدم عندما تكتب "bg-primary"
          50: '#eff6ff',
          100: '#dbeafe',
          200: '#bfdbfe',
          300: '#93c5fd',
          400: '#60a5fa',
          500: '#3b82f6',
          600: '#2563eb',
          700: '#1d4ed8',
          800: '#1e40af',
          900: '#1e3a8a',
          950: '#172554',
        },

        // استخدام متغيرات CSS (قوي للسمات!)
        'bg-primary': 'var(--color-bg-primary)',
        'text-primary': 'var(--color-text-primary)',

        // ألوان وظيفية
        success: {
          light: '#d1fae5',
          DEFAULT: '#10b981',
          dark: '#065f46',
        },
        warning: {
          light: '#fef3c7',
          DEFAULT: '#f59e0b',
          dark: '#92400e',
        },
        error: {
          light: '#fee2e2',
          DEFAULT: '#ef4444',
          dark: '#991b1b',
        },

        // تباينات شفافة
        'primary-alpha': {
          10: 'rgba(59, 130, 246, 0.1)',
          20: 'rgba(59, 130, 246, 0.2)',
          50: 'rgba(59, 130, 246, 0.5)',
          80: 'rgba(59, 130, 246, 0.8)',
        },
      }
    }
  }
}
نصيحة احترافية: استخدم مفتاح DEFAULT عند إنشاء لوحات الألوان. يتيح لك هذا كتابة bg-primary بدلاً من الحاجة دائمًا لتحديد درجة مثل bg-primary-500.

توسيع قيم المسافات

المسافات تستخدم بواسطة padding، margin، width، height، gap، والعديد من الأدوات الأخرى. قيم المسافات المخصصة مفيدة بشكل لا يصدق:

توسيع المسافات المتقدم

module.exports = {
  theme: {
    extend: {
      spacing: {
        // قيم تعتمد على البيكسل (محولة إلى rem)
        '18': '4.5rem',    // 72px
        '88': '22rem',     // 352px
        '100': '25rem',    // 400px
        '128': '32rem',    // 512px

        // قيم نسبية مئوية
        '1/10': '10%',
        '2/10': '20%',
        '3/10': '30%',
        '7/10': '70%',
        '9/10': '90%',

        // قيم دلالية مسماة
        'page-gutter': '1.5rem',
        'section-gap': '4rem',
        'header-height': '4rem',
        'sidebar-width': '16rem',
        'sidebar-collapsed': '4rem',
        'footer-height': '8rem',

        // قيم تعتمد على منفذ العرض
        'screen-1/2': '50vh',
        'screen-3/4': '75vh',
        'screen-full': '100vh',

        // مسافات ديناميكية (مفيدة للتصميم المتجاوب)
        'fluid-sm': 'clamp(1rem, 2vw, 2rem)',
        'fluid-md': 'clamp(2rem, 4vw, 4rem)',
        'fluid-lg': 'clamp(4rem, 8vw, 8rem)',
      }
    }
  }
}

الآن يمكنك استخدام هذه القيم في جميع أنحاء مشروعك:

استخدام المسافات المخصصة

<div class="p-section-gap m-page-gutter">
  <!-- يستخدم مسافاتك المخصصة -->
</div>

<aside class="w-sidebar-width lg:w-sidebar-collapsed">
  <!-- شريط جانبي متجاوب -->
</aside>

<section class="h-screen-3/4 py-fluid-md">
  <!-- منفذ العرض والمسافات المرنة -->
</section>

القيم الاعتباطية: التخصيصات الفردية

أحيانًا تحتاج إلى قيمة غير موجودة في ملف الإعدادات الخاص بك. بدلاً من إضافتها إلى ملف الإعدادات، يمكنك استخدام القيم الاعتباطية مع تدوين الأقواس المربعة:

بناء جملة القيم الاعتباطية

<!-- مسافات اعتباطية -->
<div class="p-[23px] m-[2.75rem]">حشوة وهامش دقيقان</div>

<!-- ألوان اعتباطية -->
<div class="bg-[#1da1f2] text-[rgb(255,107,107)]">ألوان مخصصة</div>

<!-- عرض/ارتفاع اعتباطي -->
<div class="w-[347px] h-[calc(100vh-80px)]">أبعاد دقيقة</div>

<!-- أحجام خطوط اعتباطية -->
<h1 class="text-[2.5rem] leading-[1.2]">طباعة مخصصة</h1>

<!-- حدود اعتباطية -->
<div class="border-[3px] border-[#ff6b6b]">حدود مخصصة</div>

<!-- ظلال اعتباطية -->
<div class="shadow-[0_35px_60px_-15px_rgba(0,0,0,0.3)]">ظل مخصص</div>

<!-- تدرجات اعتباطية -->
<div class="bg-gradient-to-r from-[#667eea] to-[#764ba2]">تدرج مخصص</div>
مهم: القيم الاعتباطية رائعة للحالات الفردية، ولكن إذا وجدت نفسك تستخدم نفس القيمة الاعتباطية عدة مرات، فمن الأفضل إضافتها إلى ملف الإعدادات الخاص بك للاتساق وسهولة الصيانة.

الخصائص الاعتباطية

بالإضافة إلى القيم الاعتباطية، يمكنك أيضًا استخدام الخصائص الاعتباطية لخصائص CSS التي لا تحتوي على أدوات في Tailwind:

بناء جملة الخصائص الاعتباطية

<!-- خصائص CSS مخصصة -->
<div class="[mask-image:linear-gradient(black,transparent)]">
  قناع التدرج
</div>

<!-- خصائص CSS Grid -->
<div class="[grid-template-areas:'header_header'_'sidebar_main']">
  مناطق قالب الشبكة
</div>

<!-- زخرفة النص -->
<p class="[text-decoration-style:wavy]">تسطير متموج</p>

<!-- مسار القطع -->
<div class="[clip-path:polygon(0_0,100%_0,100%_85%,0_100%)]">
  قاع مائل
</div>

<!-- متغيرات مخصصة -->
<div class="[--scroll-offset:100px] [scroll-margin-top:var(--scroll-offset)]">
  خصائص CSS المخصصة
</div>
تحذير: يجب استخدام الخصائص الاعتباطية بحذر. إنها تقلل من فوائد نظام القيود في Tailwind ويمكن أن تجعل HTML الخاص بك أصعب في الصيانة. فكر في استخدام الإضافات أو @apply بدلاً من ذلك للخصائص المطلوبة بشكل متكرر.

معدّل Important

عندما تحتاج إلى تجاوز أنماط أخرى بخصوصية عالية، استخدم معدّل ! (important):

استخدام معدّل Important

<!-- فرض الأنماط لتحصل على الأولوية -->
<div class="text-blue-500 !text-red-500">
  سيكون هذا أحمر (important يتجاوز الإعلان السابق)
</div>

<!-- تجاوز الأنماط المضمنة (عند الضرورة) -->
<div style="color: blue" class="!text-red-500">
  سيكون هذا أحمر (!important يتغلب على الأنماط المضمنة)
</div>

<!-- تجاوز أنماط مكتبات الطرف الثالث -->
<div class="library-class !bg-white !p-4">
  تجاوز إعدادات المكتبة الافتراضية
</div>

<!-- الجمع مع متجاوب و hover -->
<button class="bg-blue-500 hover:!bg-red-500 md:!bg-green-500">
  مهم عبر المتغيرات
</button>
أفضل ممارسة: استخدم ! بحذر وفقط عند الضرورة. من الأفضل إصلاح مشاكل الخصوصية من السبب الجذري بدلاً من الاعتماد على !important. الاستخدامات المشروعة الشائعة تشمل تجاوز مكتبات الطرف الثالث أو العمل مع التعليمات البرمجية القديمة.

غوص عميق في الشاشات المخصصة (نقاط التوقف)

نقاط التوقف ليست مجرد قيم بيكسل بسيطة—يمكنك إنشاء شروط استجابة معقدة:

إعدادات نقاط التوقف المتقدمة

module.exports = {
  theme: {
    extend: {
      screens: {
        // نقاط توقف min-width القياسية
        'xs': '475px',
        '3xl': '1920px',

        // نقاط توقف Max-width (desktop-first)
        'max-2xl': {'max': '1535px'},
        'max-xl': {'max': '1279px'},
        'max-lg': {'max': '1023px'},
        'max-md': {'max': '767px'},
        'max-sm': {'max': '639px'},

        // نقاط توقف بالنطاق (بين حجمين)
        'tablet': {'min': '640px', 'max': '1023px'},
        'desktop': {'min': '1024px'},

        // نقاط توقف تعتمد على الارتفاع
        'tall': {'raw': '(min-height: 800px)'},
        'short': {'raw': '(max-height: 600px)'},

        // نقاط توقف الاتجاه
        'portrait': {'raw': '(orientation: portrait)'},
        'landscape': {'raw': '(orientation: landscape)'},

        // استعلامات خاصة بالجهاز
        'touch': {'raw': '(hover: none) and (pointer: coarse)'},
        'mouse': {'raw': '(hover: hover) and (pointer: fine)'},

        // وسائط الطباعة
        'print': {'raw': 'print'},

        // تفضيل الوضع الداكن
        'dark-mode': {'raw': '(prefers-color-scheme: dark)'},

        // تفضيل الحركة المخفضة
        'reduce-motion': {'raw': '(prefers-reduced-motion: reduce)'},

        // وضع التباين العالي
        'high-contrast': {'raw': '(prefers-contrast: high)'},
      }
    }
  }
}

الآن يمكنك استخدام نقاط التوقف المتقدمة هذه في HTML الخاص بك:

استخدام نقاط التوقف المتقدمة

<!-- Desktop-first مع max-width -->
<div class="w-full max-lg:w-1/2 max-md:w-full">
  تخطيط متجاوب
</div>

<!-- أنماط خاصة بالأجهزة اللوحية فقط -->
<div class="hidden tablet:block desktop:hidden">
  مرئي فقط على الأجهزة اللوحية
</div>

<!-- خاص بالاتجاه -->
<div class="portrait:flex-col landscape:flex-row">
  التخطيط يتغير مع الاتجاه
</div>

<!-- أجهزة اللمس مقابل أجهزة الماوس -->
<button class="touch:p-4 mouse:p-2">
  أهداف لمس أكبر على الجوال
</button>

<!-- واعٍ بإمكانية الوصول -->
<div class="transition-all reduce-motion:transition-none">
  يحترم تفضيلات حركة المستخدم
</div>

الرسوم المتحركة المخصصة في الإعدادات

أنشئ رسومًا متحركة قابلة لإعادة الاستخدام مباشرة في إعداداتك:

إعداد الرسوم المتحركة المخصصة

module.exports = {
  theme: {
    extend: {
      // تحديد keyframes
      keyframes: {
        // ظهور تدريجي من الأسفل
        fadeInUp: {
          '0%': {
            opacity: '0',
            transform: 'translateY(20px)'
          },
          '100%': {
            opacity: '1',
            transform: 'translateY(0)'
          }
        },

        // انزلاق من اليمين
        slideInRight: {
          '0%': { transform: 'translateX(100%)' },
          '100%': { transform: 'translateX(0)' }
        },

        // ارتداد
        bounce: {
          '0%, 100%': {
            transform: 'translateY(-25%)',
            animationTimingFunction: 'cubic-bezier(0.8, 0, 1, 1)'
          },
          '50%': {
            transform: 'translateY(0)',
            animationTimingFunction: 'cubic-bezier(0, 0, 0.2, 1)'
          }
        },

        // هزة
        wiggle: {
          '0%, 100%': { transform: 'rotate(-3deg)' },
          '50%': { transform: 'rotate(3deg)' }
        },

        // نبض التحجيم
        pulseScale: {
          '0%, 100%': { transform: 'scale(1)' },
          '50%': { transform: 'scale(1.05)' }
        },

        // دوران بطيء
        spinSlow: {
          from: { transform: 'rotate(0deg)' },
          to: { transform: 'rotate(360deg)' }
        },
      },

      // إنشاء أدوات الرسوم المتحركة
      animation: {
        'fade-in-up': 'fadeInUp 0.6s ease-out',
        'slide-in-right': 'slideInRight 0.5s ease-out',
        'bounce': 'bounce 1s infinite',
        'wiggle': 'wiggle 1s ease-in-out infinite',
        'pulse-scale': 'pulseScale 2s ease-in-out infinite',
        'spin-slow': 'spinSlow 3s linear infinite',

        // تباينات مع تأخيرات
        'fade-in-up-delay': 'fadeInUp 0.6s ease-out 0.3s both',
      },

      // مدد رسوم متحركة مخصصة
      animationDuration: {
        '2000': '2000ms',
        '3000': '3000ms',
        '5000': '5000ms',
      },

      // تأخيرات رسوم متحركة مخصصة
      animationDelay: {
        '75': '75ms',
        '100': '100ms',
        '200': '200ms',
        '300': '300ms',
        '500': '500ms',
        '1000': '1000ms',
      }
    }
  }
}

استخدم رسومك المتحركة المخصصة في HTML:

استخدام الرسوم المتحركة المخصصة

<!-- رسم متحرك بسيط -->
<div class="animate-fade-in-up">
  يظهر تدريجيًا من الأسفل
</div>

<!-- رسم متحرك مع مشغل hover -->
<button class="hover:animate-wiggle">
  يهتز عند التحويم
</button>

<!-- رسوم متحركة متداخلة مع تأخيرات -->
<div class="animate-fade-in-up">الأول</div>
<div class="animate-fade-in-up animation-delay-100">الثاني</div>
<div class="animate-fade-in-up animation-delay-200">الثالث</div>

<!-- التحكم في المدة -->
<div class="animate-spin-slow duration-5000">
  دوران بطيء
</div>

الجمع بين التوسيعات المتعددة

إليك مثال شامل يجمع بين استراتيجيات التوسيع المتعددة:

مثال التوسيع الكامل

module.exports = {
  theme: {
    extend: {
      // ألوان مع تسمية دلالية
      colors: {
        brand: {
          primary: '#3b82f6',
          secondary: '#8b5cf6',
          accent: '#f59e0b',
        },
        ui: {
          background: '#f9fafb',
          surface: '#ffffff',
          border: '#e5e7eb',
        },
      },

      // نظام الطباعة
      fontFamily: {
        display: ['Poppins', 'sans-serif'],
        body: ['Inter', 'sans-serif'],
      },
      fontSize: {
        '2xs': ['0.625rem', { lineHeight: '0.75rem' }],
        '3xl': ['2rem', { lineHeight: '2.5rem', letterSpacing: '-0.01em' }],
      },

      // مقياس المسافات
      spacing: {
        '18': '4.5rem',
        '72': '18rem',
        '84': '21rem',
        '96': '24rem',
      },

      // نقاط توقف مخصصة
      screens: {
        'xs': '475px',
        '3xl': '1920px',
      },

      // التأثيرات
      boxShadow: {
        'soft': '0 2px 15px -3px rgba(0, 0, 0, 0.07)',
        'glow': '0 0 15px rgba(59, 130, 246, 0.5)',
      },
      borderRadius: {
        '4xl': '2rem',
      },

      // الرسوم المتحركة
      keyframes: {
        slideDown: {
          from: { height: '0', opacity: '0' },
          to: { height: 'var(--radix-accordion-content-height)', opacity: '1' },
        },
      },
      animation: {
        'slide-down': 'slideDown 300ms ease-out',
      },
    }
  }
}

تمرين تطبيقي

المهمة: وسّع سمتك لموقع تجارة إلكترونية:

  1. أضف لوحة ألوان لفئات المنتجات: إلكترونيات (أزرق)، أزياء (بنفسجي)، منزل (أخضر)، رياضة (برتقالي)
  2. أنشئ قيم مسافات مخصصة لبطاقات المنتجات: card-sm (12rem)، card-md (16rem)، card-lg (20rem)
  3. أضف نقاط توقف مخصصة: mobile (375px)، phablet (540px)
  4. حدد رسومًا متحركة لـ: تأثير hover للمنتج، نبض شارة السلة، تلاشي تحميل الصورة
  5. أنشئ قيمًا اعتباطية لشعار بأبعاد محددة: 1440x400px
  6. أضف أحجام خطوط مخصصة لـ: عنوان المنتج (1.25rem)، سعر المنتج (1.5rem بوزن bold)

ابنِ بطاقة منتج نموذجية باستخدام قيمك المخصصة.

تمرين التحدي

المهمة المتقدمة: أنشئ نظام رموز تصميم كامل:

  1. حدد نظام ألوان مع ألوان primary، secondary، success، warning، error، و info (كل منها مع متغيرات light، DEFAULT، و dark)
  2. أنشئ مقياس طباعة باستخدام نسبة "Perfect Fourth" (1.333)
  3. ابنِ مقياس مسافات بناءً على نظام الشبكة 4 نقاط (مضاعفات 0.25rem)
  4. أضف قيم مسافات دلالية: component-gap، section-gap، page-margin
  5. حدد مكتبة رسوم متحركة كاملة: fade، slide (جميع الاتجاهات)، scale، rotate، bounce
  6. أنشئ نقاط توقف متجاوبة مع قيم min و max للتحكم الدقيق
  7. أضف ظلال صناديق مخصصة لمستويات ارتفاع مختلفة (1-5)

وثق كل قرار وصدّر إعداداتك كقالب قابل لإعادة الاستخدام.

نصيحة احترافية: نظم قيمك الموسعة حسب الفئة وأضف التعليقات. مع نمو إعداداتك، تصبح المنظمة الجيدة حاسمة. فكر في تقسيم الإعدادات الكبيرة إلى ملفات متعددة ودمجها في وقت البناء.

الملخص

في هذا الدرس، أتقنت:

  • فهم عميق لـ theme.extend لإضافة قيم مخصصة
  • توسيعات الألوان، المسافات، والطباعة المتقدمة
  • القيم الاعتباطية مع بناء جملة [value] للتخصيصات الفردية
  • الخصائص الاعتباطية لخصائص CSS غير المدعومة
  • معدّل ! important ومتى يتم استخدامه
  • إعدادات نقاط توقف معقدة بما في ذلك الاتجاه، الارتفاع، واكتشاف الجهاز
  • رسوم متحركة مخصصة مع keyframes وأدوات الرسوم المتحركة
  • أفضل الممارسات لتنظيم وصيانة الإعدادات الموسعة

لديك الآن الأدوات لإنشاء أنظمة تصميم مخصصة بالكامل مع الاستفادة من إطار الأدوات القوي في Tailwind. في الدرس التالي، سنستكشف @apply واستخراج المكونات لإدارة الأنماط المعقدة والمتكررة.