19 β Custom utility va variant yaratish¶
β¬ οΈ Oldingi: 18 β @theme bilan dizayn tizimi Β· π README Β· Keyingi: 20 β Direktiva va funksiyalar β‘οΈ
Bu bobda: Tailwind'ni shunchaki ishlatishdan to'xtab, uni kengaytirishni o'rganamiz. v4 ning CSS-birinchi (CSS-first) yo'li bilan:
@utilityorqali Tailwind bermaydigan yangi utility yasash (statikcontent-autodan tortib,--value()bilan ishlaydigan funksionaltab-*gacha),--value()qiymatni qaysi to'rt manbadan olishi,--modifier()bilan/qiymatqismini hal qilish, manfiy funksional utility'lar, va@custom-variantorqali o'zingizning shartlaringiz uchun variant prefiksi (pointer-coarse:,theme-midnight:) qurish. Nihoyat, qachon CSS-birinchi yetadi-yu, qachon to'liq JS plagin kerakligini ajratasiz.
19.1 Avval nega? β token yetmaganda¶
Oldingi bobda tokenlar bilan butun dizayn tilini boshqarishni o'rgandingiz. Lekin token faqat mavjud utility oilalarini oziqlantiradi: rang, spacing, radius, soya. Token sizga bg-brand-500 beradi β chunki bg-* allaqachon bor. Ammo Tailwind umuman qamrab olmagan xususiyat kerak bo'lsa-chi?
Masalan, content-visibility (sahifa unumdorligini oshiruvchi zamonaviy CSS xususiyati) uchun tayyor utility yo'q. Yoki tab-size (matndagi tab kengligi). Yoki "sensorli ekranda kattaroq tugma" degan shart β bu na rang, na o'lcham, balki bir holat.
Ikkita ehtiyoj, ikkita vosita:
- Yangi utility kerak (Tailwind qamramagan xususiyat yoki loyihaga xos naqsh) β
@utility. - Yangi shart kerak (maxsus
data-atribut, media-feature, holat) β@custom-variant.
Eng yaxshi yangilik: v4 da bularning ikkalasi ham CSS ichida yoziladi. v3 da bu uchun JavaScript bilan plagin yozish kerak edi; v4 da ko'p hollarda bir-ikki qator CSS kifoya. JS plagin esa endi faqat dinamik, dasturiy generatsiya kerak bo'lgan kam holatlar uchun (21-bobda ko'rasiz).
π Atamalar. Utility β bitta-yarim xususiyatni o'rnatuvchi klass (
p-4,text-center). Variant β utility oldidagi shart prefiksi (hover:,md:) β u utility'ni "qachon" qo'llanishini boshqaradi (15-bob). Bu bobda ikkalasini ham o'zimiz yasaymiz.
19.2 Statik @utility β bitta yangi klass¶
Eng oddiy holat: bitta qat'iy xususiyatga klass berish. Sintaksis xuddi oddiy CSS qoidasiga o'xshaydi, faqat selektor o'rnida klass nomi turadi:
Tamom. Endi content-auto butun loyihada ishlaydi:
Nega oddiy .class emas?¶
"Shunchaki .content-auto { ... } yozsam bo'lmaydimi?" β yaxshi savol. Bo'ladi, lekin u holda klass variantlarni qo'llab-quvvatlamaydi. @utility orqali e'lon qilingan klass esa Tailwind'ning butun variant tizimiga ulanadi β hover:, lg:, dark:, hamma narsa avtomatik ishlaydi:
<section class="content-auto lg:content-auto hover:content-auto">
Variantlar avtomatik ishlaydi β oddiy .class buni bermaydi.
</section>
Mana shu farq β @utility ni oddiy CSS klassidan ajratuvchi asosiy sabab.
Yana ikki amaliy misol¶
Brauzer scrollbar'ini yashirish β bu uchun standart utility yo'q, lekin tez-tez kerak bo'ladi:
@utility scrollbar-none {
scrollbar-width: none; /* Firefox */
&::-webkit-scrollbar { /* Chrome/Safari */
display: none;
}
}
E'tibor bering β @utility ichida & bilan ichki selektor (&::-webkit-scrollbar) yozsangiz bo'ladi; bu oddiy CSS ichma-ichligi (nesting) kabi ishlaydi.
Diagonal chiziqli fon naqshi β sof dekorativ, lekin loyihada qayta-qayta kerak bo'ladigan narsa:
@utility bg-stripes {
background-image: repeating-linear-gradient(
45deg,
#e0e7ff 0 10px,
#ffffff 10px 20px
);
}
Endi class="bg-stripes hover:bg-stripes" β utility ham, variant ham tayyor.
19.3 Funksional @utility name-* β qiymat qabul qiluvchi utility¶
Hozirgacha klasslar qat'iy edi. Endi kuchli qismga o'tamiz: qiymat qabul qiluvchi utility. tab-2, tab-4, tab-8 β bularning hammasi bitta ta'rifdan kelib chiqsin, deylik.
Buning siri β nom oxiridagi * (yulduzcha) va --value() funksiyasi:
* β bu qiymat o'rni (placeholder). U klassda - dan keyingi qismni ifodalaydi. --value(integer) esa o'sha qismni olib, butun son sifatida hal qiladi:
<pre class="tab-2">...</pre> <!-- tab-size: 2 -->
<pre class="tab-4">...</pre> <!-- tab-size: 4 -->
<pre class="tab-[13]">...</pre> <!-- tab-size: 13 (arbitrary) -->
Bitta ta'rif β cheksiz klasslar oilasi. Aynan Tailwind'ning o'z p-*, text-* utility'lari ham xuddi shu mexanizm bilan qurilgan.
β οΈ Eng ko'p uchraydigan xato β
*ni unutish.@utility tab { ... }(yulduzchasiz) β bu statik utility bo'lib, faqattabklassini yaratadi;tab-4ishlamaydi. Qiymat qabul qilmoqchi bo'lsangiz, nom oxirida*shart:@utility tab-*.
19.4 --value() qiymatni qayerdan oladi?¶
--value() β bu funksional utility'ning yuragi. U * o'rnidagi matnni olib, uni qaysidir manbaga moslab hal qiladi. To'rtta asosiy manba bor:
| Manba turi | Sintaksis | Nimani qabul qiladi | Misol klass |
|---|---|---|---|
| Bare (yalang'och) | --value(integer), --value(number), --value(percentage) |
To'g'ridan-to'g'ri son: 2, 1.5, 50% |
tab-2, scale-150 |
| Arbitrary | --value([length]), --value([integer]), --value([*]) |
Kvadrat qavsdagi ixtiyoriy qiymat | tab-[13], w-[37px] |
| Literal kalit so'z | --value('auto'), --value('full') |
Aniq matnga moslaydi | size-auto, size-full |
| Tema namespace | --value(--spacing-*), --value(--color-*) |
@theme tokenini o'qiydi |
gap-md, glow-brand |
Bir nechta manbani birlashtirish¶
Eng kuchli tomoni β bitta --value() ichida bir nechta manbani vergul bilan sanab, Tailwind'ga "qaysi mos kelsa o'shani ol" deyish mumkin:
@utility tab-* {
/* tab-2 (bare), tab-[13] (arbitrary), tab-full (kalit so'z) β uchchalasi ham ishlaydi */
tab-size: --value(integer, [integer], 'auto');
}
Tema tokenidan o'qiydigan misol¶
Bu β eng professional naqsh: utility o'z qiymatlarini 18-bobdagi @theme tokenlaridan oladi. Masalan, "yorug'lik" soyasini turli o'lchamlarda beruvchi glow-* utility:
@import "tailwindcss";
@theme {
--glow-sm: 0 0 8px;
--glow-md: 0 0 18px;
--glow-lg: 0 0 32px;
}
@utility glow-* {
box-shadow: --value(--glow-*) var(--color-indigo-500);
}
--value(--glow-*) β Tailwind'ga "qiymatni --glow- namespace'idan qidir" deydi. Endi glow-sm, glow-md, glow-lg β uchchalasi ham @theme tokenidan oziqlanadi:
Token o'zgarsa β utility ham birga o'zgaradi. Manba bitta.
π‘ Arbitrary qiymatlar bilan bog'lanish.
tab-[13]dagi[13]β bu 3-bobda ko'rgan arbitrary value (ixtiyoriy qiymat) sintaksisining aynan o'zi.--value([integer])shu qavs ichidagi qiymatni qabul qiladi. Ya'ni siz funksional utility yaratganingizda, foydalanuvchi avtomatik ravishda arbitrary qiymat ham yoza oladi β buni alohida sozlamaysiz.
19.5 --modifier() β /qiymat qismini hal qilish¶
Tailwind klasslarida ba'zan / (slash) orqali modifikator bo'ladi: bg-black/50 (50% shaffoflik), text-lg/7 (qator balandligi). Bu / dan keyingi qism β modifier.
O'z utility'ingizda ham shuni qabul qilmoqchi bo'lsangiz, --modifier() ishlatasiz β u / dan keyingi qismni hal qiladi, xuddi --value() - dan keyingisini hal qilgani kabi:
@utility glow-* {
box-shadow: 0 0 --value([length]) var(--color-indigo-500);
opacity: --modifier([percentage]);
}
<div class="glow-[20px]/75">...</div>
<!-- --value() β 20px (length)
--modifier() β 75% (percentage) -->
Qisqacha: --value() - dan keyingisini, --modifier() / dan keyingisini oladi. Aksariyat utility'lar faqat --value() bilan ishlaydi; --modifier() shaffoflik kabi "ikkinchi o'lcham" kerak bo'lganda qo'shiladi.
19.6 Manfiy funksional utility'lar¶
Tailwind'da -mt-4 (manfiy margin) kabi manfiy utility'lar bor. O'z funksional utility'ingizning manfiy variantini berish uchun alohida - bilan boshlanuvchi ta'rif yozasiz:
@utility top-* {
top: --value(--spacing-*);
}
@utility -top-* {
top: calc(--value(--spacing-*) * -1);
}
Endi top-4 musbat, -top-4 esa manfiy qiymat beradi. Naqsh sodda: manfiy variant uchun alohida @utility -name-* e'lon qiling va qiymatni calc(... * -1) bilan teskari qiling.
19.7 Custom variant β o'zingizning shartingiz¶
Endi ikkinchi vositaga o'tamiz. Variant β bu utility oldidagi shart prefiksi. hover:, md:, dark: β bularning bari shartlar. @custom-variant esa sizga yangi shart e'lon qilish imkonini beradi.
Media-feature varianti¶
"Sensorli (touch) ekranda tugmalar kattaroq bo'lsin" β buni @media (pointer: coarse) aniqlaydi. Shu shartga nom beramiz:
Endi pointer-coarse: istalgan utility oldiga qo'yiladi:
Sintaksis sodda: @custom-variant <nom> (<shart>);. Bu β qisqa forma (shorthand), bitta media so'rovi yoki selektor uchun.
Selektor / atribut varianti¶
Endi maxsus tema. Saytda data-theme="midnight" atributi bo'lganda ishlovchi theme-midnight: varianti yasaymiz:
<html data-theme="midnight">
<body>
<div class="bg-white theme-midnight:bg-black theme-midnight:text-white">
Midnight temada qora fon, oq matn
</div>
</body>
</html>
Bu yerdagi sintaksis muhim. & β utility qo'llanayotgan elementning o'rnini bildiradi. :where(...) esa selektorni o'rab, uning specificity'sini 0 ga tushiradi β shunda variant boshqa utility'lar bilan tortishmaydi.
β οΈ Selektorli variantda
&va:where()deyarli har doim kerak.&bo'lmasa, Tailwind variantni qaysi elementga qo'llashni bilmaydi.:where()bo'lmasa, variant specificity'si oshib, oddiy utility'larni bosib ketishi mumkin. Naqsh:&:where([shart] *).
Ko'p qatorli forma va @slot¶
Ba'zan variant bir qatorga sig'maydi β masalan, media so'rovi ichida holat selektori kerak bo'lsa. U holda jingalak qavsli forma va @slot ishlatiladi. @slot β "utility shu yerga joylashadi" degan o'rin:
Bu any-hover:bg-indigo-500 ni "agar qurilma hover'ni qo'llab-quvvatlasa va element hover holatida bo'lsa" degan murakkab shartga aylantiradi. @slot o'rnida utility'ning haqiqiy CSS'i joylashadi.
dark ham aslida custom variant¶
Qiziq haqiqat: 16-bobda ko'p ishlatgan dark: varianti β bu Tailwind'ning ichki custom varianti, xolos. Va u ustiga-yoziladi. Standart dark'ni class strategiyasiga o'tkazmoqchi bo'lsangiz:
Ya'ni siz bobning birinchi yarmida o'rgangan mexanizm β Tailwind'ning o'zi dark ni qanday quradigani bilan aynan bir xil. Sehr yo'q, hammasi shu bitta direktiva.
19.8 @variant β Tailwind variantini qo'lda yozilgan CSS ichida ishlatish¶
Ba'zan oddiy CSS qoidasi yozasiz (utility emas), lekin uning ichida Tailwind variantini qo'llashni xohlaysiz β masalan, komponent stilining dark-mode versiyasini. Buning uchun @variant direktivasi bor (e'tibor bering: @custom-variant variant yaratadi, @variant esa mavjud variantni qo'llaydi):
@layer components {
.btn {
background: var(--color-indigo-600);
color: white;
@variant dark {
background: var(--color-indigo-400);
color: black;
}
}
}
Kompilyatsiyadan keyin .btn yorug' rejimda indigo-600, dark rejimda esa indigo-400 bo'ladi β dark: ni HTML'da yozmasdan, to'g'ridan-to'g'ri CSS ichida. @variant o'zingiz yaratgan custom variantlar bilan ham ishlaydi: @variant pointer-coarse { ... }.
19.9 Qachon @utility/@custom-variant, qachon JS plagin?¶
Endi tabiiy savol: "Bularning hammasini CSS'da qila olsam, JS plagin nimaga kerak?"
| Vaziyat | Vosita |
|---|---|
| Bitta yangi xususiyat klassi | @utility (statik) |
| Qiymat qabul qiluvchi utility oilasi | @utility name-* + --value() |
| Yangi shart / media-feature / atribut | @custom-variant |
| Qo'lda CSS ichida variant qo'llash | @variant |
| Yuzlab klassni dasturiy generatsiya (masalan, ikon to'plamidan, sozlama obyektidan tsikl bilan) | JS plagin (@plugin) |
| Boshqa plaginga (npm paket) ulanish | JS plagin |
Qoida sodda: CSS-birinchi yo'l aksariyat ehtiyojlarni qoplaydi. JS plagin faqat dasturiy mantiq (tsikl, shart, tashqi ma'lumotdan generatsiya) kerak bo'lgandagina ustun keladi. Bu mavzuni β plaginlarni paketlangan utility sifatida β 21-bobda batafsil ko'ramiz.
19.10 Amaliy misol β barchasini birga¶
Kichik, lekin to'liq kengaytma to'plamini quramiz: funksional tab-*, statik scrollbar-none, sensorli pointer-coarse: varianti, theme-midnight: atribut varianti va komponent ichida @variant dark:
@import "tailwindcss";
/* 1. Funksional utility β tema namespace'idan ham, bare/arbitrary'dan ham */
@utility tab-* {
tab-size: --value(integer, [integer]);
}
/* 2. Statik utility β ichki selektor bilan */
@utility scrollbar-none {
scrollbar-width: none;
&::-webkit-scrollbar { display: none; }
}
/* 3. Media-feature varianti β sensorli ekran */
@custom-variant pointer-coarse (@media (pointer: coarse));
/* 4. Atribut varianti β maxsus tema */
@custom-variant theme-midnight (&:where([data-theme="midnight"] *));
/* 5. Qo'lda komponent + @variant dark */
@layer components {
.kod-panel {
background: var(--color-slate-100);
@variant dark {
background: var(--color-slate-800);
}
}
}
<html data-theme="midnight">
<pre class="kod-panel tab-4 scrollbar-none p-3
theme-midnight:bg-black
pointer-coarse:p-5">
function salom() {
console.log("Tab kengligi 4, scrollbar yashirin");
}
</pre>
</html>
Bitta <pre> da: funksional utility (tab-4), statik utility (scrollbar-none), atribut varianti (theme-midnight:) va sensorli variant (pointer-coarse:) β barchasi siz o'zingiz CSS'da yaratdingiz, hech qanday JS plaginsiz.
19.11 Tez-tez uchraydigan xatolar¶
- Funksional utility'da
*ni unutish.@utility tab { ... }faqattabklassini beradi;tab-4uchun@utility tab-*kerak. - Noto'g'ri
--value()manba turi.tab-4da--value(integer)ishlaydi, lekintab-[13px]uchun--value([length])kerak. Klass qabul qilishi kerak bo'lgan har bir shaklni--value()ichida sanang:--value(integer, [integer], 'auto'). - Oddiy
.classdan variant kutish..content-auto { ... }gahover:ishlamaydi. Variant kerak bo'lsa β@utility content-autoishlating. - Selektorli variantda
&/:where()ni tashlab ketish.@custom-variant theme-x ([data-x] &)ko'pincha kutilmagan natija beradi. Ishonchli naqsh:&:where([data-x] *). @custom-variantva@variantni chalkashtirish.@custom-variantβ variant yaratadi (bir marta, e'lon).@variantβ mavjud variantni qo'lda yozilgan CSS ichida qo'llaydi.- CSS yetarli bo'lsa ham JS plaginga yugurish. Statik yoki qiymatli utility, oddiy shart β bularning bari CSS-birinchi. JS plaginni faqat dasturiy generatsiya kerak bo'lganda oching.
π Oldinga qarash. Endi Tailwind'ni token darajasida (18-bob) ham, utility/variant darajasida (shu bob) ham kengaytira olasiz. Keyingi bobda bu direktivalar oilasini to'liq ko'rib chiqamiz β
@apply,@layer,@reference,theme()funksiyasi va boshqalar β ya'ni Tailwind'ning butun CSS "lug'ati". Undan keyin esa 21-bobda JS plaginlar bilan tanishasiz.
Mashqlar¶
1-mashq. Loyihangizda text-wrap: balance (sarlavhalarni chiroyli o'raydigan zamonaviy CSS) kerak, lekin tayyor utility yo'q. text-balance nomli statik utility yarating va u hover: bilan ham ishlasin.
Yechim
@utility orqali e'lon qilingani uchun text-balance Tailwind'ning variant tizimiga ulanadi β hover:, lg: va boshqalar avtomatik ishlaydi. Oddiy .text-balance { ... } bo'lsa, variantlar ishlamasdi.
2-mashq. tab-2, tab-4, tab-8 va shuningdek tab-[13] ishlaydigan funksional utility yozing. tab-size xususiyatini sozlasin.
Yechim
Nom oxiridagi * β qiymat o'rni. --value(integer) tab-2/tab-4/tab-8 (bare son) ni, --value([integer]) esa tab-[13] (arbitrary) ni hal qiladi. Ikkalasini bitta --value() ichida vergul bilan sanaymiz.
3-mashq. Bir hamkasbingiz @utility shadow-soft { ... } deb yozdi va shadow-soft-lg ishlamasligidan hayron. U xohlagani β shadow-soft-sm, shadow-soft-md, shadow-soft-lg. Xatosi nimada, qanday tuzatadi?
Yechim
Nom oxirida * yo'q β shuning uchun bu statik utility bo'lib qoldi va faqat shadow-soft klassini yaratdi. Qiymat (sm/md/lg) qabul qilishi uchun funksional shaklga o'tkazish kerak:
@theme {
--shadow-soft-sm: 0 1px 4px;
--shadow-soft-md: 0 4px 12px;
--shadow-soft-lg: 0 10px 28px;
}
@utility shadow-soft-* {
box-shadow: --value(--shadow-soft-*) var(--color-slate-400);
}
* qo'shilgach shadow-soft-sm/-md/-lg ishlaydi, qiymatlar @theme tokenidan o'qiladi.
4-mashq. Saytingizda sensorli qurilmalarda tugmalar kattaroq bo'lishi kerak. pointer-coarse: variantini yarating va bitta tugmada p-2 (sichqoncha) β p-4 (barmoq) qiling.
Yechim
@media (pointer: coarse) qo'pol ko'rsatuvchi (barmoq) ishlatilayotganini aniqlaydi. Variant qisqa formada: @custom-variant <nom> (<shart>);.
5-mashq. data-theme="midnight" atributi bo'lganda ishlovchi theme-midnight: variantini yarating. Specificity muammosi chiqmasligi uchun to'g'ri sintaksisni ishlating va bitta blokda bg-white β bg-black qiling.
Yechim
& β utility qo'llanayotgan elementning o'rni, :where(...) esa specificity'ni 0 ga tushiradi, shunda variant boshqa utility'larni bosib ketmaydi. Bu β 16-bobdagi dark variant qurilishining aynan o'zi.
6-mashq (debugging). Quyidagi kod ishlamayapti β card-glow: degan variant kutilgan edi, lekin u utility'ga aylanmagandek. Sababini toping va to'g'rilang.
Yechim
Variant yaratish uchun @variant emas, @custom-variant ishlatilishi kerak. @variant β mavjud variantni qo'lda yozilgan CSS ichida qo'llash uchun. Ikkisi almashib qolgan:
/* Variant YARATISH β @custom-variant */
@custom-variant card-glow (&:hover);
/* Variantni CSS ichida QO'LLASH β @variant */
.karta {
border-radius: 1rem;
@variant card-glow {
box-shadow: 0 0 18px var(--color-indigo-500);
}
}
Eslang: @custom-variant β variant e'lon qiladi (bir marta); @variant β uni ishlatadi.
β¬ οΈ Oldingi: 18 β @theme bilan dizayn tizimi Β· π README Β· Keyingi: 20 β Direktiva va funksiyalar β‘οΈ