IlmHamroh
JavaScript Full-stack/6-qism. CSS: harakat, zamonaviy CSS va dizayn35/57-dars24 daqiqa
Mundarija (41)

Tailwind CSS 3: v4 konfiguratsiyasi — @theme, @utility va @custom-variant

Qisqacha: Tailwind v4 da sozlama JavaScript faylida emas, CSS'ning o'zida yoziladi. @theme { --color-asosiy: ...; } bitta qatorda ikki narsa beradi: bg-asosiy, text-asosiy kabi utilitalar va :root dagi --color-asosiy o'zgaruvchisi. Tokeningiz boshqa o'zgaruvchiga tayansa — @theme inline. Tailwind'ning tayyor palitrasini --color-*: initial o'chiradi. O'z utilitangiz — @utility, o'z prefiksingiz (masalan data-tema ga ulangan dark:) — @custom-variant.

Bu darsda

  • @theme tokenini yozasiz va Tailwind undan qaysi utilita va o'zgaruvchini yasashini natija faylida o'qiysiz.
  • «Bahor» tokenlarini (tokenlar.css) @theme inline bilan Tailwind'ga ulaysiz va inline nega kerakligini tushuntirasiz.
  • dark: variantini data-tema atributiga ulaysiz va uch holatli (tizim, yorug', qorong'i) variant yozasiz.
  • @utility bilan o'z utilitangizni, @source bilan qidiruv joylarini sozlaysiz.
  • Eski tailwind.config.js ni o'qiysiz va v3 loyihani npx @tailwindcss/upgrade bilan ko'chirasiz.

Oldin bilishingiz kerak: Tailwind CSS 2: variantlar, Tailwind CSS 1, Dizayn tokenlari, Qorong'i rejim va temalash, Kaskadni boshqarish: @layer.

1. Nega bu kerak?

Jasur akaning jiyani «Bahor» uchun kichik aksiya sahifasini Tailwind'da yozmoqchi. Oldingi ikki darsni o'qib chiqdi va ishga tushdi. Birinchi kartani yozdi:

html
<article class="rounded-lg bg-white p-4 shadow-sm">
  <h3 class="text-green-700">Osh</h3>
  <p class="font-bold text-orange-700">35 000 so'm</p>
</article>

Brauzerda ochdi — va hafsalasi pir bo'ldi. Tailwind'ning green-700 i «Bahor»ning yashili emas. orange-700 ham narx rangi emas. Qorong'i rejimda karta oppoq qoldi. Menyudagi masofalar 16 → 18 piksel "nafas oladi", bu yerda esa qotib qolgan 16.

U Tailwind CSS 2 darsidagi ixtiyoriy qiymatni eslaydi: bg-[#2f6b3a]. Ishlaydi, lekin bu — Dizayn tokenlari darsida qochgan narsamiz: kodga yana xom hex qaytdi. Ertaga dizayner yashilni o'zgartirsa, uni o'nlab class ichidan qidirish kerak.

Kerakli narsa — Tailwind'ga o'z tokenlarimizni o'rgatish. Shunda bg-asosiy, p-m, text-urgu kabi class'lar paydo bo'ladi. Ular «Bahor»ning --rang-asosiy, --masofa-m tokenlariga tayanadi va qorong'i rejim o'z-o'zidan ishlaydi.

Bu darsning hamma buyruqlari Tailwind 4.3.3 da tekshirildi (npm ls shunday ko'rsatdi). Loyiha — Tailwind CSS 1 darsidagidek: src/kirish.css va HTML fayllar, CSS esa CLI bilan yig'iladi. npm'ni 16-qismda to'liq o'rganamiz — hozir buyruqlarni aynan takrorlang:

bash
npm install --save-dev tailwindcss @tailwindcss/cli
npx @tailwindcss/cli -i src/kirish.css -o dist/natija.css

2. @theme: token → utilita

2.1 Birinchi tokenlar

src/kirish.css:

css
@import "tailwindcss";

@theme {
  --color-asosiy: oklch(47.5% 0.1 147.7);
  --color-urgu: oklch(53.7% 0.153 39.8);
  --font-sarlavha: "Bahor", "Bahor zaxira", serif;
  --spacing-m: 1rem;
  --radius-m: 0.5rem;
}

@theme — Tailwind'ning maxsus @-qoidasi. Brauzer uni tanimaydi, faqat Tailwind o'qiydi va natija faylida oddiy CSS'ga aylantiradi. Ichida oddiy CSS o'zgaruvchilari, lekin nomi maxsus boshlanadi: --color-, --font-, --spacing-. Bu boshlanish namespace (nomlar maydoni) deyiladi. Tailwind unga qarab qaysi utilitani yasashni biladi. Xuddi bozordagi rastalar kabi: "rang" rastasiga qo'yilgan tovar bg-, text- peshtaxtalarida sotiladi, "masofa" rastasidagisi — p-, m-, gap- da.

HTML'da ishlatamiz:

html
<article class="rounded-m bg-white p-m">
  <h3 class="font-sarlavha text-asosiy">Osh</h3>
  <p class="font-bold text-urgu">35 000 so'm</p>
</article>

dist/natija.css dan kerakli bo'laklar (CLI chiqargani, qisqartirmasdan):

css
@layer theme {
  :root, :host {
    --color-asosiy: oklch(47.5% 0.1 147.7);
    --color-urgu: oklch(53.7% 0.153 39.8);
    --font-sarlavha: "Bahor", "Bahor zaxira", serif;
    --spacing-m: 1rem;
    --radius-m: 0.5rem;
  }
}
@layer utilities {
  .rounded-m {
    border-radius: var(--radius-m);
  }
  .p-m {
    padding: var(--spacing-m);
  }
  .font-sarlavha {
    font-family: var(--font-sarlavha);
  }
  .text-asosiy {
    color: var(--color-asosiy);
  }
  .text-urgu {
    color: var(--color-urgu);
  }
}

Nimaga qarang: bitta token ikki narsaga aylandi. Birinchisi — theme qatlamidagi CSS o'zgaruvchisi, ikkinchisi — utilita, u shu o'zgaruvchini var() bilan o'qiydi. Utilita qiymatni ichiga ko'chirib olmadi. Demak, --color-asosiy ni sahifaning biror joyida qayta belgilasangiz, text-asosiy ham o'zgaradi — bu CSS o'zgaruvchilari darsidagi odatiy meros.

Bitta --color-asosiy dan faqat text-asosiy emas, rang oladigan hamma utilita chiqadi: bg-asosiy, border-asosiy, fill-asosiy, decoration-asosiy, bg-asosiy/50 (50% shaffof). Tailwind ularni HTML'da uchratgandagina yasaydi.

2.2 Namespace'lar

Eng ko'p ishlatiladiganlari:

Namespace Utilitalar «Bahor» misoli
--color-* bg-, text-, border- va boshqa rang bg-asosiy
--font-* font- (oila) font-sarlavha
--text-* text- (o'lcham) text-step-1
--spacing-* p-, m-, gap-, w-... p-m, gap-l
--radius-* rounded- rounded-m
--shadow-* shadow- shadow-2
--leading-* leading- leading-sarlavha
--breakpoint-* sm:, lg: kabi variantlar sm:
--animate-* animate- animate-yaltirash

text- ikki namespace'dan o'qiydi: --color-* dan rang, --text-* dan o'lcham. text-urgu — rang, text-step-1 — o'lcham. Tailwind nomni qaysi namespace'da topsa, shuni ishlatadi.

Namespace'siz nom esa hech narsa bermaydi. @theme { --rang-asosiy: red; } yozdik: bg-rang-asosiy yaratilmadi, o'zgaruvchining o'zi ham natijaga chiqmadi.

2.3 Faqat ishlatilgani chiqadi

Tajriba: @theme ga ikkita keraksiz token qo'shdik (--color-ishlatilmagan, --ishlatilmagan), HTML'da ularni ishlatmadik. Natijada ular yo'q. Tailwind 4 theme qatlamiga faqat utilitalar ishlatgan o'zgaruvchilarni chiqaradi. Shu sababli hatto yuzlab tokenli tema ham natijani shishirmaydi.

Ba'zan esa o'zgaruvchi utilitasiz ham kerak: masalan, uni oddiy CSS faylda yoki JavaScript'da var(--color-urgu) bilan o'qiysiz. Buning uchun @theme static bor — undagi hamma o'zgaruvchi doim chiqadi. Tekshirdik: @theme static { --color-hamma-vaqt: ...; } hech qayerda ishlatilmasa ham :root da paydo bo'ldi.

2.4 Tayyor palitrani tozalash

Tailwind o'zi bilan 20 dan ortiq rang oilasini olib keladi: red-50 dan stone-950 gacha. «Bahor» uchun ular xavfli: kimdir shoshilib text-orange-700 yozadi va brend buziladi.

css
@theme {
  --color-*: initial;
  --color-asosiy: oklch(47.5% 0.1 147.7);
  --color-urgu: oklch(53.7% 0.153 39.8);
}

--color-*: initial — "--color- bilan boshlangan hamma standart tokenni o'chir". Undan keyingi qatorlar o'zimiznikini qo'shadi. Endi bg-red-500 yozsangiz, natijada hech narsa chiqmaydi — tekshirdik. Xuddi shunday --radius-*: initial, --shadow-*: initial bor. --*: initial esa hamma namespace'ni tozalaydi — temani noldan quradigan dizayn tizimlari uchun.

Bu cheklov Dizayn tokenlari darsidagi qoidani kod darajasida himoya qiladi: palitradan tashqari rang yozishning imkoni qolmaydi.

Raqamli masofa (p-4, mt-6) boshqacha ishlaydi: u bitta --spacing qiymatiga ko'paytiriladi (calc(var(--spacing) * 4)). Uni ham o'chirish mumkin — --spacing: initial. Shunda p-4 yo'qoladi, faqat p-m kabi nomli masofalar qoladi. Jamoa kichik bo'lsa, buni qilmang: mt-px, w-1/2 kabi foydali utilitalar baribir qoladi, p-4 esa ko'p kutubxona misolida uchraydi.

Endi tokenlarni jonli ko'raylik. Natija oynasida Tailwind'ning brauzer versiyasi ishlaydi: u <style type="text/tailwindcss"> ichidagi CSS'ni o'qiydi va sahifadagi class'lardan utilitalar yasaydi. Bu faqat sinov uchun — real saytda CSS har doim CLI yoki Vite bilan oldindan yig'iladi.

html
<script
  src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4">
</script>
<style type="text/tailwindcss">
  @theme {
    --color-*: initial;
    --color-oq: oklch(100% 0 0);
    --color-fon: oklch(98.6% 0.014 84.6);
    --color-asosiy: oklch(47.5% 0.1 147.7);
    --color-urgu: oklch(53.7% 0.153 39.8);
    --spacing-m: 1rem;
    --radius-m: 0.5rem;
    --shadow-2: 0 1px 2px oklch(0% 0 0 / 12%),
      0 4px 12px oklch(0% 0 0 / 12%);
  }
</style>
<div class="bg-fon p-m font-sans">
  <article class="max-w-72 rounded-m bg-oq p-m shadow-2">
    <h3 class="text-xl font-bold text-asosiy">Osh</h3>
    <p class="font-bold text-urgu">35 000 so'm</p>
    <p class="bg-red-500 text-orange-700">Bu qator bezalmaydi</p>
  </article>
</div>

Nimaga qarang: karta qaymoq fonda oq, burchaklari yumaloq, ostida ikki qatlamli yumshoq soya. Sarlavha «Bahor» yashili, narx g'ishtdek qizg'ish. Oxirgi qator esa oddiy qora matn: bg-red-500 va text-orange-700 palitra tozalangani uchun umuman yaratilmadi. max-w-72 va text-xl ishladi — biz faqat ranglarni tozaladik.

Tekshirib ko'ring: @theme da --shadow-karta: 0 1px 2px black; yozdingiz. Qaysi class paydo bo'ladi? --karta-soya: ... deb yozsangiz-chi?

Javob

Birinchisida — shadow-karta: nom --shadow- namespace'i bilan boshlanadi. Ikkinchisida hech narsa: --karta- Tailwind biladigan namespace emas. Bunday qator @theme ichida foydasiz — oddiy o'zgaruvchi kerak bo'lsa, uni :root ga yozing.

3. «Bahor» tokenlari Tailwind'ga

3.1 Ikki yo'l

«Bahor»da tokenlar allaqachon bor — Qorong'i rejim darsida yakunlangan tokenlar.css: primitivlar, light-dark() bilan semantik --rang-*, data-tema bo'yicha color-scheme. Tailwind'ga ulashning ikki yo'li bor:

  1. Ko'chirish: hamma qiymatni @theme ga qayta yozish (--color-asosiy: oklch(...)). Yangi, Tailwind'dan boshlanadigan loyihada qulay.
  2. Ko'prik: tokenlar.css o'zgarmay qoladi, @theme esa unga faqat havola beradi: --color-asosiy: var(--rang-asosiy). Tokenlar bitta joyda yashaydi, Tailwind ularni "ko'radi".

«Bahor» uchun ikkinchisi to'g'ri: tokenlar.css Tailwind'siz sahifalarda ham ishlaydi, qorong'i rejim mantiqi esa uning ichida. Bu yo'l shadcn/ui kabi mashhur to'plamlarda ham ishlatiladi (Tailwind CSS 5 darsida ko'ramiz).

3.2 @theme inline — nega "inline"?

Ko'prik oddiy @theme bilan ham ishlayotganga o'xshaydi. Lekin bitta nozik joy bor. Ikkala usulni yonma-yon qo'yamiz. Pastki bo'lim data-tema="qorongi" bilan qorong'i — xuddi Qorong'i rejim darsidagi "bitta bo'lak qorong'i" holati:

html
<script
  src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4">
</script>
<style type="text/tailwindcss">
  @theme {
    --color-asosiy: var(--rang-asosiy);
  }
  @theme inline {
    --color-asosiy-inline: var(--rang-asosiy);
  }
  :root { --rang-asosiy: oklch(47.5% 0.1 147.7); }
  [data-tema="qorongi"] {
    --rang-asosiy: oklch(80.3% 0.098 150.8);
    background: oklch(28.2% 0.05 148.6);
  }
</style>
<section class="p-4">
  <p class="font-bold text-asosiy">Oddiy @theme</p>
  <p class="font-bold text-asosiy-inline">@theme inline</p>
</section>
<section class="p-4" data-tema="qorongi">
  <p class="font-bold text-asosiy">Oddiy @theme</p>
  <p class="font-bold text-asosiy-inline">@theme inline</p>
</section>

Nimaga qarang: tepada ikkala qator bir xil to'q yashil. Pastki to'q fonda esa "Oddiy @theme" to'q yashilligicha qoldi va zo'rg'a o'qiladi. "@theme inline" esa och yashilga o'tdi — to'g'ri.

Sababi natijadagi utilitalarda:

css
.text-asosiy {
  color: var(--color-asosiy);
}
.text-asosiy-inline {
  color: var(--rang-asosiy);
}

Oddiy @theme da utilita --color-asosiy ni o'qiydi. U esa :root da bir marta hisoblanadi: o'sha joydagi --rang-asosiy — to'q yashil. Bolalarga tayyor natija meros o'tadi, pastki bo'limdagi yangi --rang-asosiy uni o'zgartira olmaydi. inline da esa Tailwind havolani utilitaning ichiga yozadi: var(--rang-asosiy) har element uchun o'z joyida hisoblanadi.

Qoida: @theme dagi token boshqa o'zgaruvchiga (var(...)) tayansa — @theme inline. Qiymat tayyor son yoki rang bo'lsa — oddiy @theme.

3.3 Aksiya sahifasining kirish.css i

Endi to'liq ko'prik — jiyanning Tailwind'dagi aksiya sahifasi uchun. «Bahor»ning asosiy sayti oddiy CSS fayllarida qoladi; pastdagi utilita nomlari (bg-yuza, p-m, rounded-toliq …) faqat shu tajribada yashaydi. tokenlar.css Qorong'i rejim darsidagidek, unga tegmaymiz:

css
@import "tailwindcss";
@import "./tokenlar.css";

@theme inline {
  --color-*: initial;
  --color-fon: var(--rang-fon);
  --color-yuza: var(--rang-yuza);
  --color-matn: var(--rang-matn);
  --color-asosiy: var(--rang-asosiy);
  --color-asosiy-toq: var(--rang-asosiy-toq);
  --color-urgu: var(--rang-urgu);
  --color-ikkinchi: var(--rang-ikkinchi);

  --font-matn: var(--shrift-matn);
  --font-sarlavha: var(--shrift-sarlavha);
  --text-step--1: var(--step--1);
  --text-step-0: var(--step-0);
  --text-step-1: var(--step-1);
  --text-step-2: var(--step-2);
  --text-step-3: var(--step-3);
  --leading-matn: var(--qator-matn);
  --leading-sarlavha: var(--qator-sarlavha);

  --spacing-xs: var(--masofa-xs);
  --spacing-s: var(--masofa-s);
  --spacing-m: var(--masofa-m);
  --spacing-l: var(--masofa-l);
  --spacing-xl: var(--masofa-xl);

  --radius-*: initial;
  --radius-s: var(--burchak-s);
  --radius-m: var(--burchak-m);
  --radius-toliq: var(--burchak-toliq);
  --shadow-1: var(--soya-1);
  --shadow-2: var(--soya-2);
}

Uch izoh:

  • @import "./tokenlar.css" — CLI bu faylni o'qib, natijaga qo'shib yuboradi (tekshirdik: dist/natija.css da tokenlar.css ning qoidalari bor, alohida so'rov yo'q). CSS metodologiyalari darsidagi @import zanjiri muammosi bu yerda yo'q.
  • Faqat semantik tokenlar ulandi, primitivlar (--yashil-600) yo'q. --color-*: initial bilan birga bu shuni anglatadi: Tailwind'da bg-yashil-600 yozishning imkoni yo'q. Dizayn tokenlari darsidagi "komponent primitivni o'qimaydi" qoidasini endi vosita o'zi kuzatadi.
  • Masofada --spacing-2xs va --spacing-2xl ham shu tarzda ulanadi — joy tejash uchun yozmadik.

Endi aksiya kartasi shunday yoziladi:

html
<article class="rounded-m bg-yuza p-m shadow-2">
  <h3 class="font-sarlavha text-step-1 text-asosiy">Osh</h3>
  <p class="font-bold text-urgu">35 000 so'm</p>
</article>

Qorong'i rejimda ham to'g'ri: bg-yuza → var(--rang-yuza) → light-dark(...). Karta uchun bitta ham dark: yozilmadi.

3.4 Tuzoq: rounded-s

Yuqorida --radius-*: initial bejiz turmaydi. Birinchi urinishda uni yozmagan edik. rounded-s shunday chiqdi:

css
.rounded-s {
  border-radius: var(--radius-s);
  border-start-start-radius: 0.25rem;
  border-end-start-radius: 0.25rem;
}

Nimaga qarang: bitta class'da ikki xil utilita. Tailwind'da rounded-s allaqachon band — u Mantiqiy xususiyatlar darsidagi "start" (boshlanish) tomonini yumaloqlaydi. Bizning --radius-s tokenimiz shu nom bilan ustma-ust tushdi. --radius-*: initial standart radiuslarni o'chirgach, rounded-s faqat border-radius: var(--radius-s) beradi — tekshirdik.

Xulosa: token nomi Tailwind'ning mavjud so'zlari bilan to'qnashishi mumkin. Yangi token qo'shgach, natijadagi utilitani bir marta ko'zdan kechiring.

Tekshirib ko'ring: Nega --font-sarlavha: var(--shrift-sarlavha) @theme inline ichida, --color-* lar bilan birga? Oddiy @theme ga ko'chirsangiz, «Bahor»da nima buziladi?

Javob

Hozircha hech narsa ko'rinmaydi: --shrift-sarlavha sahifaning hech bir bo'lagida qayta belgilanmaydi. Lekin qoida bitta: var() bilan havola — inline. Ertaga bitta bo'lim uchun boshqa shrift berilsa (masalan, footer { --shrift-sarlavha: ... }), oddiy @theme bilan u footer'ga yetib bormasdi — xuddi qorong'i bo'limdagi yashil kabi.

4. Qorong'i rejim va @custom-variant

4.1 Standart dark:

Tailwind'da dark: prefiksi (Tailwind CSS 2 darsidagi variantlarga o'xshash) bor. Standart holatda natija shunday:

css
@media (prefers-color-scheme: dark) {
  .dark\:text-asosiy {
    color: var(--color-asosiy);
  }
}

Ya'ni dark: faqat tizim sozlamasini so'raydi. «Bahor»da esa foydalanuvchi o'zi tanlaydi va tanlov data-tema atributida (Qorong'i rejim darsidagi «Tanlov faqat @media da» xatosi aynan shu edi). Tizimi yorug', lekin "Qorong'i" ni tanlagan Malika dark: bilan yozilgan hech narsani ko'rmaydi.

4.2 dark: ni data-tema ga ulash

@custom-variant — o'z variantingizni yasash yoki mavjudini qayta belgilash:

css
@custom-variant dark
  (&:where([data-tema="qorongi"], [data-tema="qorongi"] *));

Qavs ichida — selektor. & — utilita class'i qo'yiladigan joy (Native CSS nesting darsidagi &). O'qilishi: "element o'zi data-tema="qorongi" bo'lsa yoki shunday elementning ichida bo'lsa". :where() og'irlikni nolga tushiradi — dark: class'i oddiy utilitadan kuchliroq bo'lib qolmaydi. Natija:

css
.dark\:text-urgu:where([data-tema="qorongi"],
  [data-tema="qorongi"] *) {
  color: var(--color-urgu);
}

Real loyihalarda ko'pincha .dark class'ini uchratasiz — next-themes kutubxonasi shunday qiladi: @custom-variant dark (&:where(.dark, .dark *));. G'oya bir xil, faqat atribut o'rniga class.

4.3 Uch holat: tizim ham, tanlov ham

Yuqoridagi variant endi tizimni bilmaydi: data-tema qo'yilmagan, tizimi qorong'i mehmon dark: ni ko'rmaydi. «Bahor»ga ikkalasi kerak — Qorong'i rejim darsidagi --rasm-filtr bayrog'i mantiqi. @custom-variant ning blokli shakli bunga imkon beradi:

css
@custom-variant dark {
  @media (prefers-color-scheme: dark) {
    &:where(:root:not([data-tema="yorug"]) *) {
      @slot;
    }
  }
  &:where([data-tema="qorongi"] *) {
    @slot;
  }
}

@slot — "utilitaning deklaratsiyalari shu yerga qo'yilsin". Blokda ikkita @slot — ikki shart, xuddi o'sha darsdagi "tizim qorong'i va yorug' tanlanmagan yoki qorong'i tanlangan". dark:bg-urgu uchun natija:

css
@media (prefers-color-scheme: dark) {
  .dark\:bg-urgu:where(:root:not([data-tema="yorug"]) *) {
    background-color: var(--color-urgu);
  }
}
.dark\:bg-urgu:where([data-tema="qorongi"] *) {
  background-color: var(--color-urgu);
}

4.4 «Bahor»da dark: deyarli kerak emas

Qarang: yuqoridagi karta qorong'i rejimga dark: siz o'tdi. Sabab — semantik tokenlar light-dark() bilan yozilgan, rejimni esa color-scheme hal qiladi. Tailwind'ning ko'p qo'llanmalari bg-white dark:bg-gray-900 text-gray-900 dark:text-white deb har elementga juft yozadi. Tokenli tizimda bu takror yo'q: bg-yuza text-matn.

dark: faqat rangga aylanmaydigan narsa uchun qoladi: soya, rasm filtri, chegara qalinligi. Buni jonli ko'raylik — natijadagi ikkinchi section da data-tema="qorongi":

html
<script
  src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4">
</script>
<style type="text/tailwindcss">
  @custom-variant dark
    (&:where([data-tema="qorongi"], [data-tema="qorongi"] *));
  :root {
    color-scheme: light;
    --yashil-900: oklch(28.2% 0.05 148.6);
    --oq: oklch(100% 0 0);
    --rang-fon: light-dark(oklch(98.6% 0.014 84.6),
      var(--yashil-900));
    --rang-yuza: light-dark(var(--oq),
      color-mix(in oklch, var(--yashil-900), var(--oq) 7%));
    --rang-asosiy: light-dark(oklch(47.5% 0.1 147.7),
      oklch(80.3% 0.098 150.8));
    --rang-matn: light-dark(oklch(27.2% 0.019 161),
      oklch(98.6% 0.014 84.6));
  }
  [data-tema="qorongi"] { color-scheme: dark; }
  @theme inline {
    --color-fon: var(--rang-fon);
    --color-yuza: var(--rang-yuza);
    --color-asosiy: var(--rang-asosiy);
    --color-matn: var(--rang-matn);
  }
</style>
<div class="grid gap-4 sm:grid-cols-2">
  <section class="bg-fon p-4 text-matn">
    <article
      class="rounded-lg bg-yuza p-4 shadow-md dark:shadow-none">
      <h3 class="font-bold text-asosiy">Manti</h3>
      <p>30 000 so'm</p>
    </article>
  </section>
  <section class="bg-fon p-4 text-matn" data-tema="qorongi">
    <article
      class="rounded-lg bg-yuza p-4 shadow-md dark:shadow-none">
      <h3 class="font-bold text-asosiy">Manti</h3>
      <p>30 000 so'm</p>
    </article>
  </section>
</div>

Nimaga qarang: ikki karta — bitta HTML. Chapdagisi qaymoq fonda oq, ostida soya. O'ngdagisi to'q yashil fonda, karta undan biroz yorqinroq, sarlavha och yashil, narx qaymoq rangda, soya yo'q. Ranglarni color-scheme va light-dark() almashtirdi, dark: faqat soyani olib tashladi. text-matn ni bejiz qo'ymadik: birinchi urinishda usiz yozgan edik va o'ngdagi narx qora qolgan edi. Brauzerning standart matn rangi <html> da bir marta hisoblanadi va ichki bo'lakka tayyor qora bo'lib meros o'tadi — xuddi «@theme inline — nega?» bo'limidagi holat.

4.5 Boshqa variantlar

@custom-variant faqat qorong'i rejim uchun emas. «Bahor» menyusi yuklanayotganda [aria-busy="true"] qo'yiladi (Micro-interaktsiyalar darsidagi skelet):

css
@custom-variant band (&[aria-busy="true"]);

Endi band:opacity-50 → .band\:opacity-50[aria-busy="true"] { opacity: 50%; }. Aslida Tailwind CSS 2 darsidagi aria-busy: yoki data-[...]: ham shuni qiladi. O'z nomli variant esa loyihada bir necha joyda takrorlanadigan holatga ma'noli nom beradi.

Tekshirib ko'ring: Nega @custom-variant dark (&:where(.dark *)); yozilgan loyihada <html class="dark"> ning o'zidagi dark:bg-yuza ishlamaydi?

Javob

.dark * — ".dark ning ichidagi element", o'zi emas. <html> ning o'zi o'z ichida emas. Shuning uchun to'liq shakl ikki qismli: &:where(.dark, .dark *) — "o'zi yoki ichidagisi". Upgrade vositasi v3 dan ko'chirganda ham &:is(... *) shaklini yozadi — ota elementdagi class'ga shu yetarli bo'lgani uchun.

5. @utility va qatlamlar

5.1 Oddiy utilita

Tailwind'da content-visibility: auto uchun utilita yo'q (tekshirdik: content-auto yaratilmadi). Bu xususiyat uzun sahifada ekrandan tashqaridagi bo'limlarni chizishni kechiktiradi — CSS yuklash samaradorligi darsida qayta uchraydi. O'zimiz qo'shamiz:

css
@utility content-auto {
  content-visibility: auto;
}

@utility bilan yozilgan class haqiqiy utilitaga aylanadi: utilities qatlamiga tushadi va variantlar bilan ishlaydi. md:content-auto yozdik — natijada @media (width >= 48rem) ichida chiqdi.

5.2 Funksional utilita

Oxiri -* bilan tugasa, utilita qiymat qabul qiladi. Micro-interaktsiyalar darsida kartalar navbat bilan (stagger) chiqar edi. Har kartaga kechikish:

css
@utility kechikish-* {
  animation-delay: calc(--value(integer) * 80ms);
}

--value(integer) — "class nomidagi butun sonni ol". kechikish-3 natijasi:

css
.kechikish-3 {
  animation-delay: calc(3 * 80ms);
}

--value() tema namespace'ini ham qabul qiladi: padding: --value(--spacing-*) — ichki-m → var(--spacing-m). To'liq imkoniyatlar Tailwind hujjatining "Adding custom utilities" bo'limida. Qo'lda utilita yozish kam kerak bo'ladi — avval mavjudini qidiring.

5.3 Tailwind qatlamlari va sizning CSS'ingiz

Kaskadni boshqarish darsida savol qoldirgan edik: Tailwind loyihasiga o'z CSS'ingizni qo'shsangiz, u qaysi qatlamga tushadi? Natija faylining birinchi qatorlari:

css
@layer properties;
@layer theme, base, components, utilities;

Tartib: tokenlar, Preflight (CSS reset darsi), komponentlar, utilitalar. Utilitalar oxirida — eng kuchli qatlam. Lekin o'sha darsdan eslang: qatlamsiz stil har qanday qatlamdan kuchli. kirish.css ga shunchaki yozilgan .taom-karta { padding: 2rem; } qatlamsiz qoladi (natijada u Tailwind qatlamlaridan keyin, hech qanday @layer siz chiqdi). Oqibati:

html
<script
  src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4">
</script>
<style type="text/tailwindcss">
  .karta-a { padding: 2rem; }
  @layer components {
    .karta-b { padding: 2rem; }
  }
</style>
<div class="flex gap-4">
  <p class="karta-a bg-amber-100 p-1">qatlamsiz + p-1</p>
  <p class="karta-b bg-amber-100 p-1">components + p-1</p>
</div>

Nimaga qarang: chap blokda katta ichki bo'shliq — p-1 yutqazdi, qatlamsiz .karta-a yutdi. O'ngdagisida bo'shliq kichik — components qatlami utilities dan oldin turadi, p-1 yutdi. Ikkala qoidaning og'irligi bir xil — farqni faqat qatlam berdi.

Qoida: Tailwind loyihasida o'z CSS'ingizni qatlamga qo'ying. Teglar uchun umumiy stil — @layer base, qayta ishlatiladigan class — @layer components. Shunda utilitalar ularni doim ustidan yoza oladi — Tailwind'ning butun g'oyasi shu.

Yana bir farq. v3 da @layer components dagi class variant bilan ham ishlardi: sm:taom-karta. v4 da — yo'q: tekshirdik, sm:taom-karta natijada chiqmadi. Variant kerak bo'lsa — @utility taom-karta { ... }.

flowchart LR
  T["theme<br/>tokenlar"] --> B["base<br/>Preflight"]
  B --> C["components<br/>.taom-karta"]
  C --> U["utilities<br/>p-1, bg-yuza"]
  U --> Q["qatlamsiz<br/>eng kuchli"]

Nimaga qarang: o'ngga qarab kuch ortadi. Qatlamsiz stil — eng o'ngda. Tailwind loyihasida u yerda odatda hech narsa bo'lmasligi kerak.

Tekshirib ko'ring: kirish.css da @layer base { h1 { font-size: 2rem; } }, HTML'da esa <h1 class="text-xl">. Sarlavha qaysi o'lchamda chiqadi? @layer base ni olib tashlab, qoidani qatlamsiz qoldirsangiz-chi?

Javob

Birinchi holatda — text-xl (1.25rem): utilities qatlami base dan keyin turadi va yutadi. Ikkinchi holatda — 2rem: qatlamsiz h1 qoidasi hamma qatlamdan kuchli, text-xl yutqazadi. Og'irlik bu yerda ahamiyatsiz — h1 (0,0,1) .text-xl (0,1,0) dan yengil bo'lsa ham yutadi, chunki qatlamlar og'irlikdan oldin solishtiriladi.

6. @source: Tailwind qayerga qaraydi

Tailwind CSS 1 darsidan eslang: Tailwind fayllardagi class nomlarini o'zi topadi. Ba'zan unga yordam kerak:

css
@import "tailwindcss";
@source "../node_modules/menyu-vidjeti";
@source not "../eski";
@source inline("bg-urgu underline");
  • @source "yo'l" — qo'shimcha joy. Masalan, node_modules ichidagi kutubxona: u yerni Tailwind o'zi skanerlamaydi.
  • @source not "yo'l" — bu joyga qarama. Tekshirdik: eski/eski.html dagi bg-red-500 qator olib tashlanganda natijaga kirardi, @source not "../eski" bilan — kirmadi.
  • @source inline("...") — HTML'da uchramasa ham shu class'larni yasash (v3 dagi safelist). Class nomi keyinroq, masalan server ma'lumotidan kelsa kerak bo'ladi. Tekshirdik: bg-urgu va underline hech bir faylda yo'q edi, natijada bor.

Yo'llar kirish.css ga nisbatan yoziladi. .gitignore dagi fayllarni Tailwind ataylab skanerlamaydi — .gitignore nimaligini 07-qismda ko'rasiz.

7. v3 dan v4 ga

7.1 tailwind.config.js — eski loyihalarda

2025-yilgacha yozilgan Tailwind loyihalarining deyarli hammasi v3 da. U yerda sozlama JavaScript faylida:

js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ["./**/*.html"],
  darkMode: ["class", '[data-tema="qorongi"]'],
  theme: {
    extend: {
      colors: {
        asosiy: "#2f6b3a",
        urgu: "#b4461a",
      },
      fontFamily: {
        sarlavha: ['"Bahor"', '"Bahor zaxira"', "serif"],
      },
    },
  },
  plugins: [],
};

Bu JavaScript — uni 08-qismdan keyin to'liq o'qiysiz. Hozir tanib olish yetadi: content — qaysi fayllar skanerlanadi (v4 da avtomatik va @source), theme.extend — @theme, darkMode — @custom-variant dark. CSS esa uch direktiva bilan boshlanardi: @tailwind base; @tailwind components; @tailwind utilities;.

7.2 npx @tailwindcss/upgrade

Ko'chirishni rasmiy vosita qiladi. Yuqoridagi konfiguratsiyali kichik v3 loyihada (Tailwind 3.4.19) ishga tushirdik:

bash
npx @tailwindcss/upgrade --force

Vosita konfiguratsiyani CSS'ga ko'chirdi, tailwind.config.js ni o'chirdi va package.json dagi versiyani 4.3.3 ga ko'tardi. Yangi kirish.css (vosita yozgan izohni qisqartirdik):

css
@import 'tailwindcss';

@custom-variant dark (&:is([data-tema="qorongi"] *));

@theme {
  --color-asosiy: #2f6b3a;
  --color-urgu: #b4461a;

  --font-sarlavha: 'Bahor', 'Bahor zaxira', serif;
}

@layer base {
  *,
  ::after,
  ::before,
  ::backdrop,
  ::file-selector-button {
    border-color: var(--color-gray-200, currentcolor);
  }
}

@utility bron-havola {
  @apply rounded-lg bg-asosiy px-4 py-2 text-white;
}

Nimaga qarang: @layer components dagi .bron-havola @utility ga aylandi — «Tailwind qatlamlari va sizning CSS'ingiz» bo'limidagi v4 qoidasi. @layer base bloki — moslik uchun: v4 da chegaraning standart rangi currentcolor bo'ldi, v3 da kulrang edi. Vosita "ko'rinish o'zgarmasin" deb eski rangni qaytardi. @apply ni keyingi darsda o'rganamiz.

HTML ham o'zgardi — ba'zi class nomlari v4 da boshqa ma'noga ega:

v3 v4 (vosita almashtirdi)
shadow-sm shadow-xs
rounded rounded-sm
outline-none outline-hidden
ring ring-3

v4 da o'lchamlar shkalasi bir pog'ona surildi: v3 dagi shadow-sm ko'rinishi endi shadow-xs deb ataladi. Shuning uchun class'larni qo'lda almashtirmang — vosita buni hamma HTML faylda qiladi.

Ikki eslatma:

  • Terminalda fatal: not a git repository qatori ham chiqdi. Vosita o'zgarishlarni git bilan ko'rsatishga harakat qiladi. Git — 07-qismda. Git'li loyihada --force kerak emas, lekin vosita "ishchi papka toza bo'lsin" deb talab qiladi — xato bo'lsa, qaytarish oson bo'lishi uchun.
  • Vosita faqat tailwindcss paketini yangiladi. CLI kerak bo'lsa, @tailwindcss/cli ni alohida o'rnating.

7.3 @config va @plugin

Ba'zan JS konfiguratsiyani darhol ko'chirib bo'lmaydi — masalan, v3 plagini unga tayanadi. v4 uni CSS'dan ulay oladi:

css
@import "tailwindcss";
@config "./tailwind.config.js";

Tekshirdik: text-asosiy ishladi, lekin natija boshqacha — color: #2f6b3a. @config dan kelgan qiymat utilitaning ichiga to'g'ridan-to'g'ri yoziladi, --color-asosiy o'zgaruvchisi yo'q. Demak, u bilan temani CSS'dan boshqarib bo'lmaydi. @config — ko'prik, maqsad emas.

@plugin "@tailwindcss/typography"; — plaginni ulash. Plaginlar Tailwind CSS 5 darsining mavzusi.

8. Ko'p uchraydigan xatolar

8.1 var() li token oddiy @theme da

@theme { --color-fon: var(--rang-fon); } — sahifa bo'ylab ishlaydi, lekin data-tema li bo'lakda eski rang qoladi ("@theme inline — nega?" bo'limidagi natija). Tuzatish: @theme inline.

8.2 @theme ni @media ichiga yozish

"Katta ekranda boshqa masofa" deb @media (width >= 40rem) { @theme { ... } } yozildi. Tailwind xato bermaydi — lekin tekshirdik, token media shartisiz, hamma ekran uchun :root ga chiqdi. @theme faqat eng yuqori darajada yoziladi. Tuzatish: o'zgaradigan qiymatni oddiy CSS o'zgaruvchisiga yozing (@media ichida :root { --masofa-m: ... }) va @theme inline bilan ulang — yoki fluid clamp() (Fluid tipografiya).

8.3 Nom to'qnashuvi

--radius-s → rounded-s ikki utilita bo'lib chiqdi. Tuzatish: namespace'ni initial bilan tozalang yoki boshqa nom tanlang; natijani ko'zdan kechiring.

8.4 Qatlamsiz komponent

.taom-karta { padding: 2rem; } qatlamsiz — HTML'dagi p-2 ishlamaydi. Tuzatish: @layer components ichiga.

8.5 dark: ishlamayapti

data-tema="qorongi" qo'yildi, dark:shadow-none esa ta'sir qilmaydi. dark: hali ham standart prefers-color-scheme da. Tuzatish: @custom-variant dark (...).

9. Mashqlar

Mashqlar kurs/mashqlar/06/tailwind/ da — Tailwind CSS 1 darsidagi loyihada.

1-mashq (oson): qaysi class?

@theme da quyidagilar bor. Har biri qaysi class'ni beradi — yoki hech narsa bermaydimi?

  1. --color-aksiya: oklch(53.7% 0.153 39.8);
  2. --spacing-karta: 1.25rem;
  3. --menyu-eni: 20rem;
  4. --text-narx: 1.25rem;
  5. --animate-yaltirash: yaltirash 1.5s ease-in-out infinite;

Ishora: "Namespace'lar" jadvali.

Yechim
  1. bg-aksiya, text-aksiya, border-aksiya va boshqa rang utilitalari.
  2. p-karta, m-karta, gap-karta, w-karta va boshqa masofa/o'lcham utilitalari.
  3. Hech narsa — --menyu- namespace emas. O'zgaruvchi natijaga ham chiqmaydi.
  4. text-narx — shrift o'lchami. --text-* namespace'i.
  5. animate-yaltirash. Lekin @keyframes yaltirash ham kerak: uni @theme ichiga yozsangiz, animatsiya ishlatilgandagina natijaga chiqadi. Harakat uchun motion-safe:animate-yaltirash (prefers-reduced-motion).

2-mashq (o'rta): band va qorong'i rejim

«Bahor» menyusining Tailwind variantida:

  1. band: variantini yozing — element o'zi aria-busy="true" bo'lganda.
  2. dark: ni «Bahor»ning uch holatli qoidasiga ulang: tizim qorong'i va data-tema="yorug" emas — yoki data-tema="qorongi".
  3. <div aria-busy="true" class="band:opacity-60 dark:shadow-none"> uchun natijada qanday selektorlar chiqishini yozing, keyin CLI bilan tekshiring.

Ishora: blokli @custom-variant va @slot.

Yechim
css
@custom-variant band (&[aria-busy="true"]);

@custom-variant dark {
  @media (prefers-color-scheme: dark) {
    &:where(:root:not([data-tema="yorug"]) *) {
      @slot;
    }
  }
  &:where([data-tema="qorongi"] *) {
    @slot;
  }
}

Natija (qisqartirilmagan selektorlar):

css
.band\:opacity-60[aria-busy="true"] { opacity: 60%; }

@media (prefers-color-scheme: dark) {
  .dark\:shadow-none:where(:root:not([data-tema="yorug"]) *) { ... }
}
.dark\:shadow-none:where([data-tema="qorongi"] *) { ... }

:root:not(...) * — "<html> ning ichidagi" degani, shuning uchun div ga ta'sir qiladi. data-tema esa <html> da, div uning ichida — ikkinchi shart ham ishlaydi.

3-mashq (qiyin): v3 konfiguratsiyani qo'lda ko'chiring

Eski loyihada shunday konfiguratsiya bor:

js
module.exports = {
  theme: {
    extend: {
      colors: { asosiy: "#2f6b3a", yuza: "var(--rang-yuza)" },
      spacing: { karta: "1.25rem" },
      borderRadius: { karta: "0.75rem" },
      screens: { planshet: "40rem" },
    },
  },
};
  1. Uni @theme ga yozing. Qaysi qator inline ga ketadi?
  2. screens qaysi namespace? Natijada planshet:p-karta qanday media query beradi?
  3. Upgrade vositasi bilan solishtiring: kichik v3 loyiha yarating (npm install --save-dev tailwindcss@3), shu konfiguratsiyani qo'ying va npx @tailwindcss/upgrade --force.

Ishora: borderRadius → --radius-*, screens → --breakpoint-*.

Yechim
css
@import "tailwindcss";

@theme {
  --color-asosiy: #2f6b3a;
  --spacing-karta: 1.25rem;
  --radius-karta: 0.75rem;
  --breakpoint-planshet: 40rem;
}

@theme inline {
  --color-yuza: var(--rang-yuza);
}

yuza — var() ga tayanadi, shuning uchun inline. planshet:p-karta → @media (width >= 40rem) { .planshet\:p-karta { padding: var(--spacing-karta); } }. Breakpoint ham token: sm: aynan --breakpoint-sm: 40rem dan chiqadi. Tailwind'ning sm (40rem) va lg (64rem) i «Bahor» breakpointlari bilan bir xil — «Bahor» uchun yangi nom shart emas.

Vosita bilan tekshirdik: u --color-yuza: var(--rang-yuza); ni oddiy @theme ga qo'ydi — var() ning qayerda o'zgarishini u bilmaydi. Natijani o'qing va kerak bo'lsa inline ga o'tkazing: vosita yaxshi yordamchi, lekin oxirgi so'z sizda.

4-mashq: Portfolio qadami — portfolio tokenlari Tailwind'da

Portfolio Tailwind'ga o'tmaydi — u oddiy CSS fayllarda qoladi. Lekin tajriba foydali: tokenlaringiz Tailwind'da qanday ko'rinishini ko'rasiz. Ishni tajriba/ papkasida qiling (Sass/SCSS 1 darsidagi papka, saytga chiqmaydi).

  1. tajriba/tailwind/ da npm install --save-dev tailwindcss @tailwindcss/cli.
  2. kirish.css: @import "tailwindcss";, portfolio'ning tokenlar.css iga @import (Dizayn tokenlari darsidagi fayl, nusxasi).
  3. @theme inline bilan ulang: ranglar (--rang-*, palitra tozalangan), --shrift-matn/--shrift-sarlavha, --step--1…--step-2, --masofa-*, --burchak-m, --soya-1.
  4. karta.html da loyihalar kartasini (Yakuniy loyiha darsidagi article) faqat utilitalar bilan qayta yozing. Portfolio'dagi asl karta bilan 360 va 1280 pikselda solishtiring.
  5. Qaysi qiymat uchun token yetmadi?

Ishora: --color-*: initial dan keyin portfolio'ning --rang-chegara, --rang-fon-och ham kerak bo'ladi — ular color-mix() bilan hisoblanadi, lekin ulash xuddi shunday.

Yechim

tajriba/tailwind/kirish.css:

css
@import "tailwindcss";
@import "./tokenlar.css";

@theme inline {
  --color-*: initial;
  --color-fon: var(--rang-fon);
  --color-fon-och: var(--rang-fon-och);
  --color-matn: var(--rang-matn);
  --color-asosiy: var(--rang-asosiy);
  --color-ikkinchi: var(--rang-ikkinchi);
  --color-chegara: var(--rang-chegara);
  --color-urgu: var(--rang-urgu);

  --font-matn: var(--shrift-matn);
  --font-sarlavha: var(--shrift-sarlavha);
  --text-step--1: var(--step--1);
  --text-step-0: var(--step-0);
  --text-step-1: var(--step-1);
  --text-step-2: var(--step-2);

  --spacing-xs: var(--masofa-xs);
  --spacing-s: var(--masofa-s);
  --spacing-m: var(--masofa-m);
  --spacing-l: var(--masofa-l);

  --radius-*: initial;
  --radius-m: var(--burchak-m);
  --shadow-1: var(--soya-1);
}

karta.html:

html
<article class="grid gap-s rounded-m border border-chegara
  bg-fon p-m shadow-1">
  <h3 class="font-sarlavha text-step-1 text-asosiy">«Bahor»</h3>
  <p class="text-step-0 text-matn">Choyxona uchun sayt</p>
  <a class="text-asosiy underline" href="loyihalar/bahor/">
    Batafsil
  </a>
</article>

Ko'rinish asl kartaga yaqin chiqadi. Farqlar odatda ikki joyda: subgrid (subgrid) — grid-rows-subgrid row-span-4 kabi utilitalar bilan qo'shiladi; havola chizig'ining sozlamalari (Matn bezagi) — underline-offset-*, decoration-*. Bu — oxirgi bandning javobi: Tailwind'da token emas, utilita yetishmaydi, tokenlar esa to'liq ko'chdi.

Xulosani yozib qo'ying: portfolio oddiy CSS'da qoladi (build qadami yo'q, fayllar kichik). Tailwind tajribasi esa Yakuniy loyiha: landing darsida tanlov qilishingizga yordam beradi.

10. Real ishda

  • shadcn/ui — React loyihalarida eng mashhur komponentlar to'plami. Uning CSS fayli aynan shu darsdagi ko'prik: :root da --background, --primary, .dark da ularning qorong'i qiymatlari va @theme inline { --color-background: var(--background); }. Bugun buni o'qiy olasiz.
  • Dizayn tizimlari Figma o'zgaruvchilarini @theme ga eksport qiladi (Dizayn tokenlari darsidagi Style Dictionary zanjiri). Tokenlar nomi dizaynda ham, class'da ham bir xil.
  • Eski loyihalar. Ishga kirganda ko'pincha v3 va tailwind.config.js ni uchratasiz. Migratsiya — tipik vazifa: upgrade vositasi, keyin natijani qo'lda ko'rib chiqish.
  • Intervyuda so'raladi: "Tailwind v4 da tema qayerda sozlanadi?", "@theme va @theme inline farqi?", "Qorong'i rejimni class bilan qanday boshqarasiz?", "O'z CSS'ingiz Tailwind utilitasidan nega yutib qo'yishi mumkin?".

Xulosa

  • Tailwind v4 sozlamasi CSS'da: @theme dagi --color-*, --spacing-* kabi token utilita va :root o'zgaruvchisiga aylanadi.
  • Token var() ga tayansa — @theme inline, aks holda ichki bo'lakdagi qayta belgilash ishlamaydi.
  • --color-*: initial tayyor palitrani o'chiradi — brend va tokenlar qoidasini vosita himoya qiladi.
  • «Bahor» light-dark() tokenlari bilan ranglar dark: siz almashadi; dark: ni @custom-variant bilan data-tema ga ulang.
  • O'z utilitangiz — @utility, o'z CSS'ingiz — @layer base/components ichida; qatlamsiz stil utilitalardan kuchli.
  • v3 loyiha — npx @tailwindcss/upgrade; @config faqat vaqtinchalik ko'prik.

Keyingi dars: Tailwind CSS 4: komponent naqshlari — uzun class ro'yxatlarini cn(), cva va @apply bilan qayta ishlatiladigan komponentga aylantiramiz.

Manbalar

  • Tailwind CSS: "Theme variables", "Adding custom styles", "Functions and directives", "Dark mode", "Detecting classes in source files", "Upgrade guide" — tailwindcss.com/docs
  • MDN: "@layer", "Using CSS custom properties" — developer.mozilla.org
  • shadcn/ui: "Theming" — ui.shadcn.com/docs/theming
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Tailwind CSS 3: v4 konfiguratsiyasi — @theme, @utility va @custom-variant — IlmHamroh