Tailwind CSS — React bilan sozlash, classNames kutubxonasi
Muammodan boshlaylik
Yangi loyiha boshlayapsiz. Tugma kerak — ko'k fon, oq matn, yumaloq burchak, hover da to'qroq. CSS Modules bilan:
/* Button.module.css */
.btn {
background: #3b82f6;
color: white;
padding: 10px 20px;
border-radius: 6px;
border: none;
cursor: pointer;
}
.btn:hover {
background: #2563eb;
}
<button className={styles.btn}>Saqlash</button>
Ishlaydi. Lekin bu jarayon har safar takrorlanadi: yangi element — yangi fayl, yangi klass nomi o'ylab topish, stillar yozish, import qilish. Oddiy kartochka uchun 40-50 qator CSS.
Tailwind boshqacha yondashadi: klass nomlari o'zi CSS bo'ladi.
Tailwind CSS nima?
Tailwind — utility-first CSS framework. Har bir klass bitta CSS xususiyatni anglatadi:
bg-blue-500 → background-color: rgb(59 130 246)
text-white → color: rgb(255 255 255)
px-5 → padding-left: 1.25rem; padding-right: 1.25rem
py-2.5 → padding-top: 0.625rem; padding-bottom: 0.625rem
rounded-md → border-radius: 0.375rem
Siz CSS yozmaysiz — tayyor klasslarni qo'shib ketasiz:
<button className="bg-blue-500 text-white px-5 py-2.5 rounded-md hover:bg-blue-600">
Saqlash
</button>
Hayotiy o'xshatma: Lego o'yini. Har bir Lego g'ishtchasi — bitta xususiyat. Siz ularni kerakli tarzda qo'shib, xohlagan shaklni yaratasiz. Alohida bloklarsiz yaxlit narsa yasay olmaysiz, lekin har qanday narsani qurish mumkin.
React + Vite bilan o'rnatish
npm install tailwindcss @tailwindcss/vite
vite.config.js ga plugin qo'shing:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
plugins: [
react(),
tailwindcss(), // ← qo'shing
],
});
src/index.css ga import:
@import "tailwindcss";
Tamom. Boshqa fayl, boshqa sozlama kerak emas. Tailwind v4 da konfiguratsiya fayli ham shart emas — avtomatik ishlaydi.
Asosiy klasslar — tez ko'rish
Padding va Margin
p-4 → padding: 1rem (16px)
px-4 → padding-left + right: 1rem
py-2 → padding-top + bottom: 0.5rem
pt-3 → padding-top: 0.75rem
m-4 → margin: 1rem
mx-auto → margin-left: auto; margin-right: auto
mt-8 → margin-top: 2rem
Raqamlar rem da: 4 → 1rem (16px), 2 → 0.5rem (8px), 8 → 2rem (32px).
Ranglar
bg-blue-500 → ko'k fon (o'rtacha)
bg-blue-100 → och ko'k fon
bg-blue-900 → to'q ko'k fon
text-gray-700 → to'q kulrang matn
text-red-500 → qizil matn
border-gray-200 → och kulrang chegara
Raqamlar: 100 — eng och, 900 — eng to'q.
O'lchamlar
w-full → width: 100%
w-1/2 → width: 50%
w-64 → width: 16rem (256px)
h-screen → height: 100vh
h-12 → height: 3rem (48px)
max-w-lg → max-width: 32rem
Flexbox
flex → display: flex
items-center → align-items: center
justify-between → justify-content: space-between
gap-4 → gap: 1rem
flex-col → flex-direction: column
flex-1 → flex: 1 1 0%
Matn
text-sm → font-size: 0.875rem (14px)
text-lg → font-size: 1.125rem (18px)
text-2xl → font-size: 1.5rem (24px)
font-bold → font-weight: 700
font-medium → font-weight: 500
leading-relaxed → line-height: 1.625
tracking-wide → letter-spacing: 0.025em
Chegara va yumaloqlik
border → border-width: 1px
border-2 → border-width: 2px
rounded → border-radius: 0.25rem
rounded-md → border-radius: 0.375rem
rounded-lg → border-radius: 0.5rem
rounded-full → border-radius: 9999px (doira)
Holat va Responsive klasslar
Hover, Focus, Active
Tailwind da pseudo-klass lar prefix bilan yoziladi:
<button className="
bg-blue-500
hover:bg-blue-600
active:bg-blue-700
focus:outline-none
focus:ring-2
focus:ring-blue-300
">
Bosing
</button>
hover: — hover holatida, focus: — fokus holatida, active: — bosilganda.
Responsive
Tailwind mobile-first ishlaydi. Prefix yo'q = barcha ekran. Prefix bor = shu ekrandan katta:
sm: → min-width: 640px
md: → min-width: 768px
lg: → min-width: 1024px
xl: → min-width: 1280px
<div className="
grid
grid-cols-1
sm:grid-cols-2
lg:grid-cols-3
gap-4
">
Mobilda 1 ustun, 640px dan 2 ustun, 1024px dan 3 ustun.
Dark Mode
<div className="bg-white dark:bg-gray-900 text-gray-900 dark:text-white">
dark: — foydalanuvchi qurilmasi dark modeda bo'lsa ishlaydi.
Amaliy komponentlar
Tugma
function Button({ children, variant = 'primary', disabled }) {
return (
<button
disabled={disabled}
className="
inline-flex items-center gap-2
px-5 py-2.5
rounded-md
text-sm font-medium
transition-colors duration-200
disabled:opacity-50 disabled:cursor-not-allowed
bg-blue-500 text-white hover:bg-blue-600 active:bg-blue-700
"
>
{children}
</button>
);
}
disabled:opacity-50 — disabled holatda opacity. duration-200 — transition tezligi.
Kartochka
function Card({ title, description, tag }) {
return (
<div className="
bg-white
border border-gray-200
rounded-xl
p-5
shadow-sm
hover:shadow-md
transition-shadow duration-200
">
<span className="
text-xs font-semibold uppercase tracking-wider
text-blue-600 bg-blue-50
px-2.5 py-1 rounded-full
mb-3 inline-block
">
{tag}
</span>
<h3 className="text-base font-semibold text-gray-900 mb-2">{title}</h3>
<p className="text-sm text-gray-500 leading-relaxed">{description}</p>
</div>
);
}
Muammo: className uzun va noto'g'ri
Tailwind ishlatganda tez bir muammo chiqadi:
<button className="inline-flex items-center gap-2 px-5 py-2.5 rounded-md text-sm font-medium transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed bg-blue-500 text-white hover:bg-blue-600">
Bu qator juda uzun — o'qish qiyin, variant boshqarish yanada qiyin:
// ❌ Variantlarni shunday boshqarish noto'g'ri
<button className={`px-5 py-2.5 rounded-md ${variant === 'danger' ? 'bg-red-500 hover:bg-red-600' : 'bg-blue-500 hover:bg-blue-600'} ${disabled ? 'opacity-50 cursor-not-allowed' : ''}`}>
Bu yerda clsx (yoki classnames) kutubxonasi yordamga keladi.
clsx — dinamik klasslar uchun
npm install clsx
clsx — klasslarni qulay birlashtirish uchun yordamchi:
import clsx from 'clsx';
// Oddiy birlashtirish
clsx('px-4', 'py-2', 'rounded') // → "px-4 py-2 rounded"
// Shartli klasslar — object syntax
clsx({
'bg-blue-500': true,
'bg-red-500': false,
'opacity-50': disabled,
}) // → "bg-blue-500 opacity-50"
// Aralash
clsx('px-4', { 'bg-blue-500': isPrimary, 'bg-red-500': isDanger })
Endi tugma komponentini qayta yozamiz:
import clsx from 'clsx';
const variantKlasslari = {
primary: 'bg-blue-500 text-white hover:bg-blue-600 active:bg-blue-700',
danger: 'bg-red-500 text-white hover:bg-red-600 active:bg-red-700',
success: 'bg-green-500 text-white hover:bg-green-600',
outline: 'bg-transparent border border-blue-500 text-blue-500 hover:bg-blue-50',
ghost: 'bg-transparent text-gray-600 hover:bg-gray-100',
};
const sizeKlasslari = {
sm: 'px-3 py-1.5 text-xs',
md: 'px-5 py-2.5 text-sm',
lg: 'px-6 py-3 text-base',
};
function Button({
children,
variant = 'primary',
size = 'md',
fullWidth = false,
disabled = false,
className,
}) {
return (
<button
disabled={disabled}
className={clsx(
// Asosiy stillar — har doim
'inline-flex items-center justify-center gap-2',
'rounded-md font-medium',
'transition-colors duration-200',
'focus:outline-none focus:ring-2 focus:ring-offset-2',
// Variant
variantKlasslari[variant],
// O'lcham
sizeKlasslari[size],
// Shartli
{
'w-full': fullWidth,
'opacity-50 cursor-not-allowed pointer-events-none': disabled,
},
// Tashqaridan qo'shimcha klasslar
className
)}
>
{children}
</button>
);
}
<Button>Saqlash</Button>
<Button variant="danger" size="sm">O'chirish</Button>
<Button variant="outline" fullWidth>Kirish</Button>
<Button disabled>Yuborilmoqda...</Button>
{/* Tashqaridan qo'shimcha klass */}
<Button className="mt-4">Davom etish</Button>
Endi variant qo'shish oson — variantKlasslari ga yangi kalit yozasiz. className ham clsx ichida va tashqi klasslar ham qabul qilinadi.
tailwind-merge — klass ziddiyatini hal qilish
clsx bir muammoni hal qilmaydi: bir xil xususiyatning ikki klassi to'qnashsa nima bo'ladi?
// p-4 va px-6 to'qnashdi — qaysi ustun keladi?
clsx('p-4', 'px-6') // → "p-4 px-6"
// Brauzer ikkalasini ko'radi, cascade qoidasiga ko'ra oxirgisi ustun keladi
// Lekin bu tasodifiy — boshqa tartibda yozilsa boshqa natija
tailwind-merge bu muammoni hal qiladi — ziddiyatli Tailwind klasslarni aqlli birlashtiradi:
npm install tailwind-merge
import { twMerge } from 'tailwind-merge';
twMerge('p-4 px-6') // → "p-4 px-6" emas, "px-6 p-4" tartibida to'g'rilaydi
twMerge('text-sm text-lg') // → "text-lg" (oxirgisi ustun)
twMerge('bg-blue-500', 'bg-red-500') // → "bg-red-500"
Amalda clsx va twMerge birgalikda ishlatiladi:
import clsx from 'clsx';
import { twMerge } from 'tailwind-merge';
// Ikkalasini birlashtiruvchi yordamchi funksiya
export function cn(...inputs) {
return twMerge(clsx(inputs));
}
import { cn } from '@/lib/utils'; // yoki qaerda saqlagan bo'lsangiz
function Button({ className, variant, ...props }) {
return (
<button
className={cn(
'px-4 py-2 rounded-md bg-blue-500 text-white',
variant === 'danger' && 'bg-red-500',
className // tashqi klass bg-green-500 bo'lsa — o'sha ustun keladi
)}
{...props}
/>
);
}
// Tashqaridan padding o'zgartirish — to'g'ri ishlaydi
<Button className="px-8">Keng tugma</Button>
// → "py-2 rounded-md bg-blue-500 text-white px-8"
// px-4 olib tashlandi, px-8 qoldi
cn funksiyasi — React ekotizimida juda keng tarqalgan pattern. Shadcn/ui, Radix UI, Headless UI bilan ishlaydigan har qanday loyihada shu funksiyani ko'rasiz.
Amaliy misol — to'liq forma
import { cn } from '@/lib/utils';
function FormInput({ label, error, className, ...props }) {
return (
<div className="flex flex-col gap-1.5">
{label && (
<label className="text-sm font-medium text-gray-700">
{label}
</label>
)}
<input
className={cn(
'w-full px-3 py-2',
'border rounded-md',
'text-sm text-gray-900',
'placeholder:text-gray-400',
'outline-none transition-colors duration-200',
'focus:ring-2 focus:ring-blue-300 focus:border-blue-500',
error
? 'border-red-400 focus:ring-red-200 focus:border-red-400'
: 'border-gray-300',
className
)}
{...props}
/>
{error && (
<p className="text-xs text-red-500">{error}</p>
)}
</div>
);
}
// Ishlatish
function LoginForm() {
return (
<div className="max-w-md mx-auto mt-16 p-8 bg-white rounded-2xl shadow-sm border border-gray-200">
<h2 className="text-2xl font-bold text-gray-900 mb-6">Kirish</h2>
<div className="flex flex-col gap-4">
<FormInput
label="Email"
type="email"
placeholder="siz@example.com"
/>
<FormInput
label="Parol"
type="password"
placeholder="••••••••"
error="Parol kamida 8 ta belgi bo'lishi kerak"
/>
<button className="
w-full py-2.5 mt-2
bg-blue-500 hover:bg-blue-600
text-white text-sm font-medium
rounded-md
transition-colors duration-200
">
Kirish
</button>
<p className="text-center text-sm text-gray-500">
Hisobingiz yo'qmi?{' '}
<a href="/register" className="text-blue-500 hover:underline font-medium">
Ro'yxatdan o'ting
</a>
</p>
</div>
</div>
);
}
Tez-tez uchraydigan xatolar
Dinamik klass nomlari to'liq yozilmasa
// ❌ Xato — Tailwind build vaqtida bu klassni topib, CSS ga qo'sha olmaydi
const rang = 'blue';
<div className={`bg-${rang}-500`}>
// ✅ To'g'ri — to'liq klass nomi yoziladi
const klasslar = {
blue: 'bg-blue-500',
red: 'bg-red-500',
};
<div className={klasslar[rang]}>
Tailwind statik analiz bilan ishlaydi: u faqat to'liq yozilgan klass nomlarini CSS ga qo'shadi. Dinamik birlashtirilgan nomlarni ko'rmas — build da yo'qoladi.
!important o'rniga ! prefiksi
// Tailwind da important
<div className="!text-red-500"> {/* text-red-500 !important */}
<div className="!p-0"> {/* padding: 0 !important */}
!important CSS da kuchli qurol, ehtiyotkorlik bilan ishlatiladi.
Spacing raqamlarini adashtirish
p-4 → 16px (1rem)
p-5 → 20px (1.25rem)
p-6 → 24px (1.5rem)
p-8 → 32px (2rem)
p-10 → 40px (2.5rem)
p-12 → 48px (3rem)
Har bir birlik 0.25rem (4px). p-4 = 4 × 4px = 16px. Bu qoidani bilsangiz, raqamlarni hisoblash oson bo'ladi.
Xulosa
Tailwind — utility-first yondashuv. Har bir klass bitta CSS xususiyat. Siz alohida CSS fayl yozmaysiz — klasslarni to'g'ridan-to'g'ri JSX da qo'shib ketasiz.
clsx va tailwind-merge birgalikda (cn funksiyasi) — dinamik va ziddiyatsiz klass boshqarish uchun standart pattern.
Eslab qoling:
npm install tailwindcss @tailwindcss/vite— o'rnatish@import "tailwindcss"— CSS ga importhover:,focus:,disabled:— pseudo-klass prefikslarsm:,md:,lg:— responsive prefikslardark:— dark mode- Dinamik klasslar to'liq yozilishi kerak —
bg-${rang}-500ishlamaydi clsx— shartli klasslar uchuntwMerge— ziddiyatli Tailwind klasslarni hal qilishcn = twMerge(clsx(...))— ikkalasini birlashtiruvchi standart yordamchi
Foydali havolalar
- tailwindcss.com — rasmiy sayt, barcha klasslar ro'yxati va qidiruv
- tailwindcss.com/docs/installation/using-vite — Vite bilan o'rnatish
Keyingi dars
38-dars: clsx va classnames — dinamik class boshqarish