Mundarija (41)
- Bu darsda
- 1. Nega bu kerak?
- 2. Takrorning to'rt yechimi
- 2.1 Sikl: takror aslida bir joyda
- 2.2 Komponent: asosiy yechim
- 2.3 @apply: utilitalarni CSS class'ga yig'ish
- 2.4 Variant funksiyasi
- 3. @apply tuzoqlari
- 3.1 Alohida faylda: @reference
- 3.2 Boshqa tuzoqlar
- 4. clsx, tailwind-merge va cn()
- 4.1 clsx — shartli class
- 4.2 Muammo: to'qnashuv
- 4.3 tailwind-merge — to'qnashganini olib tashlash
- 4.4 cn() = ikkalasi birga
- 4.5 Tuzoq: tailwind-merge sizning tokenlaringizni bilmaydi
- 5. cva: variantlarni tartibli yozish
- 5.1 Birinchi variantlar
- 5.2 Ikki tuzoq
- 5.3 tailwind-variants
- 6. Dinamik class nomlari
- 6.1 bg-${rang} ishlamaydi
- 6.2 To'g'ri yo'llar
- 7. Ish qurollari
- 7.1 prettier-plugin-tailwindcss — class tartibi
- 7.2 Tailwind CSS IntelliSense
- 7.3 canonicalize — class'ni qisqartirish
- 8. Ko'p uchraydigan xatolar
- 8.1 Hamma narsa @apply
- 8.2 @reference siz alohida fayl
- 8.3 clsx bilan ustidan yozish
- 8.4 tailwind-merge sozlanmagan
- 8.5 Qismlardan yig'ilgan class
- 9. Mashqlar
- 1-mashq (oson): tailwind-merge natijasini toping
- 2-mashq (o'rta): «Bahor» nishoni (badge)
- 3-mashq (qiyin): tuzoqlarni tuzating
- 4-mashq: Portfolio qadami — tugma @apply bilan
- 10. Real ishda
- Xulosa
- Manbalar
Tailwind CSS 4: komponent naqshlari — cn(), cva va @apply
Qisqacha: Tailwind'da takrorlanadigan uzun class ro'yxati CSS class'iga emas, komponentga yig'iladi: ro'yxat bir marta yoziladi va hamma joyda qayta ishlatiladi. JavaScript loyihalarida buning uchun ikki vosita bor.
cn()(clsx+tailwind-merge) class'larni shartga qarab qo'shadi va to'qnashganini (px-3vapx-6) bittaga keltiradi.cvaesaturi,olchamkabi variantlarni tartibli yozadi.@applyutilitalarni CSS class'ga yig'adi — u faqat HTML'ni o'zingiz boshqarmaydigan joylar uchun. Class nomini qismlardan yig'ish (bg-${rang}) ishlamaydi — to'liq nom yozing.
Bu darsda
- "Iflos HTML" muammosini va uning to'rt yechimini (sikl, komponent,
@apply, variant funksiyasi) farqlaysiz. @applyqachon o'rinli, qachon zararli ekanini asoslaysiz va v4 dagi@referencexatosini tuzatasiz.clsx,tailwind-mergevacn()natijalarini o'qiysiz, o'z tokenlaringiz uchuntailwind-mergeni sozlaysiz.cvabilan tugma variantlarini (turi,olcham,compoundVariants) yozasiz.- Prettier plagini, Tailwind IntelliSense va
canonicalizebuyrug'ini ishlatasiz, dinamik class xatosidan qochasiz.
Oldin bilishingiz kerak: Tailwind CSS 3: v4 konfiguratsiyasi, Tailwind CSS 2: variantlar, CSS Modules, CSS metodologiyalari.
1. Nega bu kerak?
Oldingi darsda «Bahor» tokenlarini Tailwind'ga uladik. Endi aksiya sahifasida "Stolni band qilish" tugmasi bor:
<a class="inline-flex items-center gap-xs rounded-m bg-asosiy
px-m py-xs font-bold text-fon hover:bg-asosiy-toq
focus-visible:outline-2 focus-visible:outline-offset-2
focus-visible:outline-asosiy" href="bron/">
Stolni band qilish
</a>O'n bitta class. Tugma sahifada uch joyda, menyu va bron sahifalarida yana beshta. Dizayner "tugma burchagi kattaroq bo'lsin" desa — sakkizta faylda qidirib almashtirish kerak. Bittasini unutsangiz, sayt har xil tugmalar bilan qoladi.
Bu — Tailwind'ga eng ko'p aytiladigan tanqid: "iflos HTML". HTML ichi class bilan to'lib ketadi, bir xil ro'yxat ko'p marta takrorlanadi. CSS metodologiyalari darsida utility-first yondashuvning kamchiligi sifatida shuni ko'rgan edik.
Tailwind jamoasining javobi: takrorni CSS'ga emas, komponentga yig'ing. Bugun shu javobning to'rt shaklini ko'ramiz va har birini qachon tanlashni o'rganamiz. Xuddi choyxonadagi kabi: Rustam aka har buyurtmada osh retseptini qayta yozmaydi — retsept bitta daftarda, oshxona uni qayta-qayta ishlatadi.
Dars JavaScript kutubxonalariga tayanadi. JavaScript'ni 08-qismda, React'ni 17-qismda o'rganamiz. Hozir kodni o'qishni o'rganamiz: har misoldan keyin u nima qilishini so'zlar bilan aytamiz. Kodni o'zingiz ishga tushirmoqchi bo'lsangiz — mashqlar bo'limida buyruqlar bor.
2. Takrorning to'rt yechimi
2.1 Sikl: takror aslida bir joyda
Menyudagi uchta taom kartasi. HTML'da uchta bir xil article — takror. Lekin real saytda bu kartalar qo'lda yozilmaydi: ular ro'yxatdan (masalan, bazadagi menyudan) sikl bilan chiqariladi. Sikl ichida class ro'yxati bir marta yoziladi. JavaScript'da siklni 08-qismda ko'rasiz.
Hozir, oddiy HTML'da takror bo'lsa, VS Code'ning ko'p kursorli tahriri yordam beradi (VS Code'da tez tahrirlash): bir xil class'larni Ctrl + D bilan birma-bir belgilab, hammasini birdan o'zgartirasiz. Tailwind hujjati ham kichik takror uchun aynan shuni tavsiya qiladi.
2.2 Komponent: asosiy yechim
Tugma — butun saytda bir xil ko'rinadigan narsa. Zamonaviy loyihalarda u komponent bo'ladi: HTML bo'lagini nomlab, qayta ishlatish imkoni. React'da (17-qism) bu shunday ko'rinadi:
export function BronTugma({ children }) {
return (
<a
href="bron/"
className="inline-flex rounded-m bg-asosiy px-m py-xs
font-bold text-fon hover:bg-asosiy-toq"
>
{children}
</a>
);
}O'qilishi: "BronTugma degan komponent — shu class'li a tegi, ichiga nima berilsa, o'sha matn". Sahifalarda endi <BronTugma>Stolni band qilish</BronTugma> yoziladi. className — React'da class atributining nomi. Class ro'yxati bitta faylda; burchakni o'zgartirish — bitta joy. React bilmasangiz ham g'oya aniq: retsept bir joyda, ishlatish ko'p joyda.
Vue, Svelte, Astro — hammasida komponent bor. Oddiy HTML saytda esa (masalan, «Bahor» hozir shunday) komponent yo'q. U yerda keyingi yechim kerak.
2.3 @apply: utilitalarni CSS class'ga yig'ish
@apply — Tailwind direktivasi: utilitalar ro'yxatini oddiy CSS class ichiga "yoyadi".
<script
src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4">
</script>
<style type="text/tailwindcss">
@theme {
--color-asosiy: oklch(47.5% 0.1 147.7);
--color-urgu: oklch(53.7% 0.153 39.8);
}
@layer components {
.bron-havola {
@apply inline-block rounded-lg bg-asosiy px-4 py-2
font-bold text-white hover:bg-urgu;
}
}
</style>
<p class="flex flex-wrap gap-2 p-4">
<a class="bron-havola" href="bron/">@apply</a>
<a class="bron-havola bg-urgu" href="bron/">+ bg-urgu</a>
<a class="rounded-lg bg-urgu bg-asosiy px-4 py-2 text-white"
href="bron/">urgu, asosiy</a>
<a class="rounded-lg bg-asosiy bg-urgu px-4 py-2 text-white"
href="bron/">asosiy, urgu</a>
</p>Nimaga qarang, birinchi ikki tugmaga: birinchisi yashil — .bron-havola ning o'zi. Ikkinchisi qizg'ish: bg-urgu utilitasi components qatlamidagi .bron-havola dan kuchliroq (Tailwind CSS 3 darsidagi qatlamlar). Ya'ni @apply li class'ni utilita bilan ustidan yozish mumkin — @layer components shuning uchun kerak. Oxirgi ikki tugmani pastroqda muhokama qilamiz.
@apply qayerda to'g'ri tanlov:
- HTML'ni siz yozmaysiz. Markdown'dan chiqqan blog matni, CMS (sayt matnini dasturchisiz tahrirlash tizimi) muharriri, begona kutubxona yasagan HTML — ularga class qo'yib bo'lmaydi.
.maqola a { @apply text-asosiy underline; }yagona yo'l. (Blog matni uchun tayyor yechim ham bor — Tailwind CSS 5 darsidagiprose.) - Komponentsiz kichik sayt. «Bahor» kabi oddiy HTML saytda bitta-ikkita takrorlanadigan element (
.bron-havola). - Begona komponentni bezash. Kutubxona o'z class'ini beradi, siz unga tokenlaringizni qo'yasiz.
Qayerda zararli: hamma narsani @apply ga yig'ish. Tailwind hujjati ochiq ogohlantiradi: "HTML toza ko'rinsin" deb @apply ishlatsangiz, oddiy CSS yozgan bo'lasiz — faqat qo'shimcha qadam bilan. Class nomlarini o'ylab topish, faylma-fayl sakrash, ishlatilmay qolgan class'lar — utility-first qochgan hamma muammo qaytadi.
2.4 Variant funksiyasi
Tugmaning bir necha turi bor: asosiy (yashil), urg'u (qizg'ish), chegarali. O'lchami ham ikki xil. Komponent ichida buni shartlar bilan yozish tez chalkashadi. Buning uchun cva kabi vositalar bor — pastda, «cva: variantlarni tartibli yozish» bo'limida. Undan oldin ikki kichik yordamchi kerak.
Tekshirib ko'ring: Sizning React loyihangizda
Kartakomponenti bor. Hamkasbingiz.karta { @apply rounded-m bg-yuza p-m shadow-1; }yozib, komponentdaclassName="karta"qilmoqchi. Nima deysiz?
Javob
Kerak emas. Komponent allaqachon "retsept daftari": class ro'yxati bitta faylda turibdi. @apply qo'shimcha nom (.karta), qo'shimcha fayl va qo'shimcha qatlam beradi, foyda bermaydi. @apply — komponent yo'q joy uchun.
3. @apply tuzoqlari
3.1 Alohida faylda: @reference
Vue yoki Svelte komponentining <style> bloki, CSS Modules fayli (CSS Modules) — ular alohida yig'iladi va kirish.css dagi temani bilmaydi. Tekshirdik: alohida.css da @apply rounded-lg bg-asosiy px-4 py-2; yozib, CLI'dan o'tkazdik:
Error: Cannot apply unknown utility class `rounded-lg`. Are you using CSS modules or similar and missing `@reference`? https://tailwindcss.com/docs/functions-and-directives#reference-directiveTarjimasi: "Noma'lum rounded-lg utilitasini qo'llab bo'lmaydi. CSS Modules yoki shunga o'xshash narsa ishlatyapsizmi va @reference yo'qmi?" Xato birinchi class'da to'xtadi — rounded-lg Tailwind'ning oddiy utilitasi, lekin bu fayl Tailwind'ni umuman bilmaydi.
Tuzatish — fayl boshiga:
@reference "./kirish.css";
.bron-havola {
@apply rounded-lg bg-asosiy px-4 py-2;
}Natija:
.bron-havola {
border-radius: var(--radius-lg, 0.5rem);
background-color: var(--color-asosiy, oklch(47.5% 0.1 147.7));
padding-inline: calc(var(--spacing, 0.25rem) * 4);
padding-block: calc(var(--spacing, 0.25rem) * 2);
}Nimaga qarang: @reference temani o'qidi, lekin natijaga Preflight yoki :root tokenlarini qo'shmadi — faqat .bron-havola. Shuning uchun har var() ichida zaxira qiymat bor: o'zgaruvchi topilmasa ham ishlaydi. @import yozsangiz edi, har komponent faylida butun Tailwind qayta chiqardi.
3.2 Boshqa tuzoqlar
@applyichida variant ishlaydi:hover:bg-urgu,md:px-6. Natijada@media (hover: hover)va:hoverbilan chiqadi.- O'z class'ingizni
@applyqilib bo'lmaydi.@apply bron-havola— faqat@utilitybilan yozilgan bo'lsa ishlaydi (Tailwind CSS 3). - Tartib sizniki emas.
@applyichidagi class'lar tartibi natijadagi deklaratsiyalar tartibini belgilamaydi — Tailwind ularni o'z tartibida yozadi. Ikki qarama-qarshi class (px-4 px-6) yozmang.
4. clsx, tailwind-merge va cn()
4.1 clsx — shartli class
clsx ni CSS Modules darsida ko'rgan edik: nomlarni bo'sh joy bilan birlashtiradi, false bo'lganlarini tashlaydi. Tailwind bilan ham xuddi shunday. Node'da tekshirdik (clsx 2.1.1):
import { clsx } from "clsx";
const tugadi = true;
const faol = false;
console.log(
clsx("taom-karta", tugadi && "opacity-50", faol && "ring-2"),
);
console.log(clsx("p-4", { "opacity-50": tugadi, "ring-2": faol }));Konsolda:
taom-karta opacity-50
p-4 opacity-50Ikkinchi qatordagi { ... } — obyekt (obyektlar — 08-qismda): "kalit — class nomi, qiymat — shart". Shart true bo'lgan class qoladi. Natija bir xil, yozuv shakli boshqa.
4.2 Muammo: to'qnashuv
Tugma komponenti asosiy rangni beradi, ishlatayotgan sahifa esa "bu yerda qizg'ish bo'lsin" deb qo'shimcha class uzatadi. clsx ikkalasini ham qoldiradi:
console.log(clsx("px-4 py-2 bg-asosiy", "bg-urgu"));px-4 py-2 bg-asosiy bg-urguQaysi biri yutadi? Yuqoridagi natijaning oxirgi ikki tugmasiga qayting. Uchinchisida bg-urgu bg-asosiy, to'rtinchisida bg-asosiy bg-urgu — ikkalasi ham qizg'ish. Kaskad darsidan eslang: og'irligi teng ikki qoidadan CSS faylida pastdagisi yutadi, class atributidagi tartib ahamiyatsiz. Tailwind esa natija faylini o'z tartibida yozadi. Demak, bg-asosiy ni bg-urgu ustidan yozishning imkoni yo'q — tartibni qanday qo'ysangiz ham.
4.3 tailwind-merge — to'qnashganini olib tashlash
tailwind-merge — class ro'yxatini o'qib, bir xususiyatga tegadigan class'lardan faqat oxirgisini qoldiradigan kutubxona. Tekshirdik (tailwind-merge 3.7.0):
import { twMerge } from "tailwind-merge";
console.log(twMerge("px-4 py-2 bg-asosiy", "bg-urgu"));
console.log(twMerge("px-4 py-2", "p-3"));
console.log(twMerge("p-3", "px-4"));
console.log(twMerge("hover:bg-asosiy bg-oq", "hover:bg-urgu"));Konsolda:
px-4 py-2 bg-urgu
p-3
p-3 px-4
bg-oq hover:bg-urguO'qilishi:
bg-asosiyolib tashlandi —bg-urgukeyin kelgan.p-3to'rt tomonni beradi,px-4 py-2ni butunlay qoplaydi — ular ketdi.- Teskarisi:
px-4faqat yon tomonlar,p-3ning tepa-pastini qoplamaydi. Ikkalasi qoladi, CSS'dapx-4yon tomonlarda yutadi. hover:li class'lar faqat o'zaro raqobatlashadi.bg-oqhover'siz — u qoldi.
Ya'ni tailwind-merge Tailwind'ning class ma'nosini biladi. Oddiy "takrorni o'chirish" emas.
4.4 cn() = ikkalasi birga
Ikkala kutubxona deyarli doim birga ishlatiladi. shadcn/ui (Tailwind CSS 5) loyihalarida bu kichik funksiya lib/utils faylida turadi:
import { clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...kirishlar) {
return twMerge(clsx(kirishlar));
}O'qilishi: "cn ga berilgan hamma narsani avval clsx bilan birlashtir (shartlar, false lar), keyin twMerge bilan to'qnashuvlarni tozala". ...kirishlar — "nechta argument berilsa, hammasi" (rest parametrlar — 08-qismda).
console.log(cn("rounded-lg px-4 py-2 bg-asosiy text-oq",
tugadi && "bg-kul-300", undefined, null));rounded-lg px-4 py-2 text-oq bg-kul-300Taom tugagan — tugma kulrang, bg-asosiy ketdi. undefined va null jimgina tashlandi. React komponentlarida bu naqsh shunday ishlatiladi: className={cn("...asosiy class'lar", props.className)} — komponent o'z class'larini beradi, ishlatgan joy ustidan yozishi mumkin.
4.5 Tuzoq: tailwind-merge sizning tokenlaringizni bilmaydi
«Bahor» tokenlari bilan tekshirdik — va kutilmagan natija oldik:
console.log(twMerge("text-step-1 text-urgu", "text-asosiy"));
console.log(twMerge("p-m", "p-s"));text-asosiy
p-m p-sBirinchi qatorda shrift o'lchami (text-step-1) ham o'chib ketdi! tailwind-merge step-1 ni tanimaydi va uni rang deb o'yladi: "text-urgu, text-step-1, text-asosiy — uchta rang, oxirgisi qolsin". Ikkinchi qatorda aksincha: m va s noma'lum — to'qnashuv sezilmadi.
Tuzatish — kutubxonaga tokenlarni aytish:
import { extendTailwindMerge } from "tailwind-merge";
const twMerge = extendTailwindMerge({
extend: {
theme: {
text: ["step--1", "step-0", "step-1", "step-2", "step-3"],
spacing: ["2xs", "xs", "s", "m", "l", "xl", "2xl"],
color: ["fon", "yuza", "matn", "asosiy", "urgu", "ikkinchi"],
},
},
});Endi:
text-step-1 text-asosiy
p-sQoida: @theme ga o'z nomingizni qo'shdingizmi — tailwind-merge sozlamasiga ham qo'shing. Aks holda xato ko'rinmaydi: sahifa biror joyda "sababsiz" kichik shriftga tushadi.
Tekshirib ko'ring:
twMerge("mt-2 mb-4", "my-6")nima qaytaradi?twMerge("my-6", "mt-2")chi?
Javob
Birinchisi — my-6: u tepa va pastni beradi, oldingi mt-2 va mb-4 ni to'liq qoplaydi. Ikkinchisi — my-6 mt-2: mt-2 faqat tepani o'zgartiradi, my-6 ning pastki qismi kerak — ikkalasi qoladi. «tailwind-merge — to'qnashganini olib tashlash» bo'limidagi p-3 px-4 bilan bir xil mantiq: keng class keyin kelsa — torlarini o'chiradi, tor class keyin kelsa — ikkalasi qoladi.
5. cva: variantlarni tartibli yozish
5.1 Birinchi variantlar
cva (class-variance-authority) — komponent variantlarini jadval kabi yozish uchun kichik kutubxona. «Bahor» tugmasi, tekshirdik (class-variance-authority 0.7.1):
import { cva } from "class-variance-authority";
const tugma = cva("inline-flex items-center rounded-lg font-bold", {
variants: {
turi: {
asosiy: "bg-asosiy text-oq hover:bg-asosiy-toq",
urgu: "bg-urgu text-oq",
chegara: "border-2 border-asosiy text-asosiy",
},
olcham: {
kichik: "px-3 py-1 text-sm",
katta: "px-6 py-3 text-lg",
},
},
compoundVariants: [
{ turi: "urgu", olcham: "katta", class: "uppercase" },
],
defaultVariants: { turi: "asosiy", olcham: "kichik" },
});
console.log(tugma());
console.log(tugma({ turi: "urgu", olcham: "katta" }));
console.log(tugma({ turi: "chegara", class: "w-full" }));Konsolda:
inline-flex items-center rounded-lg font-bold bg-asosiy text-oq hover:bg-asosiy-toq px-3 py-1 text-sm
inline-flex items-center rounded-lg font-bold bg-urgu text-oq px-6 py-3 text-lg uppercase
inline-flex items-center rounded-lg font-bold border-2 border-asosiy text-asosiy px-3 py-1 text-sm w-fullTuzilishi:
- Birinchi argument — asos: har turdagi tugmada bo'ladigan class'lar.
variants— o'lchovlar.turivaolcham— o'lchov nomlari, ichidagilar — ularning qiymatlari. Har qiymatga o'z class'lari.compoundVariants— kombinatsiya: "urg'u va katta bo'lsa — qo'shimchauppercase". Ikkinchi qatorda aynan shu ishladi.defaultVariants— hech narsa berilmasa. Birinchi qatordatugma()bo'sh chaqirildi — asosiy va kichik tugma chiqdi.class— joyida qo'shimcha: uchinchi qatordaw-full.
Bu — CSS metodologiyalari darsidagi BEM modifikatorining JavaScript'dagi egizagi: .tugma--urgu.tugma--katta o'rniga tugma({ turi: "urgu", olcham: "katta" }).
5.2 Ikki tuzoq
Noma'lum qiymat jim o'tadi. tugma({ olcham: "ulkan" }) natijasi — inline-flex items-center rounded-lg font-bold bg-asosiy text-oq hover:bg-asosiy-toq. O'lcham class'lari yo'q, xato ham yo'q. Tugma kichrayib qoladi va sababi ko'rinmaydi. TypeScript bilan (Nega TypeScript, 15-qism) bunday xato yozish paytida tutiladi — cva variantlar tipini o'zi chiqaradi.
cva to'qnashuvni tozalamaydi. Buni ko'rish uchun soddaroq tugma oldik — asosi qisqa, faqat ikki tur:
const tugma = cva("rounded-lg px-3 py-1 font-bold", {
variants: {
turi: { asosiy: "bg-asosiy text-oq", urgu: "bg-urgu text-oq" },
},
defaultVariants: { turi: "asosiy" },
});
console.log(tugma({ class: "px-6" }));
console.log(cn(tugma({ turi: "urgu" }), "px-6"));rounded-lg px-3 py-1 font-bold bg-asosiy text-oq px-6
rounded-lg py-1 font-bold bg-urgu text-oq px-6Birinchi qatorda px-3 va px-6 ikkalasi qoldi — va biz bilamizki, yutadigani CSS fayl tartibiga bog'liq. Ikkinchi qatorda cn() px-3 ni olib tashladi. Shuning uchun shadcn/ui'da doim cn(tugma({ ... }), className) shakli.
5.3 tailwind-variants
Shu vazifaning boshqa kutubxonasi — tailwind-variants. Farqi: u ichida tailwind-merge'ni o'zi chaqiradi va murakkab komponent bo'laklarini (slots) ham variantlaydi. Tekshirdik (tailwind-variants 3.3.1):
import { tv } from "tailwind-variants";
const tugma = tv({
base: "inline-flex rounded-lg px-3 py-1 font-bold",
variants: {
turi: { asosiy: "bg-asosiy text-oq", urgu: "bg-urgu text-oq" },
},
defaultVariants: { turi: "asosiy" },
});
console.log(tugma({ turi: "urgu", class: "px-6" }));inline-flex rounded-lg py-1 font-bold bg-urgu text-oq px-6px-3 o'zi ketdi. Qaysi birini tanlash — jamoa kelishuvi: shadcn/ui cva'ni ishlatadi, HeroUI kabi to'plamlar — tailwind-variants'ni.
Tekshirib ko'ring: Dizayner tugmaning uchinchi o'lchamini so'radi —
orta(px-4 py-2). cva'da nechta joyni o'zgartirasiz? Tugma ishlatilgan sakkizta sahifada-chi?
Javob
Bitta joy: variants.olcham ga orta: "px-4 py-2" qatori. Sahifalarga tegilmaydi — ular hozircha kichik yoki katta ni so'raydi, yangi o'lchamni esa kerak joyda tugma({ olcham: "orta" }) deb chaqirasiz. Standart o'lcham o'zgarishi kerak bo'lsa — yana bitta qator, defaultVariants. Variantlar jadvali aynan shuning uchun: qaror bir joyda.
flowchart LR
A["Asos<br/>class'lari"] --> V["cva:<br/>variantlar"]
V --> C["clsx:<br/>shartlar"]
C --> M["tailwind-merge:<br/>to'qnashuv"]
M --> H["class="...""]Nimaga qarang: har vosita bitta ishni qiladi va natijani keyingisiga uzatadi. cn(tugma({...}), qoshimcha) — aynan shu zanjir.
6. Dinamik class nomlari
6.1 bg-${rang} ishlamaydi
Taom kartasining rangi ma'lumotdan kelsin: aksiyada — urg'u, oddiy kunda — asosiy. JavaScript'da shunday yozish vasvasasi bor:
const rang = "urgu";
karta.className = `taom-karta bg-${rang} p-4`;`...${rang}...` — shablon satr (shablon satrlar, 08-qism): ${rang} o'rniga o'zgaruvchi qiymati qo'yiladi. Brauzerda natija bg-urgu bo'ladi — lekin rang chiqmaydi.
Sababi — Tailwind fayllarni ishga tushirmaydi, faqat matnini o'qiydi. Tekshirdik: shu fayl skanerlanganda natijada .p-4 bor, .bg-urgu esa yo'q. Tailwind fayl matnida bg-${rang} ni ko'rdi — bunday class yo'q. bg-urgu degan to'liq so'z esa faylda umuman yozilmagan.
6.2 To'g'ri yo'llar
To'liq nomlar lug'ati — eng toza yo'l:
const ranglar = {
asosiy: "text-asosiy",
urgu: "text-urgu",
};
karta.className = ranglar[rang];Tekshirdik: text-asosiy va text-urgu natijaga kirdi — ikkalasi fayl matnida to'liq yozilgan.
Boshqa yo'llar:
@source inline("bg-urgu bg-asosiy")(Tailwind CSS 3) — ro'yxat oldindan ma'lum, lekin kodda to'liq yozib bo'lmaydi.- Holat atributi va variant: HTML'da
data-holat="aksiya", class'dadata-[holat=aksiya]:bg-urgu(Tailwind CSS 2). Class ro'yxati o'zgarmaydi, faqat atribut. - CSS o'zgaruvchisi:
bg-(--karta-rang)va o'zgaruvchini JavaScript beradi. «Bahor»da ehtiyot bo'ling:style="..."atributini CSP to'sadi (CSS nima).
Qaysi birini tanlash? Variantlar soni oz va oldindan ma'lum bo'lsa (asosiy, urg'u) — lug'at yoki cva. Holat HTML'da allaqachon bor bo'lsa (aria-busy, data-holat) — variant: JavaScript faqat atributni almashtiradi, class'lar joyida qoladi. Qiymat oldindan noma'lum bo'lsa (foydalanuvchi tanlagan rang) — CSS o'zgaruvchisi. Uchala holatda ham bitta qoida: Tailwind ko'radigan fayl matnida har class to'liq yozilgan bo'lsin.
Tekshirib ko'ring: Kod
`border-${holat}`deb yozilgan,holat—aksiyayokitugadi. Tailwind natijasida.border-aksiyabo'ladimi? Qanday tuzatasiz?
Javob
Bo'lmaydi. Tailwind faylni ishga tushirmaydi, faqat matnini o'qiydi — matnda border-aksiya degan to'liq so'z yo'q. Tuzatish: to'liq nomlar lug'ati ({ aksiya: "border-aksiya", tugadi: "border-tugadi" }) yoki HTML'da data-holat atributi va data-[holat=aksiya]:... varianti. Ikkalasida ham class nomi faylda butunligicha yozilgan.
7. Ish qurollari
7.1 prettier-plugin-tailwindcss — class tartibi
Uzun class ro'yxatini o'qishni osonlashtiradigan kelishuv: tartib doim bir xil. Kod uslubi darsidagi Prettier uchun Tailwind jamoasining rasmiy plagini bor. Tekshirdik (prettier 3.9.9, plagin 0.8.1). .prettierrc:
{
"plugins": ["prettier-plugin-tailwindcss"],
"tailwindStylesheet": "./src/kirish.css",
"printWidth": 70
}tailwindStylesheet — v4 uchun: plagin temani shu fayldan o'qiydi (bg-asosiy ni tanishi uchun). printWidth — qator uzunligi chegarasi (standart 80). Oldin — class'lar aralash tartibda:
<a class="md:px-6 px-4 bron-havola hover:bg-urgu flex bg-asosiy"
href="bron/">Stolni band qilish</a>npx prettier --write dan keyin:
<a
class="bron-havola flex bg-asosiy px-4 hover:bg-urgu md:px-6"
href="bron/"
>Stolni band qilish</a
>Nimaga qarang: o'z class'imiz (bron-havola) — birinchi. Keyin layout (flex), keyin bezak (bg-asosiy, px-4), oxirida variantli class'lar (hover:, md:). Tartib natija CSS'dagi tartibga yaqin — ko'z o'rganib qoladi. Prettier class ro'yxatini ikki qatorga bo'lmaydi: ro'yxat uzun bo'lsa, qator ham uzun qoladi. >Stolni va </a ning g'alati ko'rinishi — Prettier'ning odatiy uslubi: u teg ichidagi matnga bo'sh joy qo'shmaslik uchun shunday bo'ladi.
7.2 Tailwind CSS IntelliSense
VS Code kengaytmasi (Tailwind Labs'niki): class yozganda taklif ro'yxati, class ustiga sichqoncha olib borsangiz — uning CSS'i, rang yonida kichik kvadrat. Eng foydalisi — to'qnashuv ogohlantirishi: bitta elementda px-4 px-6 bo'lsa, ikkalasining tagini chizadi. VS Code'da Extensions → "Tailwind CSS IntelliSense" (VS Code kengaytmalari).
7.3 canonicalize — class'ni qisqartirish
Tailwind 4.3.3 CLI'sida canonicalize buyrug'i bor. Tekshirdik:
npx @tailwindcss/cli canonicalize --css src/kirish.css \
"bg-(--color-asosiy)" "mt-[0.25rem]" "bg-[#fff]"bg-asosiy
mt-1
bg-whiteU ixtiyoriy qiymatni mavjud utilitaga aylantiradi (bg-white standart palitra tozalanmagan loyihada). Eski kodni tozalashda yoki AI yozgan class'larni tekshirishda qo'l keladi.
8. Ko'p uchraydigan xatolar
8.1 Hamma narsa @apply
.karta, .sarlavha, .matn, .tugma — hammasi @apply. Bu — Tailwind ustida qurilgan oddiy CSS, ikki qatlam murakkablik. Tuzatish: komponent bo'lsa — class'lar komponentda; @apply faqat HTML'ga qo'l yetmaydigan joyda.
8.2 @reference siz alohida fayl
Cannot apply unknown utility class. Tuzatish: fayl boshiga @reference "./kirish.css"; (yo'l shu faylga nisbatan).
8.3 clsx bilan ustidan yozish
clsx("bg-asosiy", "bg-urgu") — ikkalasi qoladi, natija CSS tartibiga bog'liq. Tuzatish: cn().
8.4 tailwind-merge sozlanmagan
text-step-1 "sababsiz" yo'qoladi. Tuzatish: extendTailwindMerge ga tokenlar.
8.5 Qismlardan yig'ilgan class
`bg-${rang}` — natijada yo'q. Tuzatish: to'liq nomlar lug'ati.
9. Mashqlar
Mashqlar kurs/mashqlar/06/tailwind/ da. JavaScript misollarini ishga tushirish uchun (npm — 16-qismda to'liq, hozir aynan takrorlang):
npm pkg set type=module
npm install clsx tailwind-merge class-variance-authority
node cn.jstype=module — import yozuvi ishlashi uchun (PostCSS darsidagi ogohlantirishni eslang).
1-mashq (oson): tailwind-merge natijasini toping
Ishga tushirmasdan yozing, keyin tekshiring:
twMerge("rounded-lg bg-asosiy", "rounded-none")twMerge("px-2 py-1", "p-4", "px-6")twMerge("text-sm font-bold", "text-lg")twMerge("md:px-4 px-2", "px-3")
Ishora: "tailwind-merge — to'qnashganini olib tashlash" bo'limidagi to'rt qoida.
Yechim
bg-asosiy rounded-none— ikkala burchak class'i bir xususiyat, oxirgisi qoladi.p-4 px-6—p-4oldingipx-2 py-1ni qoplaydi; keyin kelganpx-6faqat yon tomonlar,p-4qoladi.font-bold text-lg—text-smvatext-lgikkalasi o'lcham. Bu yerda nomlar Tailwind'niki — tailwind-merge ularni taniydi.md:px-4 px-3—md:px-4boshqa variant, u faqatmd:li class bilan raqobatlashadi.
Tekshirishda to'rttasi ham shunday chiqadi.
2-mashq (o'rta): «Bahor» nishoni (badge)
Taom kartasidagi kichik nishon: "Yangi", "Mashhur", "Achchiq". cva bilan yozing:
- asos:
inline-block rounded-toliq px-xs text-step--1 font-bold; turi:yangi—bg-asosiy text-fon,mashhur—bg-urgu text-fon,achchiq—border border-urgu text-urgu;- standart turi —
yangi.
nishon(), nishon({ turi: "achchiq" }) va nishon({ turi: "mashhur", class: "uppercase" }) natijalarini ayting.
Ishora: "Birinchi variantlar" bo'limidagi tugma — faqat bitta o'lchov (turi).
Yechim
import { cva } from "class-variance-authority";
const nishon = cva(
"inline-block rounded-toliq px-xs text-step--1 font-bold",
{
variants: {
turi: {
yangi: "bg-asosiy text-fon",
mashhur: "bg-urgu text-fon",
achchiq: "border border-urgu text-urgu",
},
},
defaultVariants: { turi: "yangi" },
},
);Natijalar (asos qisqartirildi — har birining boshida o'sha besh class):
... bg-asosiy text-fon
... border border-urgu text-urgu
... bg-urgu text-fon uppercaseyangi, mashhur, achchiq — «Bahor»ning taom-karta modifikatorlari (04-qismdan). cva'da ular class emas, variant qiymati bo'ldi.
3-mashq (qiyin): tuzoqlarni tuzating
Hamkasbingiz yozdi:
import { clsx } from "clsx";
import { cva } from "class-variance-authority";
const tugma = cva("rounded-m px-m py-xs", {
variants: { turi: { asosiy: "bg-asosiy", urgu: "bg-urgu" } },
});
const rang = aksiyami ? "urgu" : "asosiy";
const cls = clsx(tugma({ turi: "asosiy" }), `bg-${rang}`, "px-l");Uchta muammoni toping va tuzating.
Ishora: dinamik nom, clsx va cn() farqi, tailwind-merge sozlamasi.
Yechim
`bg-${rang}`— Tailwind bu class'ni yasamaydi. Variantning o'zi bor:tugma({ turi: rang }).clsxto'qnashuvni tozalamaydi:px-mvapx-likkalasi qoladi.cn()kerak.px-m,px-l— «Bahor» tokenlaridan yasalgan o'z utilitalarimiz (faqat Tailwind tajribasida). Oddiy tailwind-merge ularni tanimaydi va to'qnashuvni sezmaydi (p-m p-smisolini eslang).extendTailwindMergebilanspacingro'yxatini bering.
const rang = aksiyami ? "urgu" : "asosiy";
const cls = cn(tugma({ turi: rang }), "px-l");cn — sozlangan twMerge ustidan qurilgan. Natija: rounded-m py-xs bg-urgu px-l (aksiya kunida).
4-mashq: Portfolio qadami — tugma @apply bilan
Portfolio'da aloqa formasining tugmasi brend rangida (Yakuniy loyiha). Uni oldingi darsdagi tajriba/tailwind/ da ikki usulda qayta yozing:
karta.htmlga forma tugmasini qo'shing:<button type="submit">Yuborish</button>. Faqat utilitalar bilan bezang: fonbg-asosiy, matntext-fon, ichki masofapx-m py-xs, burchakrounded-m, hover vafocus-visibleholatlari.- Ikkinchi usul:
kirish.cssda@layer componentsichidaform button { @apply ...; }. HTML'dan class'larni olib tashlang. - Ikkala natijani 360 pikselda solishtiring.
dist/natija.csshajmi (bayt) qanday o'zgardi? - Portfolio uchun qaysi yo'l to'g'ri? Bir gap bilan asoslang.
Ishora: portfolio'da tugmaga class qo'yilmaydi — teg selektori (Yakuniy loyiha darsidagi qoida).
Yechim
1-usul (HTML'da):
<button type="submit" class="rounded-m bg-asosiy px-m py-xs
font-bold text-fon hover:bg-asosiy/90
focus-visible:outline-2 focus-visible:outline-offset-2
focus-visible:outline-asosiy">Yuborish</button>2-usul (kirish.css):
@layer components {
form button {
@apply rounded-m bg-asosiy px-m py-xs font-bold text-fon
hover:bg-asosiy/90 focus-visible:outline-2
focus-visible:outline-offset-2 focus-visible:outline-asosiy;
}
}Ko'rinish bir xil. Hajm deyarli bir xil: 1-usulda har class alohida qoida, 2-usulda bitta form button qoidasi — farq bir necha o'n bayt, bu sizning faylingizga bog'liq. Hajm hal qiluvchi emas.
4: portfolio'da 2-usul to'g'ri — HTML'da class qo'yilmaydi (teg selektori qoidasi) va tugma bitta. Bu @apply ning o'rinli holati: HTML'ni "boshqara olmaymiz" — o'z qoidamiz shunday. Portfolio esa baribir oddiy CSS'da qoladi: tajriba faqat taqqoslash uchun.
10. Real ishda
- shadcn/ui —
cn()+cvanaqshining eng mashhur namunasi. UningButtonkomponenti aynan «cva» bo'limidagi tuzilma:variant(default,destructive,outline...) vasize. Tailwind CSS 5 darsida uni o'rnatamiz. - Kod ko'rib chiqish (code review) da tez-tez uchraydigan izohlar: "
@applyshart emas, komponent bor", "cnishlating,clsxemas", "class dinamik yig'ilgan — build'da yo'qoladi". - Jamoa standarti: Prettier plagini va IntelliSense deyarli har Tailwind loyihasida — class tartibi haqida bahs bo'lmaydi.
- Intervyuda so'raladi: "Tailwind'da iflos HTML muammosini qanday hal qilasiz?", "
@applyqachon kerak?", "tailwind-mergenima uchun?", "Negabg-${rang}-500ishlamaydi?".
Xulosa
- Tailwind'da takror komponentga yig'iladi: class ro'yxati bir joyda, ishlatish ko'p joyda.
@apply— HTML'ni boshqara olmaydigan joy uchun; alohida faylda@referencebilan,@layer componentsichida.clsxshart bo'yicha qo'shadi,tailwind-mergeto'qnashganini olib tashlaydi,cn()— ikkalasi birga.- O'z tokenlaringizni
extendTailwindMergega qo'shing, aks holda merge noto'g'ri class'ni o'chiradi. cva— variantlar jadvali (variants,compoundVariants,defaultVariants); to'qnashuv uchun unicn()ga o'rang.- Class nomi fayl matnida to'liq yozilsin —
bg-${rang}Tailwind uchun ko'rinmas.
Keyingi dars: Tailwind CSS 5: plaginlar va ekotizim — prose, forma plagini, animatsiyalar, daisyUI va shadcn/ui kabi tayyor to'plamlar.
Manbalar
- Tailwind CSS: "Styling with utility classes" (Managing duplication), "Functions and directives" (@apply, @reference), "Detecting classes in source files" — tailwindcss.com/docs
- tailwind-merge: "Configuration" — github.com/dcastil/tailwind-merge
- class-variance-authority — cva.style
- tailwind-variants — tailwind-variants.org
- prettier-plugin-tailwindcss — github.com/tailwindlabs/prettier-plugin-tailwindcss
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!