مقالات › CSS و طراحی وب

آموزش Tailwind CSS؛ استایل‌دهی Utility-First برای اپلیکیشن‌های React

آموزش Tailwind CSS نسخه‌ی ۴: رویکرد Utility-First، طراحی ریسپانسیو، توکن‌های تم، حالت تاریک، راست‌چین برای سایت فارسی و کامپوننت‌سازی در React.

Tailwind CSS روش استایل‌نویسی بسیاری از تیم‌ها را تغییر داد. به‌جای اختراع نام کلاس و جابه‌جایی بین فایل‌های JSX و CSS، کلاس‌های کوچک کاربردی (Utility) را مستقیم در Markup ترکیب می‌کنید. در ابتدا class="flex items-center gap-3 rounded-xl bg-white p-4 shadow" شلوغ به نظر می‌رسد؛ اما بعد از یک هفته، بیشتر توسعه‌دهندگان می‌بینند رابط کاربری را سریع‌تر می‌سازند و CSS پروژه دیگر بی‌پایان بزرگ نمی‌شود. این راهنما Tailwind نسخه‌ی ۴ را در یک پروژه‌ی React + Vite پوشش می‌دهد.

ایده‌ی Utility-First

CSS سنتی:

<div class="card">...</div>
<style>
.card { display: flex; align-items: center; gap: .75rem; padding: 1rem; border-radius: .75rem; background: white; }
</style>

Tailwind:

<div class="flex items-center gap-3 rounded-xl bg-white p-4">...</div>

مزایا:

  • بدون نام‌گذاری — دیگر خبری از .card-inner-wrapper-2 نیست.
  • محدودیت‌های طراحی — فاصله‌ها، رنگ‌ها و اندازه‌ها از یک مقیاس مشترک می‌آیند و رابط کاربری یکدست می‌ماند.
  • CSS بزرگ نمی‌شود — همان Utilityها دوباره استفاده می‌شوند و موارد استفاده‌نشده اصلاً تولید نمی‌شوند.
  • استدلال محلی — تغییر یک کلاس فقط همان عنصر را تغییر می‌دهد؛ ترسی از خراب شدن صفحات دیگر نیست.

راه‌اندازی با Vite (نسخه‌ی ۴)

npm install tailwindcss @tailwindcss/vite
// vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";

export default defineConfig({ plugins: [react(), tailwindcss()] });
/* src/index.css */
@import "tailwindcss";

همین. Tailwind 4 فایل‌های سورس را خودکار اسکن می‌کند؛ نه آرایه‌ی content لازم است و نه tailwind.config.js.

موارد اصلی

کاربرد نمونه‌ها
چیدمان flex، grid، grid-cols-3، items-center، justify-between، gap-4
فاصله p-4، px-6، mt-2، space-y-3
اندازه w-full، max-w-3xl، h-12، size-10
تایپوگرافی text-sm، text-2xl، font-semibold، leading-relaxed، text-gray-600
پس‌زمینه و حاشیه bg-white، bg-violet-600، border، rounded-xl، ring-1
افکت‌ها shadow-lg، opacity-80، blur-sm، transition، duration-200

مقادیر دلخواه (Arbitrary) موارد خاص را پوشش می‌دهند: top-[72px]، bg-[#13121f]، grid-cols-[200px_1fr].

طراحی ریسپانسیو

Tailwind موبایل‌اول است: کلاس‌های بدون پیشوند همه‌جا اعمال می‌شوند و کلاس‌های پیشونددار از یک نقطه‌ی شکست به بالا.

<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
  {projects.map((p) => <ProjectCard key={p.id} project={p} />)}
</div>

نقاط شکست پیش‌فرض: sm برابر 40rem، md برابر 48rem، lg برابر 64rem، xl برابر 80rem و 2xl برابر 96rem. نسخه‌ی ۴ از Container Query هم به‌صورت پیش‌فرض پشتیبانی می‌کند: @container روی والد و @md:flex-row روی فرزندان.

حالت‌ها (State Variants)

<button className="rounded-lg bg-violet-600 px-4 py-2 font-medium text-white
                   hover:bg-violet-700 focus-visible:outline-2 focus-visible:outline-offset-2
                   active:scale-95 disabled:cursor-not-allowed disabled:opacity-50">
  ذخیره
</button>

موارد پرکاربرد دیگر: group-hover: (استایل فرزند وقتی والد Hover شده)، peer-invalid: (واکنش به یک Input هم‌سطح)، first:، last:، odd:، aria-expanded: و data-[state=open]:.

<a className="group flex items-center gap-2">
  ادامه‌ی مطلب
  <ArrowIcon className="transition group-hover:-translate-x-1" />
</a>

توکن‌های تم با @theme

در نسخه‌ی ۴ تم در خود CSS تعریف می‌شود. تعریف یک توکن Utilityهای مربوط را خودکار می‌سازد:

@import "tailwindcss";

@theme {
  --color-brand-50: #f5f3ff;
  --color-brand-500: #8b5cf6;
  --color-brand-700: #6d28d9;
  --font-display: "Sora Variable", sans-serif;
  --font-fa: "Vazirmatn Variable", sans-serif;
  --radius-card: 1.25rem;
}

حالا bg-brand-500، text-brand-700، font-fa و rounded-card همه‌جا کار می‌کنند؛ و مقادیر، متغیرهای واقعی CSS هم هستند که در CSS سفارشی قابل استفاده‌اند: var(--color-brand-500).

حالت تاریک

به‌طور پیش‌فرض dark: از تنظیم سیستم‌عامل (prefers-color-scheme) پیروی می‌کند. برای سوئیچ دستی، Variant را با یک کلاس بازتعریف کنید:

@custom-variant dark (&:where(.dark, .dark *));
<div className="bg-white text-gray-900 dark:bg-gray-950 dark:text-gray-100">...</div>

RTL و سایت‌های فارسی

Tailwind ویژگی‌های منطقی (Logical) دارد که با dir خودکار برعکس می‌شوند:

فیزیکی منطقی (سازگار با RTL)
ml-4 / mr-4 ms-4 / me-4
pl-6 / pr-6 ps-6 / pe-6
left-0 / right-0 start-0 / end-0
text-left text-start
rounded-l-lg rounded-s-lg

همه‌جا Utilityهای منطقی را ترجیح دهید تا یک کامپوننت هم در فارسی (dir="rtl") و هم در انگلیسی درست کار کند. برای موارد نادر از rtl: و ltr: استفاده کنید: مثلاً rtl:rotate-180 برای برعکس کردن آیکون فلش.

کامپوننت‌های قابل استفاده‌ی مجدد در React

پاسخ «کلاس‌های تکراری» کامپوننت است، نه کلاس CSS:

const variants = {
  primary: "bg-violet-600 text-white hover:bg-violet-700",
  outline: "border border-gray-300 text-gray-800 hover:bg-gray-50",
  ghost: "text-gray-700 hover:bg-gray-100",
};
const sizes = { sm: "h-8 px-3 text-sm", md: "h-10 px-4", lg: "h-12 px-6 text-lg" };

export function Button({ variant = "primary", size = "md", className = "", ...props }) {
  return (
    <button
      className={`inline-flex items-center justify-center gap-2 rounded-lg font-medium transition
                  disabled:opacity-50 ${variants[variant]} ${sizes[size]} ${className}`}
      {...props}
    />
  );
}

برای کلاس‌های شرطی و بازنویسی امن، clsx را با tailwind-merge ترکیب کنید (تداخل‌هایی مثل p-2 و p-4 را حل می‌کند):

import clsx from "clsx";
import { twMerge } from "tailwind-merge";
export const cn = (...inputs) => twMerge(clsx(inputs));

هشدار: Tailwind کلاس‌ها را با اسکن متن سورس پیدا می‌کند. هرگز نام کلاس را پویا نسازید، مثل `bg-${color}-500`؛ این کلاس‌ها تولید نمی‌شوند. به‌جای آن به رشته‌ی کامل کلاس نگاشت کنید.

CSS سفارشی در صورت نیاز

Tailwind نوشتن CSS را ممنوع نمی‌کند. برای چیزهایی مثل محتوای Markdown از @layer components استفاده کنید یا با @utility Utility دلخواه بسازید:

@utility scrollbar-hidden {
  scrollbar-width: none;
  &::-webkit-scrollbar { display: none; }
}

برای HTML مقالات طولانی، پلاگین رسمی @tailwindcss/typography با یک کلاس prose پیش‌فرض‌های زیبایی اضافه می‌کند.

نگه‌داری آسان

  • افزونه‌ی Tailwind CSS IntelliSense را برای تکمیل خودکار و پیش‌نمایش نصب کنید.
  • از پلاگین رسمی Prettier برای مرتب کردن یکدست کلاس‌ها استفاده کنید.
  • وقتی یک الگو سه بار تکرار شد، آن را به کامپوننت تبدیل کنید.
  • تصمیم‌های طراحی را در @theme نگه دارید، نه در مقادیر دلخواه پراکنده.

Tailwind در برابر روش‌های دیگر

روش مزایا معایب
Tailwind سریع، یکدست، CSS بسیار کوچک لیست کلاس طولانی، یادگیری نام‌ها
CSS Modules CSS خالص، محدوده‌دار نام‌گذاری، فایل بیشتر، رشد CSS
CSS-in-JS استایل پویا، کنار کامپوننت هزینه‌ی زمان اجرا (در بسیاری از کتابخانه‌ها)
کتابخانه‌های کامپوننت رابط آماده سفارشی‌سازی سخت‌تر، ظاهر تکراری

جمع‌بندی

Tailwind CSS اجازه می‌دهد مستقیم در Markup و با یک سیستم طراحی محدود استایل بدهید: پیشوندهای ریسپانسیو موبایل‌اول، حالت‌ها، توکن‌های تم در @theme، ویژگی‌های منطقی برای RTL و Variant ‏dark:. آن را با کامپوننت‌های React و cn() ترکیب کنید تا تکرار نداشته باشید، از نام کلاس پویا دوری کنید و CSS سفارشی را برای معدود جاهایی که لازم است نگه دارید.

پرسش‌های متداول

آیا Tailwind کد HTML را شلوغ نمی‌کند؟

Markup طولانی‌تر می‌شود، اما استایل‌ها محلی و قابل‌پیش‌بینی می‌مانند. استخراج کامپوننت، JSX را خوانا نگه می‌دارد.

آیا Tailwind برای کارایی بد است؟

برعکس: فقط کلاس‌های استفاده‌شده تولید می‌شوند و CSS نهایی معمولاً زیر ۲۰ تا ۳۰ کیلوبایت (فشرده‌نشده) است.

آیا پروژه‌ی CSS موجود را به Tailwind مهاجرت دهم؟

لزوماً نه. Tailwind می‌تواند کنار CSS فعلی وجود داشته باشد؛ برای کامپوننت‌های جدید از آن استفاده کنید و اگر تیم پسندید، تدریجی مهاجرت کنید.