Mundarija (35)
- Bu darsda
- 1. Nega bu kerak?
- 2. Global CSS
- 2.1 Root layout'da
- 2.2 Import tartibi
- 3. CSS Modules
- 3.1 Nima uchun
- 3.2 portfolio dagi o'zgarish
- 3.3 Next nima yasadi
- 4. Tailwind — kanon o'lchovi
- 4.1 Sukut bo'yicha bor edi
- 4.2 Narxi
- 4.3 Tailwind Next'da qanday ulanadi
- 5. CSS-in-JS va Server Components
- 5.1 Muammo
- 5.2 Nima tanlash kerak
- 6. Qorong'i rejim
- 6.1 Uch talab
- 6.2 Kanon yechimi — ikki qism
- 6.3 Natija oynasida: tema modeli
- 6.4 next-themes nega kirmadi
- 7. shadcn/ui Next'da
- 8. Portfolio qadami: CSS Module va commit
- 8.1 O'zgarishlar (holat 33)
- 8.2 Tekshiruv
- 8.3 Commit
- 9. Ko'p uchraydigan xatolar
- 10. Mashqlar
- 1-mashq (oson): qayerga yozasiz?
- 2-mashq (o'rta): tizim mavzusi
- 3-mashq (qiyin): CSS Module modeli
- 4-mashq: Portfolio qadami
- 11. Real ishda
- Xulosa
- Manbalar
Next.js'da stil va tema: global CSS, CSS Modules, Tailwind va qorong'i rejim
Qisqacha: App Router'da uch asosiy yo'l bor. Global CSS — root layout'da bir marta import qilinadi, tartib import tartibiga bog'liq. CSS Modules (
*.module.css) — klass nomlari build'da noyob bo'ladi va faqat shu komponentga tegadi. Tailwind v4 — utility klasslar;create-next-appuni sukut bo'yicha qo'shadi. Runtime CSS-in-JS (styled-components, Emotion) faqat Client Component'larda va maxsus "registry" bilan ishlaydi. Qorong'i rejim —<head>dagi kichik skript +data-temaatributi, hydration xatosisiz.
Bu darsda
- Global CSS, CSS Modules va Tailwind farqini va qachon qaysi birini tanlashni bilasiz.
portfolioning loyiha kartasini CSS Module'ga o'tkazasiz va Next yasagan haqiqiy CSS'ni o'qiysiz.- Kanon nega Tailwind'ni olib tashlaganini o'lchov bilan asoslaysiz (18 MB, 20 paket).
- CSS-in-JS nega Server Component'larda ishlamasligini tushuntirasiz.
- Qorong'i rejimni
next-themessiz — o'zTemaProviderbilan — qanday qilinganini va "chaqnash"ning oldi qanday olinganini bilasiz.
Oldin bilishingiz kerak: Provider'lar App Router'da, Hydration xatolari, Kaskad qatlamlari, Tailwind CSS, Qorong'i rejim.
1. Nega bu kerak?
React'da stil yozishning o'nlab usullari bor — 20-qismda bir nechtasini ko'rgansiz: oddiy CSS, Tailwind, CSS-in-JS. SPA'da ularning hammasi bir xil joyda ishlaydi — brauzerda.
Next.js'da yangi savol paydo bo'ladi: komponent qayerda chiziladi? Server Component serverda bir marta chiziladi va JS'siz HTML bo'lib ketadi. JS ichida, render paytida CSS yaratadigan kutubxona (styled-components) uchun bu muammo: serverda yaratilgan stillar HTML'ga qanday tushadi? Server Component'da useState, useContext yo'q — kutubxona ishlay oladimi?
portfolio uchun yana bir savol bor: v1 da 04–06-qismlarda qurilgan CSS bor — tokenlar (--rang-*, --masofa-*), qatlamlar (@layer). Uni Tailwind'ga qayta yozish kerakmi yoki shundayligicha ko'chirish yetadimi?
Hayotiy o'xshatish: uyni bo'yash. Global CSS — butun uyga bitta bo'yoq rejasi. CSS Module — har xonaning o'z devor qog'ozi: qo'shni xonaga o'tmaydi. Tailwind — tayyor bo'yoq qutilari to'plami: tez, lekin qutilarni uyga olib kirish kerak (va ular joy egallaydi).
2. Global CSS
Avval umumiy xarita — qaysi stil qayerda ishlaydi:
flowchart TB
Q{"Stil qayerda yaratiladi?"}
Q -->|build vaqtida| B["Global CSS, CSS Modules,<br/>Tailwind, vanilla-extract"]
Q -->|brauzerda, render paytida| R["styled-components, Emotion"]
B --> SC["Server va Client Component — ikkalasi"]
R --> CC["faqat Client Component + registry"]Bu darsning asosiy g'oyasi shu rasmda: stil build vaqtida tayyor bo'lsa — Server Component unga hech narsa demaydi.
2.1 Root layout'da
portfolio da butun sayt CSS'i — app/globals.css, root layout'da bir marta:
import "./globals.css";Ichida v1 ning hammasi: tokenlar, reset, qatlamlar. Fayl boshida qatlamlar tartibi e'lon qilingan:
@layer tokenlar, reset, asos, layout, komponentlar;Kaskad qatlamlari darsidan bilasiz: keyingi qatlam oldingisidan kuchli, specificity'dan qat'i nazar. Bu qator butun loyihaning "konstitutsiyasi".
O'lchov: globals.css — 7.2 KB xom, 2.4 KB gzip. Butun saytning CSS'i — shu.
2.2 Import tartibi
Next production'da CSS fayllarni birlashtiradi va bo'laklarga ajratadi (chunk). Hujjat ogohlantiradi: CSS tartibi — kodda import qilinish tartibi. Tugma komponenti o'z CSS'ini import qilsa va sahifa undan keyin o'zinikini — sahifa CSS'i keyin keladi va ustun.
Hujjatning tavsiyalari:
- global stil va Tailwind — ilovaning ildizida (root layout);
- CSS import'larini avtomatik saralaydigan linter qoidalarini o'chiring (
sort-imports) — tartib o'zgarsa, stil buziladi; - dev va production'da tartib farq qilishi mumkin — build'ni tekshiring.
portfolio da bu muammo deyarli yo'q: tartibni @layer hal qiladi, import tartibi emas. Bu — qatlamlarning yashirin foydasi.
3. CSS Modules
3.1 Nima uchun
Global CSS'da .karta klassi bitta. Ertaga blogda boshqa .karta yozsangiz — ikkalasi to'qnashadi. CSS Module — fayl nomi *.module.css bo'lgan CSS: undagi klass nomlari build'da noyob nomga aylanadi va faqat uni import qilgan komponentga tegadi.
3.2 portfolio dagi o'zgarish
Kanon (holat 33) loyiha kartasini global CSS'dan modulga o'tkazdi. LoyihaKartasi.module.css (kanon izohi qisqartirilgan):
/* CSS Module: klass nomlari faqat shu komponentga tegishli.
Tokenlar globals.css dan — o'zgaruvchilar modulga o'tadi. */
@layer komponentlar {
.karta {
display: grid;
gap: var(--masofa-s);
block-size: 100%;
padding: var(--masofa-m);
border: 1px solid var(--rang-chegara);
border-radius: var(--burchak-m);
}
.karta > * {
margin: 0;
}
.karta {
align-content: start;
}
.karta h2 {
font-size: 1.25rem;
}
@media (hover: hover) {
.karta:has(a:hover) {
border-color: var(--rang-asosiy);
}
}
}Komponentda:
+import stil from "./LoyihaKartasi.module.css";
…
- <article>
+ <article className={stil.karta}>stil — oddiy obyekt: stil.karta — build'dagi noyob nom. Uch muhim detal:
- Tokenlar ishlaydi. CSS o'zgaruvchilari (
var(--masofa-s)) — klass emas, ular:rootdan meros bo'lib keladi. Modul ularni bemalol ishlatadi. - Qatlam ichida. Modul qoidalari
@layer komponentlarda — global qatlam tartibiga bo'ysunadi. Modul "hammadan kuchli" bo'lib qolmaydi. .karta > *vaalign-content: start— vizual tekshiruvda topilgan nuqson: kartadagip/ulo'z margin'larini olib kelib, grid'da bo'sh qatorlar hosil qilardi. Kanon 3 sahifani × mobil/desktop × yorug'/qorong'i (12 ta skrinshot,natijalar/surat/33-*) ko'rib, tuzatdi.
3.3 Next nima yasadi
Build'dan keyingi CSS bo'lagi (holat 33 o'zgarishlari bilan nusxa, next build, biz ishga tushirdik):
@layer komponentlar{.k4BiaG_karta{gap:var(--masofa-s);block-size:100%;padding:var(--masofa-m);border:1px solid var(--rang-chegara);border-radius:var(--burchak-m);display:grid}.k4BiaG_karta>*{margin:0}.k4BiaG_karta{align-content:start}.k4BiaG_karta h2{font-size:1.25rem}@media (hover:hover){.k4BiaG_karta:has(a:hover){border-color:var(--rang-asosiy)}}}.karta → .k4BiaG_karta: fayl nomidan yasalgan prefiks. Boshqa modulda .karta bo'lsa, u boshqa prefiks oladi — to'qnashuv yo'q. Fayl — alohida bo'lak: bizning build'da 352 bayt (gzip 250), kanon o'lchovida 302 B (232 gzip). U faqat kartalar bor sahifada yuklanadi.
Tekshirib ko'ring: CSS Module ichida
body { margin: 0 }yozsangiz nima bo'ladi?
Javob
Next uni rad etadi: CSS Module'da faqat lokal selektorlar bo'lishi kerak — kamida bitta klass yoki id bilan. body, h1 kabi "sof" teg selektorlari global ta'sir qiladi, modulning ma'nosi yo'qoladi. Global qoida — globals.css ga. Modul ichida .karta h2 mumkin, chunki u .karta bilan cheklangan.
4. Tailwind — kanon o'lchovi
4.1 Sukut bo'yicha bor edi
create-next-app 16.4 Tailwind v4 ni sukut bo'yicha qo'shadi (Loyiha yaratish). Kanon topilmasi: 16.4 shablonida Tailwind PostCSS orqali emas, Turbopack loader'i (@tailwindcss/turbopack) orqali ulanadi. Next hujjati esa hali PostCSS yo'lini (@tailwindcss/postcss + postcss.config.mjs) ko'rsatadi — ikkalasi ham ishlaydi, shablon yangirog'ini tanlagan.
4.2 Narxi
Kanon o'lchadi (natijalar/tajriba/33-tailwind.txt):
tailwindcss+@tailwindcss/turbopack: 18M, 20 package.json
457M node_modules| Tailwind bilan | Tailwind'siz (kanon) | |
|---|---|---|
node_modules |
463 MB (skelet) | 457 MB |
| Paketlar | +20 | — |
| Sayt CSS'i (gzip) | o'lchanmadi | 2.4–2.7 KB |
| v1 markup'i | utilitalarga qayta yozish | o'zgarishsiz |
Diqqat: 463 va 457 MB — turli paytdagi o'lchov (skelet va holat 33; orada boshqa paketlar, masalan zod va marked, qo'shilgan). Shuning uchun ularning farqi Tailwind hajmi emas; Tailwind'ning o'zi — birinchi qatordagi 18 MB.
Brauzer uchun Tailwind CSS ham kichik bo'lardi (u faqat ishlatilgan klasslarni chiqaradi). Asosiy narx — qayta yozish: v1 dagi har class="karta" ni class="grid gap-2 p-4 border rounded-lg" ga aylantirish. 20-qismda vazifalar ni Tailwind'ga o'tkazgansiz (Tailwind CSS) — u loyiha uchun bu to'g'ri edi. portfolio da esa tayyor dizayn tizimi bor.
Kanon qarori: CSS qoladi, Tailwind olib tashlandi. Bu "Tailwind yomon" degani emas — bu "mavjud tizimni sababsiz almashtirmang" degani. Next hujjatining o'zi Tailwind'ni ko'p vazifalar uchun tavsiya qiladi; yangi loyihada u ko'pincha eng tez yo'l.
4.3 Tailwind Next'da qanday ulanadi
Agar ishlatsangiz (hujjat bo'yicha):
/* app/globals.css */
@import "tailwindcss";
@theme {
--color-asosiy: oklch(45% 0.1 155);
}Root layout globals.css ni import qiladi — tamom. Server Component'larda ham ishlaydi: Tailwind — oddiy klass nomlari, runtime JS'i yo'q. Shrift o'zgaruvchisini ulash — next/font darsida.
5. CSS-in-JS va Server Components
5.1 Muammo
Runtime CSS-in-JS (styled-components, Emotion) — stil komponent render bo'lganda JS ichida yaratiladi va <style> tegiga qo'shiladi. Buning uchun kutubxona React Context va effektlardan foydalanadi. Server Component'da esa ular yo'q (Server Components).
Next hujjati shunday deydi: CSS-in-JS kutubxonalari App Router'da faqat Client Component'larda qo'llab-quvvatlanadi. Sozlash uch qadam:
- style registry — bitta render davomidagi hamma stillarni yig'adi;
useServerInsertedHTMLhook'i — yig'ilgan stillarni HTML'ga, kontentdan oldin qo'yadi;- ilovani registry bilan o'raydigan client komponent.
// app/registry.tsx — styled-components uchun (hujjat naqshi)
"use client";
import { useServerInsertedHTML } from "next/navigation";
import {
ServerStyleSheet,
StyleSheetManager,
} from "styled-components";
// … registry stillarni yig'ib, useServerInsertedHTML bilan beradiHujjatdagi ro'yxat: styled-components, styled-jsx, MUI, Chakra, Panda, vanilla-extract va boshqalar qo'llab-quvvatlanadi; Emotion — "qo'llab-quvvatlash ustida ishlanmoqda".
5.2 Nima tanlash kerak
| Yo'l | Server Component'da | Runtime JS | Izoh |
|---|---|---|---|
| Global CSS / CSS Modules | ha | 0 | portfolio tanlovi |
| Tailwind | ha | 0 | build'da yasaladi |
| Zero-runtime CSS-in-JS (vanilla-extract, Panda, StyleX) | ha | 0 | build'da CSS faylga |
| Runtime CSS-in-JS (styled-components) | yo'q, faqat client | bor | registry kerak |
Zamonaviy yo'nalish aniq: stil build vaqtida yasaladigan yechimlar. Ular Server Component'lar bilan to'qnashmaydi va brauzerga JS qo'shmaydi.
6. Qorong'i rejim
6.1 Uch talab
Qorong'i rejim darsida v1 uchun to'liq yechim qurgansiz: data-tema atributi, tokenlar, prefers-color-scheme. Next'da yana ikkita qiyinchilik qo'shiladi:
- Chaqnash (FOUC). Server foydalanuvchi qorong'i rejim tanlaganini bilmaydi (u
localStorageda). HTML yorug' keladi, JS yuklangach qorong'iga o'tadi — oq "chaqnash". - Hydration farqi. Server
tizimdeb chizadi, brauzerqorongini o'qiydi — React mismatch ogohlantirishini beradi (Hydration xatolari). - Statiklik. Cookie ishlatsangiz, server mavzuni bilardi — lekin har sahifa dinamik bo'lib qolardi (Request API'lar).
6.2 Kanon yechimi — ikki qism
<head> dagi skript — React'dan oldin, birinchi bo'yashdan oldin:
const KOD = `try{var t=localStorage.getItem("tema");if(t==="yorug"||t==="qorongi")document.documentElement.dataset.tema=t}catch(e){}`;
export function TemaSkripti() {
return <script dangerouslySetInnerHTML={{ __html: KOD }} />;
}Bu skript <html data-tema="qorongi"> ni qo'yadi — CSS darhol to'g'ri ranglarni oladi, chaqnash yo'q. React hydration paytida <html> da kutilmagan atributni ko'radi — shuning uchun root layout'da <html suppressHydrationWarning>. Bu ogohlantirishni faqat <html> ning o'z atributlari uchun o'chiradi, ichkarisiga ta'sir qilmaydi.
TemaProvider — client komponent, Context + useSyncExternalStore (N-12 da qurilgan). Asosiy qatori:
const tema = useSyncExternalStore(obuna, oqi, () => "tizim" as const);Uchinchi argument — getServerSnapshot: serverda va hydration paytida doim "tizim", keyin brauzer qiymati. React bu holatda mismatch xatosi bermaydi — hydration'dan keyin qayta chizadi.
Kanon o'lchovi (holat 13 dan beri, har holatda): hydration ogohlantirishi 0, localStorage.tema = "qorongi" bilan ochilganda sahifa darhol qorong'i.
6.3 Natija oynasida: tema modeli
Natija oynasi sandbox ichida — u yerda localStorage ga kirish taqiqlangan (xato beradi). Kanondagi oqi() buni try/catch bilan ushlaydi va doim "tizim" qaytaradi — demak tanlov saqlanmaydi. Shuning uchun quyidagi o'quv modelida localStorage o'rniga oddiy o'zgaruvchi (xotira) ishlatiladi. Qolgani — kanondagidek: Context, use(), useSyncExternalStore va hodisa:
import {
createContext,
use,
useCallback,
useSyncExternalStore,
type ReactNode,
} from "react";
type Tema = "tizim" | "yorug" | "qorongi";
let xotira: Tema = "tizim"; // localStorage o'rnida
const tinglovchilar = new Set<() => void>();
const oqi = () => xotira;
const obuna = (f: () => void) => {
tinglovchilar.add(f);
return () => tinglovchilar.delete(f);
};
const TemaKonteksti = createContext<{
tema: Tema;
temaniQoy: (t: Tema) => void;
} | null>(null);
function TemaProvider({ children }: { children: ReactNode }) {
const server = (): Tema => "tizim";
const tema = useSyncExternalStore(obuna, oqi, server);
const temaniQoy = useCallback((t: Tema) => {
xotira = t;
console.log(`data-tema: ${t}`);
for (const f of tinglovchilar) f();
}, []);
const qiymat = { tema, temaniQoy };
return <TemaKonteksti value={qiymat}>{children}</TemaKonteksti>;
}
function useTema() {
const q = use(TemaKonteksti);
if (!q) throw new Error("useTema faqat <TemaProvider> ichida");
return q;
}
const VARIANTLAR: { qiymat: Tema; nomi: string }[] = [
{ qiymat: "tizim", nomi: "Tizim" },
{ qiymat: "yorug", nomi: "Yorug'" },
{ qiymat: "qorongi", nomi: "Qorong'i" },
];
function ThemePicker() {
const { tema, temaniQoy } = useTema();
return (
<fieldset>
<legend>Mavzu</legend>
{VARIANTLAR.map((v) => (
<label key={v.qiymat}>
<input
type="radio"
name="tema"
checked={tema === v.qiymat}
onChange={() => temaniQoy(v.qiymat)}
/>{" "}
{v.nomi}
</label>
))}
<p>Joriy: {tema}</p>
</fieldset>
);
}
export default function App() {
return (
<TemaProvider>
<ThemePicker />
</TemaProvider>
);
}Konsolda:
data-tema: qorongiEkranda:
Mavzu
Tizim Yorug' Qorong'i
Joriy: qorongi«Qorong'i» bosilganda temaniQoy xotirani o'zgartirdi va tinglovchilarga xabar berdi — useSyncExternalStore komponentni qayta chizdi. Kanonda xuddi shu joyda localStorage.setItem, document.documentElement.dataset.tema = t va window.dispatchEvent(new Event("tema:ozgardi")) turadi; boshqa tabdagi o'zgarishni storage hodisasi olib keladi.
6.4 next-themes nega kirmadi
next-themes — Next uchun mashhur tema kutubxonasi. U aynan shu naqshni qiladi: <head> skripti, localStorage, suppressHydrationWarning talabi. Kanon qarori: kirmadi — portfolio da bu naqsh allaqachon bor (0 bog'liqlik, ~40 qator), paket faqat qo'shimcha bog'liqlik bo'lardi. Katta loyihada, ko'p tema va tizim sozlamalari bilan, next-themes vaqtni tejaydi — g'oyasi endi sizga tanish.
7. shadcn/ui Next'da
shadcn/ui — kutubxona emas, komponentlar kodini loyihangizga ko'chiradigan vosita (npx shadcn add button). Komponentlar Radix + Tailwind asosida, components/ui/ papkasiga tushadi va sizniki bo'ladi. 20-qismda vazifalar da ishlatgansiz (shadcn/ui I).
Next'da ikki farq: interaktiv komponentlar (Dialog, DropdownMenu) fayl boshida "use client" bilan keladi; oddiy komponentlar (Card, Badge) esa Server Component'da ham ishlaydi. shadcn Tailwind talab qiladi — portfolio da Tailwind yo'q, shuning uchun bu yerda ishlatilmaydi.
8. Portfolio qadami: CSS Module va commit
8.1 O'zgarishlar (holat 33)
| Fayl | O'zgarish |
|---|---|
loyihalar/_komponentlar/LoyihaKartasi.module.css |
yangi — .karta (@layer komponentlar) |
loyihalar/_komponentlar/LoyihaKartasi.tsx |
import stil …, className={stil.karta} |
app/globals.css |
.loyihalar > li > article va .loyihalar h2/h3 qoidalari olib tashlandi |
8.2 Tekshiruv
npm run lint
npm run tip
npm run build
npm run start/loyihalar ni telefon va desktop o'lchamida, yorug' va qorong'i rejimda oching: kartalar avvalgidek, ichida bo'sh qatorlar yo'q, gorizontal skroll yo'q. Kanon o'lchovi: JS o'zgarmadi (146.5 KB), CSS 2.4 → 2.7 KB (modul bo'lagi qo'shildi), axe 0, hydration 0.
8.3 Commit
git add -A
git commitCommit (kanon): Stil: loyiha kartasi CSS Module'ga (komponentlar qatlami).
9. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
| Stil dev'da to'g'ri, build'da boshqacha | CSS import tartibi | Global stil — root'da; @layer bilan tartib |
Modulda body {…} — build xatosi |
CSS Module'da faqat lokal selektor | Global qoida — globals.css ga |
styled-components Server Component'da ishlamaydi |
Runtime CSS-in-JS Context talab qiladi | "use client" + registry yoki zero-runtime yechim |
| Qorong'i rejimda oq "chaqnash" | Mavzu faqat React'da qo'llanadi | <head> dagi inline skript |
<html> da hydration ogohlantirishi |
Skript data-tema qo'shdi |
<html suppressHydrationWarning> |
| Hamma sahifa dinamik bo'ldi | Mavzu cookie'dan o'qilmoqda | localStorage + skript |
| Klass nomlari to'qnashdi | Global CSS'da bir xil nom | CSS Module |
10. Mashqlar
Mashqlar kurs/mashqlar/23/33-stil-tema/ da. Jonli yechimlarni «Ishga tushir» bilan sinang.
1-mashq (oson): qayerga yozasiz?
- Saytning rang tokenlari (
--rang-asosiy) — - Faqat blog kartasining stili —
- Server Component'da stil, runtime JS'siz — yoki CSS
- styled-components bilan yozilgan tugma —
Yechim
- globals.css — tokenlar butun saytga,
:rootda. - CSS Module —
BlogKartasi.module.css: nomlar to'qnashmaydi. - Tailwind (yoki global CSS / CSS Module) — build vaqtida yasaladi.
- Client Component — runtime CSS-in-JS faqat client'da, registry bilan.
2-mashq (o'rta): tizim mavzusi
«tema modeli» blokini kengaytiring: «Tizim» tanlanganda Joriy: qatorida haqiqiy rang ham ko'rinsin — Joriy: tizim (yorug'). Tizim mavzusini matchMedia("(prefers-color-scheme: dark)").matches bilan aniqlang (matchMedia). Natija oynasi brauzeri yorug' rejimda deb hisoblang.
Yechim
import { useSyncExternalStore } from "react";
type Tema = "tizim" | "yorug" | "qorongi";
let xotira: Tema = "qorongi";
const tinglovchilar = new Set<() => void>();
const oqi = () => xotira;
const obuna = (f: () => void) => {
tinglovchilar.add(f);
return () => tinglovchilar.delete(f);
};
function temaniQoy(t: Tema) {
xotira = t;
for (const f of tinglovchilar) f();
}
function tizimRangi(): string {
const qorongi = matchMedia("(prefers-color-scheme: dark)").matches;
return qorongi ? "qorong'i" : "yorug'";
}
function ThemePicker() {
const tema = useSyncExternalStore(obuna, oqi, () => "tizim");
const korinish =
tema === "tizim" ? `tizim (${tizimRangi()})` : tema;
return (
<fieldset>
<legend>Mavzu</legend>
<button onClick={() => temaniQoy("tizim")}>Tizim</button>{" "}
<button onClick={() => temaniQoy("yorug")}>Yorug'</button>{" "}
<button onClick={() => temaniQoy("qorongi")}>Qorong'i</button>
<p>Joriy: {korinish}</p>
</fieldset>
);
}
export default function App() {
return <ThemePicker />;
}Ekranda:
Mavzu
Tizim Yorug' Qorong'i
Joriy: tizim (yorug')matchMedia faqat brauzerda bor — shuning uchun bu funksiya client komponentda, render paytida chaqiriladi. Haqiqiy Next'da serverda matchMedia yo'q: u yerda getServerSnapshot "tizim" qaytaradi, aniq rangni esa CSS (@media (prefers-color-scheme: dark)) hal qiladi — JS'siz.
3-mashq (qiyin): CSS Module modeli
CSS Module klass nomini qanday yasashini modellashtiring: modulNomi(fayl, klass) — fayl nomidan qisqa xesh yasab ([...fayl] belgilar kodlari yig'indisini 36 lik sanoq tizimida, oxirgi 6 belgi), xesh_klass qaytarsin. Ikki fayldagi bir xil .karta turli nom olishini ko'rsating. Belgi kodi — codePointAt(0), 36 lik — toString(36) (sanoq tizimlari).
Yechim
function xesh(matn) {
let h = 0;
for (const b of matn) h = (h * 31 + b.codePointAt(0)) >>> 0;
return h.toString(36).slice(-6);
}
function modulNomi(fayl, klass) {
return `${xesh(fayl)}_${klass}`;
}
const a = modulNomi("loyihalar/LoyihaKartasi.module.css", "karta");
const b = modulNomi("blog/PostKartasi.module.css", "karta");
console.log(a);
console.log(b);
console.log(a === b);
const yana = modulNomi("loyihalar/LoyihaKartasi.module.css", "karta");
console.log(a === yana);Konsolda:
a7o2re_karta
32ihy5_karta
false
trueBir xil karta, turli fayl — turli nom (to'qnashuv yo'q). Bir xil fayl — har build'da bir xil nom (barqaror, kesh buzilmaydi). Next'ning haqiqiy algoritmi boshqa (Lightning CSS), lekin ikki xususiyat aynan shu: noyob va barqaror. Kanondagi .k4BiaG_karta ham shunday yasalgan.
4-mashq: Portfolio qadami
Loyiha kartasini CSS Module'ga o'tkazing («Portfolio qadami» jadvali). Build'dan keyin .next/static/chunks/ da _karta bor CSS faylni toping va hajmini ko'ring. 4 ta holatda (mobil/desktop × yorug'/qorong'i) /loyihalar ni tekshirib, commit qiling.
Yechim
Kutilgan: alohida, bir necha yuz baytli CSS fayl, ichida .xxxxxx_karta (prefiks sizda boshqa). Agar kartalarda ichki bo'sh qatorlar ko'rinsa — .karta > * { margin: 0 } va align-content: start qo'shilmagan. Qorong'i rejimni tez sinash: DevTools → Rendering → "Emulate CSS prefers-color-scheme: dark", yoki mavzu tanlovidan «Qorong'i».
11. Real ishda
- Yangi Next loyihalarining ko'pi Tailwind + shadcn/ui bilan boshlanadi —
create-next-appsukuti ham shunday. Mavjud dizayn tizimi bo'lsa — CSS Modules yoki zero-runtime yechimlar. - MUI, Chakra kabi katta UI kutubxonalari App Router uchun alohida qo'llanma beradi (registry,
"use client"). Kompaniyalar ba'zan aynan shu sababdan zero-runtime yechimlarga ko'chmoqda. - Qorong'i rejim — deyarli har zamonaviy saytda; "chaqnash" — eng ko'p uchraydigan sifat xatosi.
- Intervyu savoli: "Nega styled-components Server Component'da ishlamaydi?", "CSS Modules qanday izolyatsiya qiladi?", "Qorong'i rejimda chaqnashni qanday yo'qotasiz?"
Xulosa
- Global CSS root layout'da; tartib import tartibiga bog'liq,
@layeruni barqaror qiladi. - CSS Module (
*.module.css) klasslarni noyob qiladi (.k4BiaG_karta), tokenlar va qatlamlar ishlayveradi. - Tailwind
create-next-appda sukut (Turbopack loader orqali); kanon uni olib tashladi — 18 MB, 20 paket va qayta yozish narxi. - Runtime CSS-in-JS — faqat Client Component'da, registry bilan; build vaqtidagi yechimlar Server Component'lar bilan to'qnashmaydi.
- Qorong'i rejim:
<head>skripti +suppressHydrationWarning+getServerSnapshot— chaqnashsiz, hydration xatosiz, sahifalar statik.
Keyingi dars: i18n Next.js'da: next-intl — portfolio ga ingliz tilini qo'shamiz: [locale] segmenti, proxy, tarjima xabarlari va hreflang.
Manbalar
- Next.js hujjati (16.4.0,
node_modules/next/dist/docs/): "CSS" (Tailwind, CSS Modules, Global CSS, Ordering and Merging), "CSS-in-JS", "Preventing flash before hydration" — nextjs.org/docs/app/getting-started/css (2026-10-21 da o'qildi) - Kanon natijalari:
natijalar/tajriba/33-tailwind.txt,natijalar/tekshiruv-33.txt,natijalar/surat/33-*; holat 33 va holat 13 (TemaProvider,TemaSkripti) - CSS Module chiqishi — biz ishga tushirdik:
portfolioholat 32 nusxasi + holat 33 o'zgarishlari,next build, next 16.4.0, 2026-10-21 - shadcn/ui — ui.shadcn.com/docs/installation/next; next-themes — github.com/pacocoursey/next-themes
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!