مشكلات @apply والبدائل
تعرّف إلى الاستخدامات الخاطئة الشائعة لـ @apply، وافهم آثار الخصوصية، وقيّم بدائل استخراج المكوّنات مثل مكوّنات JSX.
مشكلات @apply والبدائل درس مجاني في Tailwind CSS Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Tailwind CSS Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Tailwind CSS Academy 4 دروس في المجموع.
متى يسبب @apply مشكلات
رغم أن @apply يبدو طريقة مريحة لتنظيم الأنماط، فإن الإفراط في استخدامه يسبب مجموعة من المشكلات المعروفة جيدًا. تشمل هذه المشكلات صعوبة فهم الأدوات النشطة، وفقدان المصدر الوحيد للحقيقة الخاص بأنماط المكوّنات، والمفاجآت المتعلقة بالخصوصية. يساعدكم فهم هذه العيوب على تحديد متى يكون @apply أداة مناسبة فعلًا، ومتى يوجد بديل أفضل.
المشكلة الأولى: إعادة إنشاء CSS التقليدية
أكثر إساءة استخدام شائعة لـ @apply هي استخدامه لإعادة إنشاء فئات CSS التقليدية، بحيث يمتلك كل عنصر فئة دلالية واحدة مثل .header-title ثم تُملأ هذه الفئة بالأدوات. وهذا هو النمط الذي صُمّم Tailwind للابتعاد عنه تحديدًا. وينتهي بكم الأمر إلى عيوب النهجين معًا: ملفات CSS مطوّلة، وHTML يتطلب معرفة فئات CSS الموجودة. وتصبح النتيجة أصعب في الصيانة من أي من النهجين منفردًا.
/* ANTI-PATTERN: Recreating traditional CSS with @apply */
.page-header { @apply bg-white border-b px-6 py-4; }
.page-title { @apply text-2xl font-bold text-gray-900; }
.page-meta { @apply text-sm text-gray-500 mt-1; }
.page-action { @apply ml-auto; }
/* BETTER: Just write the utilities directly in HTML -->
<header class="bg-white border-b px-6 py-4">
<h1 class="text-2xl font-bold text-gray-900">Title</h1>
<p class="text-sm text-gray-500 mt-1">Meta</p>
</header>المشكلة الثانية: فقدان سهولة اكتشاف التنويعات
عندما تُخفي فئات الأدوات المساعدة داخل قواعد @apply في ملف CSS، تصبح غير مرئية لماسح JIT ما لم يكن ملف CSS مُدرجًا في مصفوفة content. والأهم من ذلك أن المطورين الذين يقرأون HTML لاحقًا لن يتمكنوا من رؤية جميع التنسيقات للوهلة الأولى، بل سيتعين عليهم فتح ملف CSS والعثور على الفئة وتوسيع @apply ذهنيًا. وهذا يقلل من الطبيعة التوثيقية الذاتية لنهج Tailwind القائم على الأدوات المساعدة أولًا.
/* CSS: @apply hides what the component looks like */
.hero-button {
@apply px-8 py-3 bg-indigo-600 text-white rounded-full font-semibold
hover:bg-indigo-500 shadow-lg hover:shadow-indigo-500/50
transition-all duration-200;
}
<!-- HTML: developer sees only the class name, not the styles -->
<button class="hero-button">Get Started</button>
<!-- Better: developer sees everything at a glance -->
<button class="px-8 py-3 bg-indigo-600 text-white rounded-full font-semibold hover:bg-indigo-500 shadow-lg transition-all duration-200">
Get Started
</button>المأزق 3: مفاجآت الأولوية
عند استخدام @apply من دون وضع النتيجة داخل @layer components، توجد كتلة CSS المُجمَّعة في الموضع من ورقة الأنماط الذي كتبتها فيه. وقد يؤدي ذلك إلى مشكلات غير متوقعة في الأولوية، بحيث تتغلب فئة المكوّن على الأدوات المساعدة المضمّنة لأنها تظهر لاحقًا في الملف. استخدم @layer components دائمًا لضمان أن يعالج تتابع الطبقات الأولوية بطريقة متوقعة.
/* BAD: No @layer wrapper — could override utilities unexpectedly */
.btn-primary {
@apply bg-blue-600 text-white;
}
/* Later in the same file: */
/* p-4 might not override .btn-primary if placed before it */
/* GOOD: Use @layer components */
@layer components {
.btn-primary {
@apply bg-blue-600 text-white;
}
/* Now utilities always override correctly */
}المأزق 4: لا يمكن استخدام @apply مع القيم العشوائية
لا تعمل صيغة القيم العشوائية في Tailwind، أي تدوين الأقواس مثل w-[347px] أو bg-[#1a2b3c]، داخل @apply. هذا قيد أساسي؛ إذ يحل ماسح JIT القيم العشوائية عند العثور عليها في الملفات المصدرية، بينما يعمل @apply في مرحلة مختلفة. إذا كان المكوّن يحتاج إلى قيم خاصة لمرة واحدة، فيجب استخدام خصائص CSS العادية داخل القاعدة بدلًا من أدوات القيم العشوائية.
/* ERROR: Arbitrary values in @apply don't work */
.hero {
@apply w-[347px] bg-[#1a2b3c]; /* Will not compile! */
}
/* CORRECT: Use plain CSS for arbitrary values */
.hero {
@apply rounded-xl shadow-lg; /* Regular utilities work fine */
width: 347px; /* Plain CSS for the arbitrary value */
background-color: #1a2b3c; /* Plain CSS for custom color */
}البديل الحقيقي: مكوّنات JSX
في React وأطر المكوّنات الأخرى، يُعد تجريد المكوّن أفضل بديل لـ @apply. يقبل مكوّن Button خاصية variant ويعرض فئات الأدوات المساعدة الصحيحة داخليًا. تكون التنسيقات معزولة، وتكون واجهة البرمجة مكتوبة الأنواع، وتنتشر التغييرات في كل موضع يُستخدم فيه المكوّن. وهذا هو النمط الذي يوصي به فريق Tailwind لقواعد التعليمات البرمجية التي تعتمد بكثافة على المكوّنات.
// React component replaces @apply .btn-primary
const variantStyles = {
primary: 'bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500',
outline: 'border border-gray-300 text-gray-700 hover:bg-gray-50',
ghost: 'text-gray-600 hover:bg-gray-100 hover:text-gray-900',
};
export function Button({ variant = 'primary', children, ...props }) {
return (
<button
className={'inline-flex items-center px-4 py-2 rounded-lg text-sm font-medium transition-colors ' + variantStyles[variant]}
{...props}
>
{children}
</button>
);
}مكتبة clsx للفئات الشرطية
تجعل مكتبة clsx، أو بديلها classnames، تركيب الفئات الشرطي نظيفًا في JavaScript. فبدلًا من تسلسل السلاسل النصية أو القوالب النصية، مرّر كائنًا أو مصفوفة إلى clsx، وستتولى المكتبة ضم العناصر الشرطية. وهذه هي الطريقة المعتمدة لإدارة فئات الأنماط المختلفة في مكوّنات React من دون @apply.
import clsx from 'clsx';
function Button({ variant, size, fullWidth, children }) {
return (
<button className={clsx(
'inline-flex items-center justify-center rounded-lg font-medium transition-colors',
{
'px-4 py-2 text-sm': size === 'md' || !size,
'px-3 py-1.5 text-xs': size === 'sm',
'px-6 py-3 text-base': size === 'lg',
},
{
'bg-blue-600 text-white hover:bg-blue-700': variant === 'primary',
'border border-gray-300 text-gray-700 hover:bg-gray-50': variant === 'outline',
},
fullWidth && 'w-full',
)}>
{children}
</button>
);
}أجزاء قوالب HTML كبديل
في مشاريع HTML التي لا تستخدم أطرًا، مثل التطبيقات المعروضة من الخادم باستخدام قوالب Django أو Laravel أو Go، يكون النظير للمكوّن هو جزء القالب أو include. استخرج مقطع HTML المتكرر مع أدواته المساعدة إلى جزء قالب، ثم أدرجه أينما دعت الحاجة. يمنحك هذا الفائدة نفسها من تقليل التكرار التي يوفرها @apply، مع إبقاء التنسيقات في HTML حيث ينبغي أن تكون.
<!-- Jinja2 / Django example -->
<!-- templates/components/button.html -->
<button class="inline-flex items-center px-4 py-2 rounded-lg font-medium text-sm bg-blue-600 text-white hover:bg-blue-700 transition-colors" type="{{ type|default:'button' }}">
{{ label }}
</button>
<!-- Used via include -->
{% include 'components/button.html' with label='Save' type='submit' %}متى يكون @apply هو الخيار الصحيح
بعد فهم المآزق، يمكنك تحديد الحالات الفعلية التي يكون فيها @apply الأداة المناسبة. وتشمل هذه الحالات: تنسيق HTML لا يمكنك التحكم فيه، مثل Markdown المعروض أو مخرجات CMS أو HTML الخاص بمكتبة خارجية، وتوحيد عناصر النماذج في المتصفح إلى جانب إضافة النماذج، وإضافة أدوات Tailwind المساعدة إلى عناصر SVG أو canvas الخارجية. في هذه الحالات، لا يمكنك إضافة فئة إلى العنصر، لذلك يكون @apply هو الخيار الوحيد.
@layer components {
/* Styling markdown content rendered by a CMS */
.prose-content h1 { @apply text-4xl font-bold text-gray-900 mb-6 mt-8; }
.prose-content h2 { @apply text-3xl font-semibold text-gray-800 mb-4 mt-6; }
.prose-content p { @apply text-gray-600 leading-relaxed mb-4; }
.prose-content a { @apply text-blue-600 underline underline-offset-2 hover:text-blue-800; }
.prose-content ul { @apply list-disc list-inside space-y-1 mb-4 text-gray-600; }
}الإرشادات الرسمية لفريق Tailwind
يوصي فريق Tailwind CSS صراحةً بعدم استخدام @apply لتنظيم التنسيقات لمجرد أنه «يبدو أنظف». وتذكر وثائقهم: «إذا وجدت نفسك تريد استخدام @apply لتقليل التكرار في Tailwind CSS، فمن المحتمل أن عليك استخدام مكوّن.» فتجريدات المكوّنات أوضح، وأسهل في البحث، وأكثر قابلية للصيانة على نطاق واسع. ينبغي أن يكون @apply خيارًا أخيرًا، لا أول استجابة.
إعادة هيكلة @apply إلى مكوّنات
إذا كان لديك مشروع قائم يستخدم @apply بكثافة، فيمكنك الانتقال تدريجيًا إلى المكوّنات. ابدأ بفئة المكوّن الأكثر استخدامًا، وعادةً ما تكون الأزرار أو البطاقات، وأنشئ مكوّنًا مناسبًا، ثم استبدل الاستخدامات ملفًا بعد ملف. يحسّن كل استبدال أمان الأنواع، وتجميع التنسيقات مع المكوّن، وسهولة القراءة. وتكون عملية الانتقال منخفضة المخاطر لأن الناتج المرئي ينبغي أن يظل مطابقًا؛ فأنت تغيّر الآلية فقط، لا التصميم.
/* BEFORE: @apply in CSS */
@layer components {
.btn-primary { @apply bg-blue-600 text-white px-4 py-2 rounded-lg font-medium; }
}
<!-- BEFORE: HTML -->
<button class="btn-primary">Save</button>
/* AFTER: Component abstraction */
// Button.jsx
export function Button({ children }) {
return <button className="bg-blue-600 text-white px-4 py-2 rounded-lg font-medium">{children}</button>;
}
// usage
<Button>Save</Button>تحقق سريع
اختبر مدى فهمك لمآزق @apply وبدائله.
مراجعة الدرس
تعلمت في هذا الدرس أن مآزق @apply تشمل إعادة إنشاء CSS التقليدي وإخفاء التنسيقات عن قارئي HTML وعدم العمل مع القيم العشوائية، وأن البدائل الأفضل هي مكوّنات JSX مع clsx في React أو أجزاء القوالب للتطبيقات المعروضة من الخادم، وأنه ينبغي حجز @apply لـ HTML الذي لا يمكنك التحكم فيه، مثل Markdown المعروض من CMS. سنستكشف بعد ذلك أدوات الانتقال والتحريك في Tailwind.
تعلم HTML مع معلم ذكاء اصطناعي — مجانًا
اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.
- الدورات
- 30
- الدروس
- 120
الأسئلة الشائعة
هل درس «مشكلات @apply والبدائل» مجاني؟
نعم — نص درس «مشكلات @apply والبدائل» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Tailwind CSS Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Tailwind CSS Academy 4 دروس في المجموع.
ماذا ستتعلم في «مشكلات @apply والبدائل»؟
تعرّف إلى الاستخدامات الخاطئة الشائعة لـ @apply، وافهم آثار الخصوصية، وقيّم بدائل استخراج المكوّنات مثل مكوّنات JSX. تتمرن على Tailwind CSS Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Tailwind CSS Academy؟
لا تُشترط خبرة سابقة. Tailwind CSS Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «مشكلات @apply والبدائل»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Tailwind CSS Academy هذا؟
نعم. كل درس في Tailwind CSS Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- ما الذي يفعله @apply ومتى يُستخدم
- إنشاء فئات مكوّنات قابلة لإعادة الاستخدام
- تنظيم CSS المخصّص باستخدام الطبقات
- مشكلات @apply والبدائل