توسعه فرانت‌اند

Tailwind CSS: نکات و ترفندهای پیشرفته

راهنمای Tailwind 4 با تشخیص کلاس، Theme Variables، Group و Peer، انتخاب Arbitrary Value و نمونه کامل HTML و CSS همراه نصب CLI.

1404/11/02 3 دقیقه مطالعه 2,528 بازدید

تکنیک پیشرفته Tailwind CSS باید یک مسئله نگهداری یا رفتار رابط را حل کند. طولانی شدن classها، تغییر رنگ بر اساس وضعیت، هماهنگی Tokenها و تشخیص کلاس در Build از مسئله‌های رایج‌اند. اضافه کردن Arbitrary Value و Variant برای هر جزء، به تنهایی معماری بهتری نمی‌سازد. ابتدا قرارداد جزء و حالت‌های آن را مشخص کنید؛ سپس تصمیم بگیرید چه چیزی با Utility، چه چیزی با CSS معمول و چه چیزی با یک Component مشترک بیان شود.

این آموزش بر روش Tailwind نسخه ۴ تمرکز دارد. متن‌هایی که PurgeCSS، فعال‌کردن جداگانه JIT و tailwind.config را بدون تعیین نسخه کنار هم می‌گذارند، مسیرهای نسل‌های مختلف را مخلوط می‌کنند. پیش از کپی نمونه، نسخه پروژه و روش Build را ببینید. مهاجرت هم فقط تغییر شماره package نیست؛ نام بعضی Utilityها، تنظیمات و حد پشتیبانی مرورگر می‌تواند عوض شود. ادعای افزایش سه‌برابری سرعت توسعه برای همه تیم‌ها نیز معیار مستندی ندارد و از این راهنما حذف شده است.

تشخیص کلاس، اجرای منطق برنامه نیست

در مستندات تشخیص کلاس، فایل‌ها به صورت متن بررسی می‌شوند. Tailwind منطق JavaScript یا template را اجرا نمی‌کند تا نام نهایی کلاس را حدس بزند. ساختن رشته‌ای از بخش نام رنگ و بخش عدد ممکن است کلاسی تولید کند که در منبع به صورت کامل وجود ندارد. برای وضعیت‌های محدود، نگاشت از وضعیت به رشته کامل کلاس بنویسید. انتخاب در Runtime انجام می‌شود، اما نام همه کلاس‌های ممکن برای Build قابل مشاهده می‌ماند.

اگر مقدار از داده بیرونی می‌آید، فهرست مجاز را مشخص کنید. هر رشته دلخواه کاربر نباید به نام کلاس تبدیل شود. برای مقدار پیوسته مانند عرض محاسبه‌شده، CSS Variable همراه Utility ثابت می‌تواند قرارداد روشن‌تری بدهد. این روش هم نیازمند کنترل دامنه مقدار است. مشکل را با اضافه کردن بی‌حد همه رنگ‌ها به خروجی پنهان نکنید؛ آن کار اندازه CSS و سطح نگهداری را بالا می‌برد و تعریف وضعیت محصول را روشن‌تر نمی‌کند.

Tokenها را با نقش و تکرار تعریف کنید

Theme Variables در نسخه ۴ برای تعریف Tokenهایی به کار می‌روند که با Utilityها مرتبط‌اند. در نمونه، color-brand باعث دسترسی به کلاس‌هایی مانند text-brand و bg-brand می‌شود. یک Custom Property معمولی الزاماً همان نقش Theme را ندارد. Tokenی تعریف کنید که استفاده مشترک و معنای مشخص دارد؛ تبدیل هر مقدار اتفاقی به نام مشترک، فهرست بزرگی می‌سازد که تشخیص تفاوت‌هایش برای تیم دشوار است.

نام رنگ برند برای هویت مفید است، اما رنگ‌های معنایی هم لازم‌اند. Error و Success با Brand یک مفهوم نیستند. فاصله، Radius و Typography را با نقش جزء هماهنگ کنید و ترکیب‌های مجاز را مستند نگه دارید. اگر دو کارت واقعاً رفتار متفاوت دارند، یکسان کردن همه جزئیات آن‌ها به اسم ثبات می‌تواند اطلاعات را مخفی کند. مقاله Atomic Design برای رابطه Token، جزء و صفحه زمینه مناسبی دارد؛ اشتراک باید از نیاز مشترک بیاید.

Group و Peer به ساختار وابسته‌اند

Group وقتی مفید است که حالت یک والد روی فرزند اثر می‌گذارد؛ مثلاً Hover روی کارت رنگ عنوان را تغییر می‌دهد. Peer برای واکنش یک عنصر به حالت sibling پیشین کاربرد دارد. این‌ها صرفاً اسم‌های کوتاه برای هر رابطه دلخواه DOM نیستند. راهنمای حالت‌ها و Variantها رابطه و کاربرد آن‌ها را توضیح می‌دهد. اگر عنصر هدف در ساختار دیگری قرار گرفت، همان کلاس قبلی ممکن است دیگر رفتار مورد نظر را ایجاد نکند.

برای رفتار مهم، حالت صفحه‌کلید را همراه Hover ببینید. تغییر عنوان کارت فقط روی Hover نباید تنها نشانه تعامل باشد. لینک واقعی، نام روشن و Focus قابل مشاهده لازم‌اند. Peer-invalid می‌تواند پیام را به وضعیت فیلد وصل کند، اما نمایش خطا از لحظه بارگذاری ممکن است نامناسب باشد. زمان اعتبارسنجی تصمیم محصول است و از انتخاب Variant به دست نمی‌آید. همچنین رنگ خطا باید با متن و رابطه قابل دسترس همراه باشد؛ Utility نقش Label یا پیام خطای مرتبط را جایگزین نمی‌کند.

نمونه کامل نسخه ۴ با CLI

یک پوشه آموزشی جدا بسازید و سه بخش زیر را با نام‌های ذکرشده نگه دارید. Node.js و npm پیش‌نیاز این مسیر هستند. فرمان‌ها را داخل همان پوشه اجرا کنید؛ نصب اولیه به دریافت package از شبکه نیاز دارد. نمونه شامل index.html و input.css است و خروجی Build با نام output.css کنار آن‌ها نوشته می‌شود. راهنمای رسمی CLI از package جداگانه @tailwindcss/cli استفاده می‌کند. در این آموزش هیچ CDN یا فایل تصویری خارجی لازم نیست.

npm init -y
npm install --save-dev tailwindcss@4 @tailwindcss/cli@4
npx @tailwindcss/cli -i ./input.css -o ./output.css --watch

محتوای بخش زیر را در input.css قرار دهید. source(none) تشخیص خودکار را برای همین نمونه غیرفعال می‌کند و @source فایل HTML مشخص را معرفی می‌کند. بنابراین نتیجه به فایل‌های نامرتبط پوشه وابسته نیست. اگر در پروژه واقعی فایل‌های بیشتری دارید، مسیرهای آن‌ها را با ساختار همان پروژه تعریف کنید. مسیر @source نسبت به stylesheet تفسیر می‌شود؛ تغییر محل فایل بدون اصلاح مسیر ممکن است باعث تولید نشدن کلاس‌ها شود.

@import "tailwindcss" source(none);
@source "./index.html";
@theme {
  --color-brand: #123b55;
  --font-sans: Tahoma, sans-serif;
}

این بخش را در index.html ذخیره کنید. پس از اجرای Build، فایل را در مرورگر باز کنید. صفحه سه کارت آموزشی دارد؛ در عرض کوچک یک ستون و در breakpoint متوسط سه ستون نمایش داده می‌شود. عنوان کارت به Hover و Focus داخل همان کارت واکنش نشان می‌دهد. در بخش درخواست، Checkbox پیش از متن راهنما آمده و peer-checked پیام را نمایش می‌دهد. این Checkbox صرفاً نمونه رابطه sibling است و هیچ درخواست یا رضایت واقعی به سرور ارسال نمی‌کند.

<!doctype html>
<html lang="fa" dir="rtl">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>نمونه Tailwind 4</title><link rel="stylesheet" href="./output.css"></head>
<body class="bg-white p-6 font-sans leading-8 text-black">
<main class="mx-auto max-w-[72rem]">
<h1 class="mb-6 text-2xl font-bold">مسیرهای آموزشی</h1>
<section aria-label="سه مسیر آموزشی" class="grid grid-cols-1 gap-6 md:grid-cols-3">
<article class="group rounded-lg border-2 border-black p-6"><h2 class="text-xl font-bold group-hover:text-brand group-focus-within:text-brand">ساختار</h2><p>رابطه Container و آیتم را مشخص کنید.</p><a href="#request" class="underline focus-visible:outline-2 focus-visible:outline-offset-4">بررسی مسیر ساختار</a></article>
<article class="group rounded-lg border-2 border-black p-6"><h2 class="text-xl font-bold group-hover:text-brand group-focus-within:text-brand">حالت‌ها</h2><p>Hover و Focus را همراه هم طراحی کنید.</p><a href="#request" class="underline focus-visible:outline-2 focus-visible:outline-offset-4">بررسی مسیر حالت‌ها</a></article>
<article class="group rounded-lg border-2 border-black p-6"><h2 class="text-xl font-bold group-hover:text-brand group-focus-within:text-brand">Token</h2><p>مقدار مشترک را با نقش روشن تعریف کنید.</p><a href="#request" class="underline focus-visible:outline-2 focus-visible:outline-offset-4">بررسی مسیر Token</a></article>
</section>
<section id="request" aria-labelledby="request-title" class="mt-8 rounded-lg border-2 border-black p-6">
<h2 id="request-title" class="mb-4 text-xl font-bold">نمونه Peer</h2>
<input id="show-note" type="checkbox" class="peer me-2 size-5 accent-brand focus-visible:outline-2 focus-visible:outline-offset-4">
<label for="show-note">توضیح نمونه را نمایش بده</label>
<p class="mt-4 hidden peer-checked:block">این نمونه محلی است؛ داده‌ای ذخیره یا ارسال نمی‌شود.</p>
</section>
</main></body></html>

در حالت --watch، تغییر فایل منبع باعث ساخت دوباره CSS می‌شود و فرایند تا توقف شما فعال می‌ماند. برای خروجی یک‌باره می‌توانید --watch را حذف کنید؛ برای خروجی کوچک‌تر، گزینه --minify را در همان فرمان Build به کار ببرید. فرمان تولید CSS و باز کردن HTML دو کار جدا هستند؛ فایل index بدون output ساخته‌شده، ظاهر نمونه را ندارد. نام فایل‌ها و لینک stylesheet باید یکسان بمانند. روش ارائه‌شده برای پروژه آموزشی است و تنظیم Build یک برنامه موجود را نباید بی‌بررسی جایگزین کند.

Arbitrary Value را با دلیل انتخاب کنید

Arbitrary Value برای مقداری مفید است که در مقیاس موجود مناسبش پیدا نمی‌شود؛ مثل محدودیت عرض خاص یک بخش. اگر همان مقدار در چند جزء تکرار شد، درباره Token مشترک فکر کنید. فهرست بزرگی از اندازه‌های تقریباً مشابه می‌تواند طراحی را از مقیاس منسجم دور کند. عبارت calc نیز باید Syntax معتبر CSS داشته باشد؛ فاصله در نام کلاس با روش مناسب نمایش داده شود. کوتاه بودن یک رشته کلاس، صحت محاسبه یا تناسب آن با محتوا را تضمین نمی‌کند.

برای Responsive، کلاس پایه را وضعیت کوچک در نظر بگیرید و تغییر در breakpoint را آگاهانه اضافه کنید. سه ستون در نمونه تصمیم همان صفحه است، نه قاعده همه کارت‌ها. مقاله Grid و Flexbox درباره تفاوت محور و نیاز چیدمان توضیح دارد. کلاس order هم ترتیب بصری را تغییر می‌دهد و لزوماً ترتیب خواندن را تغییر نمی‌دهد؛ از آن برای پنهان کردن مشکل ساختار محتوا استفاده نکنید. HTML باید بدون ظاهر پیچیده هم ترتیب منطقی داشته باشد.

استخراج Component با استخراج CSS یکسان نیست

اگر چند کارت ساختار و رفتار مشترک دارند، Component می‌تواند تکرار markup و حالت‌ها را مدیریت کند. @apply فقط ترکیب Style را بیان می‌کند و ساختار یا رفتار را به اشتراک نمی‌گذارد. انتخاب آن برای همه کلاس‌ها ممکن است مزیت دیدن رابطه Utility و عنصر را کاهش دهد. از طرف دیگر، تکرار بسیار زیاد یک ترکیب هم نیازمند قرارداد مشترک است. راه‌حل را بر اساس چیزی که تکرار می‌شود انتخاب کنید: مقدار، ظاهر، markup یا رفتار.

در Componentهای پویا، Props را به حالت‌های محدود نگاشت کنید. نام کامل کلاس‌ها در منبع بماند و ترکیب ناسازگار مشخص شود. ترتیب رشته کلاس‌ها به تنهایی روش مطمئن حل همه تعارض‌های CSS نیست؛ خروجی Cascade و قواعد تولیدشده اهمیت دارند. دو Utility متضاد را بدون دلیل کنار هم نگه ندارید. مرور قرارداد جزء باید روشن کند کدام حالت مجاز است و کدام کلاس پایه همیشه وجود دارد. این کار برای تیم از حفظ کردن فهرست ترفندها مفیدتر است.

مهاجرت و تحویل را با نسخه هماهنگ کنید

راهنمای ارتقای رسمی برای نسخه ۴ مرورگرهای مدرن و تغییرات نسبت به نسخه ۳ را مشخص می‌کند؛ در راهنما Safari 16.4، Chrome 111 و Firefox 128 حدهای پایه ذکر شده‌اند. نیاز مخاطب به مرورگر قدیمی می‌تواند تصمیم نسخه را تغییر دهد. در پروژه مهاجرتی، تغییر Border، Ring، Shadow و Outline را هم مرور کنید؛ یک Build موفق نشان نمی‌دهد ظاهر و Focus دقیقاً همان رفتار قبلی را حفظ کرده‌اند.

در تحویل، نسخه packageها، مسیرهای منبع، Tokenهای مشترک و Variantهای مهم را ثبت کنید. تغییر فایل‌های خارج از منبع تعریف‌شده ممکن است در خروجی دیده نشود؛ این محدودیت باید برای همکار بعدی معلوم باشد. مقاله Color Contrast برای بازبینی رنگ و Focus مفید است. نقطه شروع مناسب، یک جزء واقعی با حالت‌های مشخص است: آن را با قرارداد روشن بسازید، تکرارهای واقعی را استخراج کنید و تنها تکنیکی را اضافه کنید که مشکل مشخصی از همان جزء را حل می‌کند.

واکنش به این مقاله

اشتراک‌گذاری این مقاله:
دیدگاه‌ها 0
۰ / ۲۰۰۰

هنوز دیدگاهی ثبت نشده

اولین نفری باشید که نظر می‌دهد!