CSS Modules — nima, qanday ishlaydi, global va local
Muammodan boshlaylik
Siz katta jamoada ishlayapsiz. Bir kuni Jasur .title klassini yozdi — sariq rang, katta shrift. Siz ham .title yozdingiz — boshqa komponent uchun, qizil rang. Brauzerda ikkalasi ham bir sahifaga tushdi. Qaysi .title ustun kelishini hech kim aniq bilmaydi.
Ertasi kuni Malika .btn yozdi. Siz ham .btn yozdingiz — boshqa joylarda. Stillar bir-birini bosib ketdi. Qaysi komponent qaysi stildan kelganini aniqlash uchun DevTools da uzoq vaqt sarfladingiz.
Bu — global CSS ning asosiy muammosi. Katta loyihalarda klasslar bir-birini bosib ketadi, qaysi stil qayerdan kelganini aniqlash qiyinlashadi, birovning stilini o'zgartirsangiz boshqa joyni buzasiz.
CSS Modules aynan shu muammoni hal qilish uchun yaratilgan.
CSS Modules nima?
CSS Modules — bu oddiy CSS fayl, lekin unda yozilgan barcha klasslar avtomatik ravishda faqat o'sha komponentga tegishli bo'ladi. Boshqa komponentga o'tib ketmaydi.
Fayl nomi .module.css bilan tugaydi — ana shu farq. Button.module.css — CSS Module. Button.css — oddiy global CSS.
Hayotiy o'xshatma: tasavvur qiling, har bir xonaning o'z kalit raqami bor — 101, 102, 103. Siz faqat o'z xonangizning kalitini ishlatasiz, boshqa xonaga kirmaydigan kalit. CSS Modules ham shunday — har klassga noyob raqam qo'shib, faqat o'z komponentida ishlashini ta'minlaydi.
Qanday ishlaydi?
Siz yozasiz:
/* Button.module.css */
.btn {
background: #3b82f6;
color: white;
padding: 10px 20px;
border-radius: 6px;
border: none;
cursor: pointer;
}
.btn:hover {
background: #2563eb;
}
Brauzerga yetib borganda Vite/Webpack bu klassni o'zgartiradi:
.btn → .btn_xK92a (yoki _btn_abc12 — build vositasiga qarab)
Oxiridagi tasodifiy belgilar — shu komponent uchun noyob imzo. Boshqa komponentdagi .btn boshqa imzo oladi. Ular bir-biriga tegmaydi.
Birinchi misol
src/
components/
Button/
Button.jsx
Button.module.css
/* Button.module.css */
.btn {
background: #3b82f6;
color: white;
padding: 10px 20px;
border-radius: 6px;
border: none;
cursor: pointer;
font-size: 14px;
}
.primary {
background: #3b82f6;
}
.danger {
background: #ef4444;
}
.outline {
background: transparent;
border: 1px solid #3b82f6;
color: #3b82f6;
}
// Button.jsx
import styles from './Button.module.css';
export function Button({ variant = 'primary', children }) {
return (
<button className={styles.btn}>
{children}
</button>
);
}
styles.btn — bu oddiy string: "btn_xK92a". Brauzerga shunday yetib boradi.
// Ishlatish
<Button>Saqlash</Button>
Bir nechta klass qo'shish
import styles from './Button.module.css';
export function Button({ variant = 'primary', children }) {
return (
// styles.btn + styles[variant] — ikki klass birlashadi
<button className={`${styles.btn} ${styles[variant]}`}>
{children}
</button>
);
}
<Button variant="danger">O'chirish</Button>
// className="btn_xK92a danger_mP3q1"
Nima uchun styles[variant]? Chunki variant — o'zgaruvchi. styles.primary, styles.danger, styles.outline — bularni dinamik olish uchun [] ishlatiladi.
Klas nomi notog'ri bo'lsa nima bo'ladi?
// styles.notExists → undefined
<button className={styles.notExists}>
undefined className ga o'tadi — brauzerda class="undefined" bo'ladi. Bu ko'rinishda xato qilmaslik uchun TypeScript bilan ishlash qulay — u mavjud bo'lmagan klassni ko'rsatib beradi.
Global va Local — farqi
CSS Modules da ikkita rejim bor: local (standart) va global.
Local — standart holat
/* styles.module.css */
.title {
font-size: 24px;
}
/* Brauzerda: .title_xK92a { font-size: 24px } */
Barcha klasslar standart holda local — noyob imzo oladi.
:global — butun sahifaga tegishli
Ba'zan siz uchinchi tomon kutubxona klassini yoki butun ilova bo'ylab ishlaydigan klassni o'zgartirmoqchi bo'lasiz. :global shu uchun:
/* styles.module.css */
.wrapper {
padding: 20px;
}
/* Bu klass imzo olMaydi — global qoladi */
:global(.react-datepicker) {
font-size: 13px;
border-radius: 8px;
}
:global(.active) {
font-weight: 600;
}
.wrapper → .wrapper_xK92a (local — o'zgartirildi)
.react-datepicker → .react-datepicker (global — o'zgarmadi)
Nima uchun :global kerak? Uchinchi tomon kutubxonalar (React DatePicker, Swiper, Ant Design) o'zlarining klasslarini ishlatadi. Siz ularni CSS Module ichidan o'zgartirmoqchi bo'lsangiz — :global yozing, aks holda o'zgartirishingiz ular klassiga yetib bormaydi.
:local — global faylda local klass
Agar butun faylingiz global bo'lsa (masalan, global stillar uchun) va shu ichida bitta klassni local qilmoqchi bo'lsangiz:
/* global.css — oddiy CSS, Modules emas */
/* Bu stillar global ishlaydi */
:local(.specialCard) {
border: 1px solid red;
}
/* Brauzerda: .specialCard_xK92a */
Amalda bu juda kam ishlatiladi — odatda .module.css faylda ishlaysiz va hammasi local bo'ladi.
composes — klass meros olish
CSS Modules da bir klassdan boshqasini "meros" qilish mumkin:
/* base.module.css */
.flexCenter {
display: flex;
align-items: center;
justify-content: center;
}
/* Card.module.css */
.card {
composes: flexCenter from './base.module.css'; /* ← tashqi fayldan */
background: white;
padding: 20px;
border-radius: 8px;
}
.header {
composes: flexCenter; /* ← o'z faylidan */
border-bottom: 1px solid #eee;
padding-bottom: 12px;
}
// Brauzerda card elementi ikkita klass oladi:
// className="card_abc flexCenter_xyz"
// ikkalasining stillari ishlaydi
composes — CSS Modules ning kuchli xususiyati. SCSS dagi @extend ga o'xshaydi, lekin build vaqtida ishlaydi — runtime xarajati yo'q.
Amaliy misol — to'liq komponent
/* UserCard.module.css */
.card {
background: white;
border: 1px solid #e5e7eb;
border-radius: 12px;
padding: 20px;
display: flex;
gap: 16px;
align-items: center;
transition: box-shadow 0.2s;
}
.card:hover {
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
}
.avatar {
width: 48px;
height: 48px;
border-radius: 50%;
object-fit: cover;
flex-shrink: 0;
}
.info {
flex: 1;
}
.name {
font-size: 15px;
font-weight: 600;
color: #111827;
margin-bottom: 2px;
}
.role {
font-size: 13px;
color: #6b7280;
}
.badge {
font-size: 11px;
font-weight: 600;
padding: 3px 8px;
border-radius: 20px;
text-transform: uppercase;
letter-spacing: 0.04em;
}
.badgeAdmin {
composes: badge;
background: rgba(239, 68, 68, 0.1);
color: #dc2626;
}
.badgeUser {
composes: badge;
background: rgba(59, 130, 246, 0.1);
color: #2563eb;
}
// UserCard.jsx
import styles from './UserCard.module.css';
export function UserCard({ user }) {
const badgeClass = user.role === 'admin'
? styles.badgeAdmin
: styles.badgeUser;
return (
<div className={styles.card}>
<img
src={user.avatar}
alt={user.name}
className={styles.avatar}
/>
<div className={styles.info}>
<p className={styles.name}>{user.name}</p>
<p className={styles.role}>{user.email}</p>
</div>
<span className={badgeClass}>{user.role}</span>
</div>
);
}
Ushbu komponent boshqa komponentning stillariga ta'sir qilmaydi — hech qanday nom konflikti yo'q.
Tez-tez uchraydigan xatolar
Defis bilan yozilgan klassga murojaat
/* styles.module.css */
.primary-btn {
background: blue;
}
// ❌ Xato — defis JavaScript da ruxsat etilmaydi
<div className={styles.primary-btn}>
// ✅ To'g'ri — kvadrat qavslar bilan
<div className={styles['primary-btn']}>
Shuning uchun CSS Modules da klasslarni camelCase yozish qoidaga aylangan: primaryBtn, cardHeader, errorText — shunda styles.primaryBtn to'g'ridan-to'g'ri ishlaydi.
Klass mavjudligini tekshirmaslik
// styles.loading mavjud emas — className="undefined" bo'ladi
<div className={styles.loading}>
Agar klass dinamik bo'lsa va ba'zan bo'lmasligi mumkin bo'lsa:
// ✅ To'g'ri — undefined o'tmaslik uchun
<div className={isLoading ? styles.loading : ''}>
:global haddan tashqari ko'p ishlatish
/* ❌ Yomon — CSS Modules ning maqsadini yo'qotadi */
:global(.title) { color: red; }
:global(.card) { background: white; }
:global(.btn) { padding: 10px; }
:global faqat uchinchi tomon kutubxonalari yoki haqiqiy global stillar uchun. Har doim local klasslarni afzal ko'ring.
CSS Modules vs boshqa yondashuv lar
CSS Modules:
+ Qurilish vaqtida — runtime xarajati yo'q
+ Oddiy CSS sintaksisi — yangi narsa o'rganish shart emas
+ Har qanday framework bilan ishlaydi
- className="string" — bir nechta klass dinamik boshqarish ba'zan og'ir
Styled Components:
+ Props bilan dinamik stil — juda qulay
+ TypeScript integratsiya yaxshi
- Runtime xarajat bor — brauzerda CSS yaratialdi
- Katta paket hajmi
Tailwind CSS:
+ HTML ichida — alohida fayl yo'q
+ Juda tez prototiplash
- className juda uzun bo'lishi mumkin
- CSS sintaksisini bilish shart emas degan yanglish tushuncha
CSS Modules — CSS ni yaxshi bilganlar uchun ideal. Hech qanday yangi sintaksis yo'q, hamma narsa oddiy CSS — faqat nom konflikti muammosi hal qilingan.
Xulosa
CSS Modules — nom konflikti muammosini hal qiladigan oddiy mexanizm. .module.css bilan tugaydigan fayl yozasiz, barcha klasslar avtomatik noyob nom oladi, boshqa komponentga o'tib ketmaydi.
Eslab qoling:
.module.css— CSS Modules fayliimport styles from './Component.module.css'— import qilishstyles.className— klass nomiga murojaatstyles['defis-li-nom']— defis bo'lsa kvadrat qavslar:global(.klass)— uchinchi tomon kutubxonalari uchuncomposes— klass meros olish- Klasslarni
camelCaseyozish — eng qulay yo'l
Keyingi dars
36-dars: Styled Components — CSS in JS, props bilan dinamik stil