IlmHamroh
JavaScript Full-stack/6-qism. CSS: harakat, zamonaviy CSS va dizayn31/57-dars19 daqiqa
Mundarija (32)

CSS-in-JS: runtime va zero-runtime yondashuvlar

Qisqacha: CSS-in-JS — stilni alohida .css faylda emas, JavaScript fayli ichida, komponent yonida yozish usuli. Runtime kutubxonalar (styled-components, Emotion) CSS'ni brauzerda, sahifa ishlayotganda yasaydi — bu qulay, lekin JavaScript hajmi va tezlik narxi bor. Zero-runtime vositalar (vanilla-extract, Linaria, Panda CSS, StyleX) xuddi shu yozuvni build paytida oddiy .css faylga aylantiradi. Dinamik qiymatlar uchun ikkalasida ham eng arzon yo'l — CSS o'zgaruvchilari.

Bu darsda

  • CSS-in-JS qaysi muammoni hal qilishini va nega paydo bo'lganini tushuntira olasiz.
  • styled-components va Emotion natijasini (haqiqiy chiqishni) o'qib, "runtime narxi" nimadan iboratligini ayta olasiz.
  • Zero-runtime vositalar build'da nima qilishini vanilla-extract misolida ko'rasiz.
  • Nega sanoat zero-runtime va CSS o'zgaruvchilari tomon siljiganini (React Server Components, styled-components holati) bilasiz.
  • Loyiha uchun CSS Modules, Tailwind va CSS-in-JS orasidan asosli tanlov qila olasiz.

Oldin bilishingiz kerak: CSS Modules, CSS o'zgaruvchilari 2, CSS metodologiyalari.

1. Nega bu kerak?

CSS Modules darsida nom to'qnashuvini build vositasi bilan yechdik: har fayl o'z hash'ini oldi. Lekin stil baribir alohida faylda qoldi. Komponent — TaomKarta.js, uning ko'rinishi — taom-karta.module.css. Ikki fayl, ikki joy.

Endi tasavvur qiling: «Bahor» menyusi ilovaga aylandi. Taom tugasa, karta xiralashadi. Aksiya bo'lsa, narx qizg'ish. Bu holatlar JavaScript'da saqlanadi: tugadi = true, aksiya = false. Stil esa CSS faylida. Dasturchi har safar ikki fayl orasida yuguradi va "bu class qayerda ishlatilgan?" deb qidiradi.

2014–2016-yillarda React (komponentlardan interfeys yig'adigan JavaScript kutubxonasi — 17-qismda o'rganamiz, hozir bilish shart emas) jamoasi va boshqa dasturchilar savol berishdi: stil ham komponentning bir qismi-ku, nega uni o'sha faylga yozmaymiz? Shunday qilib CSS-in-JS paydo bo'ldi.

Hayotiy o'xshatish. Choyxonada ikki xil oshpaz bor. Birinchisi mehmon kelgandan keyin boshlaydi: sabzini to'g'raydi, go'shtni qovuradi — har buyurtma yangidan. Taom mehmonga aynan mos, lekin kutish kerak. Ikkinchisi ertalab hamma masalliqni tayyorlab qo'yadi, mehmon kelganda faqat suzadi. Birinchisi — runtime (ish paytida), ikkinchisi — zero-runtime (ish paytida nol qo'shimcha ish). Bu dars — shu ikki oshpaz haqida.

Maslahat: Bu darsda JavaScript kodi ko'p ko'rinadi, lekin siz uni yozmaysiz — faqat o'qiysiz. Har qatorning ma'nosini oddiy so'z bilan aytamiz. Natijalar — biz haqiqiy vositalarda ishga tushirib olgan chiqishlar, o'zgarishsiz.

2. Runtime CSS-in-JS: styled-components

2.1 Yozuv qanday ko'rinadi

Eng mashhur runtime kutubxona — styled-components. Unda stil shunday yoziladi:

js
import styled from "styled-components";

const Narx = styled.p`
  color: #b4461a;
  font-weight: bold;
  font-size: ${(props) => (props.$katta ? "1.5rem" : "1rem")};
`;

So'zlar bilan:

  • styled.p — "p elementidan yangi komponent yasa". Natija — Narx degan komponent. React'da uni <Narx>35 000 so'm</Narx> deb ishlatadilar — bu yozuv (JSX) 17-qismda.
  • Ikki backtick (klaviaturadagi teskari tirnoq) orasidagi matn — oddiy CSS deklaratsiyalari. Backtick'li satrni JavaScript'da template literal deyiladi — 08-qismda o'rganasiz.
  • styled.p backtick'ning oldida turibdi. Bu — "teg": JavaScript satrni o'sha funksiyaga beradi, u esa satrdan CSS yasaydi. Bu imkoniyat — Tagged template literals. 08-qismda "CSS-in-JS kutubxonalari backtick oldidagi teg bilan ishlaydi" degan gapni o'qiganingizda — aynan shu yozuvni eslang.
  • props — komponentga tashqaridan beriladigan qiymatlar. HTML atributiga o'xshaydi: <Narx $katta> deb yozilsa, komponent ichida props.$katta "rost" bo'ladi. Oldidagi $ — styled-components kelishuvi: "bu qiymat faqat stil uchun, HTML'ga chiqmasin".
  • ${...} ichidagisi — kichik funksiya: "$katta belgisi bo'lsa 1.5rem, bo'lmasa 1rem". Stil qiymati JavaScript'dan keladi. CSS Modules buni qila olmaydi.

Oddiy CSS'ga o'xshaydimi? Ha, ataylab. Dasturchi CSS'ni o'zgartirmasdan yozadi, kutubxona esa class nomini o'zi o'ylab topadi. CSS Modules dagidek, nom to'qnashuvi yo'q.

2.2 Haqiqiy natija

Brauzer JavaScript faylini emas, HTML va CSS'ni chizadi. Unda styled-components nima yasaydi? Buni ko'rish uchun kodni Node'da, serverda chizish rejimida ishga tushirdik (styled-components 6.5.3, React 19.3.0). Ikkita narx: biri oddiy, biri $katta bilan.

Chiqqan HTML (bitta qatorda chiqdi, o'qish uchun bo'ldik):

html
<div>
  <p class="sc-bdvwhi fqYBio">35 000 so'm</p>
  <p class="sc-bdvwhi lenGif">5 000 so'm</p>
</div>

Chiqqan CSS (<style data-styled="true"> ichida, qator ko'chirishlarni o'qish uchun qo'shdik):

css
.fqYBio {
  color: #b4461a;
  font-weight: bold;
  font-size: 1rem;
}
.lenGif {
  color: #b4461a;
  font-weight: bold;
  font-size: 1.5rem;
}

Nomlarni o'qiymiz:

  • sc-bdvwhi — komponentning doimiy nomi ("sc" — styled-components). Ikkala p da bir xil: ikkalasi Narx komponenti.
  • fqYBio va lenGif — stil hash'i. Kutubxona tayyor CSS matnidan qisqa "barmoq izi" hisobladi. Matn boshqa — nom boshqa.

Brauzer ko'radigan natija — xuddi shu HTML va CSS:

html
<style>
  .fqYBio {
    color: #b4461a;
    font-weight: bold;
    font-size: 1rem;
  }
  .lenGif {
    color: #b4461a;
    font-weight: bold;
    font-size: 1.5rem;
  }
  body { font-family: system-ui, sans-serif; }
</style>
<div>
  <p class="sc-bdvwhi fqYBio">35 000 so'm</p>
  <p class="sc-bdvwhi lenGif">5 000 so'm</p>
</div>

Nimaga qarang: ikkala narx qizg'ish va qalin, ikkinchisi kattaroq. Lekin CSS'da ikkita to'liq qoida bor: color va font-weight ikki marta yozilgan. Faqat bitta qiymat farq qilgani uchun kutubxona butun qoidani qayta yasadi. Bu — runtime narxining birinchi belgisi.

2.3 Emotion: yana bir runtime kutubxona

Emotion — styled-components'ning eng yaqin raqibi. Uning React'siz ham ishlaydigan css funksiyasi bor. Uni ham Node'da ishga tushirdik (@emotion/css 11.13.5):

js
import { css } from "@emotion/css";

const narx = css`
  color: #b4461a;
  font-weight: bold;
`;
const katta = css({ fontSize: "1.5rem", color: "#1a5d1a" });
console.log(narx);
console.log(katta);

Konsolda:

text
css-173gp4r
css-6dp47w

Yig'ilgan CSS (bo'sh joylarni o'qish uchun qo'shdik):

css
.css-173gp4r { color: #b4461a; font-weight: bold; }
.css-6dp47w { font-size: 1.5rem; color: #1a5d1a; }

Ikki yozuv shakli bor. Birinchisi — backtick'li, styled-components'dagidek. Ikkinchisi — obyekt: { fontSize: "1.5rem" }. Obyektda xususiyat nomi camelCase bo'ladi (fontSize), chunki JavaScript nomida chiziqcha bo'lmaydi — CSS Modules darsidagi karta["taom-karta"] muammosi eslang. Natijada kutubxona uni yana font-size ga qaytaradi.

Emotion'ning React'dagi mashhur imkoniyati — css prop: stilni to'g'ridan-to'g'ri elementning atributiga yozish (<p css={...}>). Buning uchun loyihada maxsus sozlama kerak. React'ni bilmay turib uni ko'rsatmaymiz — mohiyati bir xil: satr yoki obyekt → hash → <style>.

Tekshirib ko'ring: styled-components'da uchta narx bor: 1rem, 1rem va 1.5rem. Nechta CSS qoidasi yasaladi?

Javob

Ikkita. Hash CSS matnidan hisoblanadi: birinchi ikkita narxning matni aynan bir xil (font-size: 1rem), shuning uchun ular bitta class'ni (fqYBio kabi) bo'lishadi. Uchinchisining matni boshqa — ikkinchi qoida. Qoida soni narx soniga emas, turli qiymatlar soniga bog'liq.

3. Runtime narxi

3.1 Brauzerda nima bo'ladi

Runtime kutubxona brauzerda har safar komponent chizilganda quyidagi ishni qiladi:

flowchart TD
  A["JS fayl yuklanadi<br/>(kutubxona ham)"] --> B["Komponent chiziladi"]
  B --> C["Stil matni yig'iladi<br/>props qiymatlari bilan"]
  C --> D["Matndan hash<br/>hisoblanadi"]
  D --> E{"Bu hash<br/>bormi?"}
  E -- "yo'q" --> F["style tegiga<br/>yangi qoida"]
  E -- "bor" --> G["Tayyor class"]
  F --> H["Brauzer stilni<br/>qayta hisoblaydi"]

Nimaga qarang: oddiy CSS faylda bu qadamlarning hech biri yo'q — brauzer faylni o'qiydi va tamom. Runtime kutubxonada esa har chizishda satr yig'iladi va hash hisoblanadi. Yangi qoida qo'shilsa, brauzer sahifa stillarini qayta hisoblaydi (Rendering pipeline darsidagi "Style" bosqichi).

Uch xil narx bor:

  1. Yuklash narxi. Kutubxonaning o'zi JavaScript fayli — foydalanuvchi uni yuklab olishi kerak.
  2. Ishlash narxi. Har chizishda satr yig'ish va hash. Tez-tez o'zgaradigan qiymatda (masalan, sichqoncha orqasidan yuradigan element) bu sezilarli bo'ladi.
  3. Birinchi ko'rinish. JavaScript yuklanib ishlamaguncha, stil yo'q. Serverda oldindan yig'ib qo'ymasangiz, sahifa bir lahza stilsiz ko'rinadi — FOUC (flash of unstyled content — "stilsiz bir lahza").

3.2 Yuklash narxi — o'lchadik

Bir xil kichik komponentni uch vosita bilan yozib, esbuild 0.28.2 bilan siqilgan (minify) holda yig'dik. React'ning o'zi hisobga olinmadi — faqat CSS vositasining ulushi:

Vosita Siqilgan JS gzip bilan
styled-components 6.5.3 26 881 bayt 11 101 bayt
@emotion/css 11.13.5 15 284 bayt 6 300 bayt
vanilla-extract 1.21.2 73 bayt 78 bayt

Nimaga qarang: vanilla-extract'ning 73 bayti — bu kutubxona emas, faqat class nomlari satrlari. Nega bunday — «Zero-runtime» bo'limida ko'ramiz. gzip — server faylni brauzerga yuborishdan oldin siqadigan usul (CSS yuklash samaradorligi darsida batafsil): foydalanuvchi taxminan shu hajmni yuklab oladi.

11 KB kichik ko'rinadi. Lekin sekin mobil internetda har KB ahamiyatga ega — Aziz ham, «Bahor»ning ko'p mijozlari ham telefondan kiradi.

3.3 Server va React Server Components

Yirik saytlar sahifani avval serverda chizadi (SSR — server-side rendering), foydalanuvchi esa tayyor HTML oladi. Runtime CSS-in-JS uchun bu qo'shimcha ish: serverda yasalgan stillarni yig'ib, HTML'ga qo'shish kerak. Biz yuqoridagi natijani aynan shu bilan oldik — styled-components'ning ServerStyleSheet yig'uvchisi bilan.

Keyin React'ga Server Components (RSC) keldi: komponent faqat serverda ishlaydi va brauzerga JavaScript'i umuman bormaydi (Server Components, 23-qism). Runtime CSS-in-JS esa aynan brauzerdagi JavaScript'ga tayanadi. Next.js 16.3 hujjati buni ochiq yozadi: styled-components va boshqalar faqat Client Components ichida qo'llab-quvvatlanadi, Emotion esa ro'yxatda hali "qo'llab-quvvatlash ustida ishlanmoqda" qatorida. Sozlash uchun alohida "stil registri" fayli kerak.

Diqqat: Runtime kutubxona stilni <style> tegi sifatida sahifaga qo'shadi. «Bahor»dagi kabi qat'iy CSP (HTML darajasidagi xavfsizlik darsidagi Content Security Policy) bunday tegni to'sadi. Kutubxonalar buning uchun maxsus sozlama (nonce) beradi, lekin bu yana bir qadam. Oddiy .css fayl bilan bu muammo yo'q.

3.4 styled-components hozir qanday holatda

2025-yil 17-martda styled-components'ning asosiy qo'llab-quvvatlovchisi Evan Jacobs kutubxona maintenance mode (faqat qo'llab-quvvatlash rejimi) ga o'tishini e'lon qildi. Sababi sifatida React Server Components va React'ning Context API'ga munosabatini ko'rsatdi. (Context — React'da ma'lumotni ko'p komponentga birdaniga uzatish usuli; styled-components tema ranglarini shu orqali tarqatadi. Server Components'da esa Context ishlamaydi.) Ma'nosi: katta yangi imkoniyatlar kutilmaydi, asosiy e'tibor — xatolarni tuzatishga.

Lekin "o'ldi" degani emas. Rasmiy blogdagi 2026-yil apreldagi maqolada muallif "maintenance mode — o'lim emas" deb yozdi. 6.4 versiyasida CSS o'zgaruvchilari bilan ishlaydigan createTheme qo'shildi va tezlik yaxshilandi. npm'da hozir 6.5.3 versiya. Minglab loyihalar uni ishlatadi va yana yillar ishlatadi.

Xulosa: ishga kirsangiz, styled-components'ni mavjud loyihada uchratishingiz ehtimoli katta — uni o'qiy olishingiz kerak. Yangi loyiha uchun esa jamoalar ko'pincha boshqa yo'lni tanlaydi.

Tekshirib ko'ring: Nega FOUC muammosi oddiy <link rel="stylesheet"> bilan ulangan CSS'da deyarli uchramaydi, runtime CSS-in-JS'da esa uchraydi?

Javob

<link> bilan ulangan CSS render'ni to'sadi: brauzer uni yuklamaguncha sahifani chizmaydi (Critical Rendering Path). Runtime CSS-in-JS'da stil JavaScript ishlagandan keyin paydo bo'ladi. JavaScript kechiksa, brauzer HTML'ni stilsiz chizib ulguradi. Serverda stillarni yig'ib HTML'ga qo'shish (SSR) buni hal qiladi — lekin bu qo'shimcha sozlama.

4. Zero-runtime: yozuv JS'da, natija — oddiy CSS

4.1 vanilla-extract

G'oya: dasturchi stilni baribir JavaScript (yoki TypeScript) faylida yozsin — tiplar, import, avtomatik nom. Lekin build paytida vosita undan oddiy .css fayl yasasin. Brauzerga kutubxona bormaydi.

vanilla-extract'da stil fayli nomi .css.ts bilan tugaydi (.ts — TypeScript, 15-qism; bu yerda oddiy JavaScript'dan farqi yo'q). src/karta.css.ts:

ts
import { style, createVar } from "@vanilla-extract/css";

export const rang = createVar();

export const narx = style({
  vars: { [rang]: "#b4461a" },
  color: rang,
  fontWeight: "bold",
});

export const katta = style({
  fontSize: "1.5rem",
});

So'zlar bilan: style({...}) — "shu deklaratsiyalardan class yasa". createVar() — "noyob nomli CSS o'zgaruvchisi yasa". narx class'i o'zgaruvchiga boshlang'ich qiymat beradi va rangni undan oladi.

Build qildik (vanilla-extract 1.21.2, esbuild plagini bilan). Chiqqan CSS fayl:

css
.karta_narx__1d3n7ai1 {
  --rang__1d3n7ai0: #b4461a;
  color: var(--rang__1d3n7ai0);
  font-weight: bold;
}
.karta_katta__1d3n7ai2 {
  font-size: 1.5rem;
}

Chiqqan JavaScript — faqat satrlar:

js
// src/karta.css.ts
var katta = "karta_katta__1d3n7ai2";
var narx = "karta_narx__1d3n7ai1";
var rang = "var(--rang__1d3n7ai0)";

Nimaga qarang: JavaScript'da hech qanday "stil yasovchi" kod qolmadi — faqat class nomlari. «Yuklash narxi — o'lchadik» jadvalidagi 73 bayt shu. Brauzer esa oddiy CSS faylni o'qiydi, xuddi siz qo'lda yozgandek. Nom shakli ham CSS Modules ga o'xshaydi: karta (fayl) + narx (nom) + hash.

Narxi bormi? Ha, lekin boshqa joyda: build'da. Va bitta cheklov — build paytida qiymatlar ma'lum bo'lishi kerak. ${(props) => ...} kabi "brauzerda hisoblanadigan" qiymat yo'q. Dinamika kerak bo'lsa — CSS o'zgaruvchisi («Dinamika: CSS o'zgaruvchilari bilan» bo'limida).

4.2 Boshqa zero-runtime vositalar

Ularni ishga tushirmadik — nomini tanishingiz va g'oyasini bilishingiz yetarli. Hammasi React loyihalarida uchraydi:

  • Linaria — yozuvi styled-components'ga o'xshaydi (styled.p va backtick), lekin build'da .css faylga chiqariladi. Eski styled-components kodini ko'chirishda qulay.
  • Panda CSS — stil obyektlarini build'da kichik "atom" class'larga aylantiradi. npm'da hozir 2.0.0.
  • StyleX — Meta (Facebook) yaratgan va o'z mahsulotlarida ishlatadigan vosita. U ham atomar class'lar yasaydi.

Atomar CSS (atomic CSS) — har class faqat bitta deklaratsiya: .x1 { color: #b4461a }, .x2 { font-weight: bold }. Element esa bir nechta class oladi: class="x1 x2". Yutug'i: sayt qancha o'smasin, CSS fayl deyarli o'smaydi — color: #b4461a butun saytda bitta class. Bu g'oyani Tailwind CSS 1 darsida to'liq ko'rasiz: Tailwind'da siz atomar class'larni o'zingiz HTML'ga yozasiz.

Tekshirib ko'ring: vanilla-extract loyihasida foydalanuvchi tanlagan rangni (masalan, rang tanlagichdan) narxga berish kerak. style({ color: tanlanganRang }) ishlaydimi?

Javob

Yo'q. style() build paytida ishlaydi, foydalanuvchi esa rangni sahifa ochilgandan keyin tanlaydi — build paytida bu qiymat hali yo'q. Yechim: createVar() bilan o'zgaruvchi yasash va CSS'da color: var(...) yozish. Brauzerda esa JavaScript faqat o'zgaruvchi qiymatini elementga beradi. vanilla-extract'da buning uchun assignInlineVars yordamchisi bor.

5. Dinamika: CSS o'zgaruvchilari bilan

5.1 Ikki yo'l, bir natija

Runtime va zero-runtime farqining yuragi — dinamik qiymat. Uchta narx, uchta rang: qizg'ish, yashil, kulrang. styled-components'da ikki yo'l bilan yozdik va natijani solishtirdik.

1-yo'l — rang props'dan to'g'ridan-to'g'ri CSS'ga:

js
const Narx = styled.p`
  color: ${(props) => props.$rang};
  font-weight: bold;
`;

2-yo'l — CSS'da o'zgaruvchi, qiymat esa elementning style atributida:

js
const Narx2 = styled.p`
  color: var(--rang);
  font-weight: bold;
`;

Haqiqiy chiqish (styled-components 6.5.3; CSS bir qatorda chiqdi, xizmat qatorlari tushirildi):

html
<p class="sc-bdvwhi zwHSL">Narx</p>
<p class="sc-bdvwhi cEHswB">Narx</p>
<p class="sc-bdvwhi dA-DAsO">Narx</p>
<p style="--rang:#b4461a" class="sc-gsDMPd fGErKZ">Narx</p>
<p style="--rang:#2f6b3a" class="sc-gsDMPd fGErKZ">Narx</p>
<p style="--rang:#5b6660" class="sc-gsDMPd fGErKZ">Narx</p>
css
.zwHSL { color: #b4461a; font-weight: bold; }
.cEHswB { color: #2f6b3a; font-weight: bold; }
.dA-DAsO { color: #5b6660; font-weight: bold; }
.fGErKZ { color: var(--rang); font-weight: bold; }

1-yo'l: uch rang — uchta qoida. 100 xil rang bo'lsa — 100 ta qoida, har biri brauzerda yangidan yasaladi. 2-yo'l: har qanday rang soni uchun bitta qoida. O'zgaradigani faqat o'zgaruvchi qiymati — kutubxona hech narsa yasamaydi.

Bu yondashuv sizga tanish: CSS o'zgaruvchilari 2 darsida komponent tashqaridan --tugma-fon bilan sozlanardi. Kutubxonasiz, oddiy CSS bilan ham xuddi shunday:

html
<style>
  .narx {
    color: var(--rang, #1f2a24);
    font-weight: bold;
  }
  body { font-family: system-ui, sans-serif; }
</style>
<p class="narx" style="--rang: #b4461a">Osh — 35 000 so'm</p>
<p class="narx" style="--rang: #2f6b3a">Lag'mon — 28 000 so'm</p>
<p class="narx" style="--rang: #5b6660">Manti — 30 000 so'm</p>
<p class="narx">Ko'k choy — 5 000 so'm</p>

Nimaga qarang: birinchi uchta narx qizg'ish, yashil va kulrang, to'rtinchisi — to'q (zaxira qiymat #1f2a24, chunki --rang berilmagan). CSS qoidasi bitta. "Tahrirlab ko'rish" bilan birinchi qatordagi rangni o'zgartiring — qoidaga tegmasdan.

Diqqat: style="..." atributini bu yerda faqat namoyish uchun yozdik. «Bahor»da inline stil ishlatilmaydi — 04-qismdagi CSP uni to'sadi. Real ilovada qiymatni JavaScript beradi (element.style.setProperty(...), CSS o'zgaruvchilari 2 darsidagi qisqa ko'rsatma) — CSP bunga ruxsat beradi.

5.2 Nega bu sanoatning yo'nalishi

Bugungi yangi vositalarning deyarli hammasi dinamikani shu yo'l bilan qiladi: vanilla-extract'da createVar, styled-components 6.4 dagi createTheme ham CSS o'zgaruvchilari ustiga qurilgan. Sabab uchta:

  • CSS o'zgaruvchisi brauzerning o'zida ishlaydi — kutubxona kerak emas.
  • U meros bo'ladi: qorong'i rejim uchun :root dagi bir nechta qiymatni almashtirsangiz, butun sayt o'zgaradi (Qorong'i rejim).
  • Server va brauzer bir xil CSS'ni ko'radi — RSC muammosi yo'q.

Tekshirib ko'ring: Karta sichqoncha orqasidan yorug' dog' chizishi kerak: dog' markazi har harakatda o'zgaradi (sekundiga o'nlab marta). Runtime kutubxonada ${(props) => props.$x}px bilan yozish nega yomon?

Javob

Har harakatda yangi qiymat — yangi CSS matni — yangi hash — <style> ga yangi qoida. Sekundiga o'nlab qoida yasaladi, <style> shishadi va brauzer har safar stillarni qayta hisoblaydi. To'g'ri yo'l: CSS'da bitta qoida (background: radial-gradient(at var(--x) var(--y), ...)), JavaScript esa faqat --x va --y ni yangilaydi.

6. Qachon nimani tanlash

Kursda uch yondashuvni ko'rdingiz va to'rtinchisi — Tailwind — kelyapti. Real loyihada ular shunday taqsimlanadi:

Vaziyat Odatiy tanlov
Oddiy sayt, build yo'q («Bahor», portfolio) Oddiy CSS + @layer + tokenlar
React/Next.js, yangi loyiha Tailwind yoki CSS Modules
Tiplar va tokenlar qat'iy kerak, katta jamoa Zero-runtime: vanilla-extract, Panda, StyleX
Mavjud loyiha styled-components yoki Emotion'da O'shani davom ettirish, dinamikani CSS o'zgaruvchisiga o'tkazish

Runtime CSS-in-JS'ning haqiqiy yutuqlari ham bor: stil komponent bilan bitta faylda, props'dan to'g'ridan-to'g'ri qiymat, keraksiz komponent o'chirilsa uning stili ham yo'qoladi. Kichik ichki panel yoki prototipda bu yutuqlar narxdan og'ir bo'lishi mumkin. Tanlov — "qaysi yaxshi" emas, "shu loyihaga qaysi mos".

Mashhur UI kutubxonalar ham shu yo'ldan o'tmoqda. Masalan, MUI (Material UI) uzoq yillar Emotion ustida qurilgan. Ular haqida React'da stil berish darsida gaplashamiz.

7. Ko'p uchraydigan xatolar

7.1 Tez o'zgaradigan qiymat props orqali

Animatsiya, skroll yoki sichqoncha koordinatasi ${props => ...} bilan CSS'ga yozilgan. Sahifa sekinlashadi, DevTools'da <style> tegi minglab qatorga to'ladi. Tuzatish: CSS'da var(--x), qiymat — o'zgaruvchi orqali.

7.2 Server Component'da runtime kutubxona

Next.js'da styled-components komponentini server komponentida ishlatish xatoga olib keladi. Sabab — kutubxona brauzer JavaScript'iga va React Context'ga tayanadi. Tuzatish: fayl boshiga "use client" (komponentni mijoz tomoniga o'tkazish) va stil registri — yoki zero-runtime vosita. Buni Next.js'da stil va tema darsida amalda qilasiz.

7.3 Serverda yig'ilmagan stil — FOUC

SSR bor, lekin stil registri sozlanmagan. Sahifa bir lahza stilsiz ko'rinadi, keyin "sakraydi". Tuzatish: kutubxona hujjatidagi SSR bo'limi (styled-components'da ServerStyleSheet, Next.js'da registri fayli).

7.4 Zero-runtime'dan runtime qiymat kutish

vanilla-extract yoki Linaria'da style({ color: foydalanuvchiRangi }) — build xato beradi yoki qiymat qotib qoladi. Tuzatish: createVar() + brauzerda o'zgaruvchi qiymatini berish.

7.5 "Hamma narsa JS'da"

Reset, shriftlar, :root tokenlari ham CSS-in-JS ichiga ko'chirilgan — har sahifada JavaScript bilan qayta yasaladi. Tuzatish: global narsalar — oddiy global CSS faylda (CSS reset, Dizayn tokenlari). CSS-in-JS — faqat komponent stili uchun.

8. Mashqlar

Bu mashqlar kutubxonalarni o'rnatmasdan bajariladi: siz haqiqiy chiqishni o'qiysiz va oddiy CSS'da yozasiz.

1-mashq (oson): chiqishni o'qing

Begona saytda DevTools'da shu HTML'ni ko'rdingiz:

html
<button class="sc-kAyceB hMpQrs">Band qilish</button>
<button class="sc-kAyceB bXrTnw">Bekor qilish</button>

Qaysi kutubxona? Ikkala tugma bitta komponentmi? Nega ikkinchi class'lar farq qiladi?

Ishora: "Haqiqiy natija" bo'limidagi sc-bdvwhi fqYBio tahlili.

Yechim
  • sc- bilan boshlangan class — styled-components belgisi.
  • sc-kAyceB ikkalasida bir xil — demak, bitta komponent (masalan, Tugma).
  • hMpQrs va bXrTnw — stil hash'lari. Ular farq qiladi, demak ikkala tugmaning yakuniy CSS matni farq qiladi. Ehtimol, props orqali rang yoki fon berilgan: biri yashil, biri kulrang.

DevTools'da Styles panelida ikkala class'ning qoidasini solishtirsangiz, qaysi qator farq qilishini aniq ko'rasiz.

2-mashq (o'rta): props'dan o'zgaruvchiga

Dasturchi styled-components'da taom kartasini shunday yozgan: border-color: ${(props) => props.$rang};. Menyuda 12 ta taom, har birining o'z rangi. Nechta CSS qoidasi yasaladi? Xuddi shu kartani oddiy CSS da bitta qoida bilan yozing: rang --karta-rang o'zgaruvchisidan kelsin, berilmasa — #2f6b3a. Uchta karta bilan kurs/mashqlar/06/css-in-js/index.html da sinab ko'ring.

Ishora: var(--nom, zaxira) — CSS o'zgaruvchilari 2. --karta-rang — «Bahor»ning mavjud komponent tokeni.

Yechim

Rang har karta uchun boshqa bo'lsa — 12 ta qoida (bir xil ranglar bitta class'ni bo'lishadi, shuning uchun eng ko'pi 12).

asosiy.css:

css
.taom-karta {
  padding: 1rem;
  border: 2px solid var(--karta-rang, #2f6b3a);
  border-radius: 0.5rem;
}

index.html da (mashq sahifasi, CSP yo'q — namoyish uchun inline qiymat):

html
<article class="taom-karta">Osh</article>
<article class="taom-karta" style="--karta-rang: #b4461a">
  Lag'mon
</article>
<article class="taom-karta" style="--karta-rang: #5b6660">
  Manti
</article>

Birinchi karta yashil (zaxira), ikkinchisi qizg'ish, uchinchisi kulrang. Qoida bitta — 12 ta taom bo'lsa ham.

3-mashq (qiyin): uch loyiha, uch qaror

Har loyiha uchun CSS yondashuvini tanlang va bir-ikki gap bilan asoslang:

  1. Toshkentdagi taksi xizmatining React Native'siz, oddiy React veb-ilovasi. Next.js, server komponentlar ko'p, jamoa 3 kishi.
  2. Bankning ichki hisobot paneli: 2019-yilda styled-components bilan yozilgan, 400 ta komponent. Yangi talab — qorong'i rejim.
  3. Kichik kafe uchun bir sahifali sayt, build vositasi yo'q, hostingga faylni o'zi yuklaydi.

Ishora: "Qachon nimani tanlash" jadvali va "Dinamika: CSS o'zgaruvchilari bilan" bo'limi.

Yechim
  1. Tailwind yoki CSS Modules (yoki zero-runtime vosita). Server komponentlarida runtime CSS-in-JS faqat "use client" bilan ishlaydi — bu ko'p komponentni mijozga o'tkazadi. Kichik jamoa uchun Tailwind yoki CSS Modules sozlamasi eng oddiy.
  2. styled-components qoladi. 400 ta komponentni ko'chirish — oylar ishi va yangi xatolar. Qorong'i rejim uchun ranglarni :root dagi CSS o'zgaruvchilariga chiqarish kerak: komponentlar color: var(--rang-matn) yozadi, tema faqat o'zgaruvchilarni almashtiradi. 6.4 dagi createTheme aynan shu yo'lni beradi.
  3. Oddiy CSS. Build yo'q — CSS Modules ham, zero-runtime ham ishlamaydi. Runtime kutubxona esa kichik sahifaga keraksiz JavaScript qo'shadi. Tokenlar va @layer bilan bitta-ikkita .css fayl yetarli.

4-mashq: Portfolio qadami — "dinamik" joylar xaritasi

Portfolio'da JavaScript va build yo'q, shuning uchun CSS-in-JS'ni unga qo'shmaymiz. Bu qadam — tahlil: portfolio'da "holatga qarab o'zgaradigan" stillar qayerda va ular allaqachon qaysi usul bilan ishlayotganini topish. Portfolio v2 (Next.js nima, 23-qism) ga ko'chganda aynan shu joylar "props bilan yozaymi yoki o'zgaruvchi bilanmi?" degan savol tug'diradi.

sayt/assets/css/ fayllaridan kamida to'rtta shunday joyni toping va jadval tuzing: joy — hozir qanday ishlaydi — runtime CSS-in-JS'da odatda qanday yozilardi. Faqat qog'ozda; fayllar o'zgarmaydi.

Ishora: qorong'i rejim, hover, [aria-current="page"], @property bilan animatsiya qilingan --karta-chegara, skip link fokusi.

Yechim

Namuna (sizning fayllaringizda nomlar biroz boshqacha bo'lishi mumkin):

Joy Hozir Runtime CSS-in-JS'da odatda
Qorong'i rejim :root o'zgaruvchilari, light-dark() ThemeProvider + props — yoki yaxshisi, xuddi shu o'zgaruvchilar
Menyudagi joriy sahifa [aria-current="page"] selektori ${props => props.$faol && "..."}
Karta chegarasi hover'da --karta-chegara (@property) + transition O'zgaruvchi — props'da har kadr qoida yasamaslik uchun
Skip link .otish:focus Xuddi shu &:focus (kutubxonalar & ni tushunadi)

Xulosa: portfolio'dagi hamma "dinamika" allaqachon brauzerning o'zida — selektorlar, pseudo-klasslar va CSS o'zgaruvchilari bilan. JavaScript'ga ko'chirishga hech narsa majbur qilmaydi. Next.js'ga o'tganda ham shu yondashuv qoladi; aria-current kabi atribut selektorlari props'dan ham yaxshiroq — ular accessibility bilan bir vaqtda ishlaydi.

9. Real ishda

  • Mavjud loyihalar. 2017–2022-yillarda boshlangan ko'p React loyihalari styled-components yoki Emotion'da. sc- yoki css- bilan boshlangan class'larni ko'rsangiz — bilasiz.
  • Migratsiya ishi. Ko'p kompaniyalar runtime CSS-in-JS'dan Tailwind, CSS Modules yoki zero-runtime vositaga bosqichma-bosqich ko'chmoqda. Bu — real vazifa va intervyudagi savol.
  • Dizayn tizimlari. Katta kompaniyalarning komponent kutubxonalari tiplar va tokenlar uchun vanilla-extract yoki StyleX kabi vositani tanlaydi.
  • Intervyuda: "Runtime va zero-runtime CSS-in-JS farqi?", "Nega styled-components RSC bilan qiyin?", "Dinamik rangni qanday qilib ortiqcha CSS yasamasdan berasiz?" — endi javob bera olasiz.

Xulosa

  • CSS-in-JS — stilni komponent yonida, JavaScript ichida yozish; nomlar avtomatik noyob.
  • Runtime (styled-components, Emotion) CSS'ni brauzerda yasaydi: har turli qiymat — yangi qoida, kutubxona hajmi, SSR va RSC bilan qo'shimcha ish.
  • Zero-runtime (vanilla-extract, Linaria, Panda CSS, StyleX) build'da oddiy .css yasaydi, JS'da faqat class nomlari qoladi.
  • styled-components 2025-yil martdan maintenance mode'da, lekin yashayapti (6.5.3) va ko'p loyihada uchraydi.
  • Dinamik qiymat uchun eng arzon yo'l — CSS o'zgaruvchisi: bitta qoida, qiymat o'zgaradi.

Keyingi dars: CSS freymvorklar: Bootstrap va muqobillari — tayyor komponentli freymvorklar, ular qachon foydali va qachon xalaqit beradi.

Manbalar

  • styled-components: "Celebrating a Decade of styled-components" — styled-components.com/blog
  • styled-components: maintenance mode e'loni — github.com/orgs/styled-components/discussions/5568
  • Next.js: "How to use CSS-in-JS libraries" — nextjs.org/docs/app/guides/css-in-js
  • vanilla-extract — vanilla-extract.style
  • Emotion — emotion.sh
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
CSS-in-JS: runtime va zero-runtime yondashuvlar — IlmHamroh