18-bo‘lim
Komponentlar amaliyoti
BEM nomlash tizimi, CSS ni tashkil qilish va tugma, forma, kartochka, modal kabi komponentlar yaratish.
Ushbu bo‘lim mundarijasi
Loyiha o'sgani sari CSS boshqarib bo'lmas holga keladi. Buning yechimi - komponentlarga bo'lish va aniq nomlash tizimi.
BEM nomlash tizimi #
BEM = Block, Element, Modifier.
.blok { } /* mustaqil komponent */
.blok__element { } /* komponent qismi */
.blok--modifikator { } /* komponent varianti */
<article class="karta karta--mashhur">
<img class="karta__rasm" src="..." alt="...">
<div class="karta__tana">
<h3 class="karta__sarlavha">Python darsligi</h3>
<p class="karta__matn">Noldan boshlab...</p>
<a class="karta__tugma karta__tugma--asosiy" href="...">Boshlash</a>
</div>
</article>
/* Blok */
.karta {
background: var(--fon);
border: 1px solid var(--chegara);
border-radius: 14px;
overflow: hidden;
}
/* Elementlar */
.karta__rasm {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
}
.karta__tana {
padding: 1.25rem;
}
.karta__sarlavha {
margin: 0 0 0.5rem;
font-size: 1.15rem;
}
/* Modifikator */
.karta--mashhur {
border-color: var(--asosiy);
border-width: 2px;
}
.karta--gorizontal {
display: grid;
grid-template-columns: 180px 1fr;
}
- Nom bo'yicha joyini bilasiz.
.karta__sarlavhani ko'rib, u qayerda ishlatilishini darhol tushunasiz. - Ustunlik tekis. Barcha selektorlar bir xil kuchda (10 ball) - kaskad bilan urushish kerak emas.
- Ichma-ichlik yo'q.
.karta .sarlavha span akabi zanjirlar paydo bo'lmaydi. - Nomlar to'qnashmaydi.
.karta__sarlavhaboshqa hech qayerga ta'sir qilmaydi.
/* Yomon: ikki daraja element */
.karta__tana__sarlavha { }
/* Yaxshi: element faqat bir daraja */
.karta__sarlavha { }
/* Yomon: modifikator yolg'iz ishlatilgan */
<div class="karta--mashhur">
/* Yaxshi: asl klass bilan birga */
<div class="karta karta--mashhur">
CSS faylini tashkil qilish #
css/
├── uslub.css <- barchasini import qiladi
├── asos/
│ ├── qayta-yozish.css (reset)
│ ├── ozgaruvchilar.css
│ └── tipografiya.css
├── komponentlar/
│ ├── tugma.css
│ ├── karta.css
│ ├── forma.css
│ └── modal.css
└── sahifalar/
├── bosh.css
└── darslik.css
/* uslub.css */
@import "asos/qayta-yozish.css";
@import "asos/ozgaruvchilar.css";
@import "asos/tipografiya.css";
@import "komponentlar/tugma.css";
@import "komponentlar/karta.css";
@import "komponentlar/forma.css";
@import "komponentlar/modal.css";
@import "sahifalar/bosh.css";
@import ishlab chiqarishda sekinHar bir @import alohida so'rov yuboradi va ular ketma-ket yuklanadi.
Kichik loyiha uchun muammo emas, lekin katta saytda barcha fayllarni
bitta faylga birlashtirish (build vositasi bilan) yoki oddiygina bitta
katta .css fayl yozish afzalroq.
Asosiy sozlamalar (reset) #
/* asos/qayta-yozish.css */
*, *::before, *::after {
box-sizing: border-box;
}
* {
margin: 0;
}
body {
min-height: 100vh;
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
img, picture, video, canvas, svg {
display: block;
max-width: 100%;
}
input, button, textarea, select {
font: inherit;
color: inherit;
}
p, h1, h2, h3, h4, h5, h6 {
overflow-wrap: break-word;
}
ul[class], ol[class] {
list-style: none;
padding: 0;
}
a:not([class]) {
text-decoration-skip-ink: auto;
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
input { font: inherit } nima uchun kerak?Brauzerlar forma elementlariga o'z shriftini beradi - u sahifa shriftidan farq qiladi. Bu qator ularni bir xil qiladi. Eng ko'p unutiladigan qatorlardan biri.
Komponent: tugma #
.tugma {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 0.65rem 1.3rem;
min-height: 44px;
border: 1px solid transparent;
border-radius: 8px;
font-size: 0.95rem;
font-weight: 600;
line-height: 1;
text-decoration: none;
white-space: nowrap;
cursor: pointer;
transition: background 0.18s, border-color 0.18s, transform 0.1s;
}
.tugma:active {
transform: translateY(1px);
}
.tugma:focus-visible {
outline: 2px solid var(--asosiy);
outline-offset: 2px;
}
.tugma:disabled,
.tugma[aria-disabled="true"] {
opacity: 0.55;
cursor: not-allowed;
transform: none;
}
/* Variantlar */
.tugma--asosiy {
background: var(--asosiy);
color: #fff;
}
.tugma--asosiy:hover:not(:disabled) {
background: var(--asosiy-toq);
}
.tugma--ikkilamchi {
background: #fff;
color: var(--matn);
border-color: var(--chegara);
}
.tugma--ikkilamchi:hover:not(:disabled) {
background: var(--fon-yumshoq);
}
.tugma--xavfli {
background: #fff;
color: #dc2626;
border-color: #fecaca;
}
.tugma--xavfli:hover:not(:disabled) {
background: #dc2626;
border-color: #dc2626;
color: #fff;
}
.tugma--shaffof {
background: transparent;
color: var(--matn-och);
}
/* O'lchamlar */
.tugma--kichik { padding: 0.4rem 0.85rem; font-size: 0.85rem; min-height: 36px; }
.tugma--katta { padding: 0.9rem 1.8rem; font-size: 1.05rem; min-height: 52px; }
.tugma--toliq { display: flex; width: 100%; }
<button class="tugma tugma--asosiy">Saqlash</button>
<button class="tugma tugma--ikkilamchi">Bekor qilish</button>
<button class="tugma tugma--xavfli tugma--kichik">O'chirish</button>
<a href="#" class="tugma tugma--asosiy tugma--katta tugma--toliq">Boshlash</a>
Komponent: forma #
.maydon {
display: grid;
gap: 0.4rem;
margin-bottom: 1.1rem;
}
.maydon__yorliq {
font-size: 0.9rem;
font-weight: 600;
color: var(--matn);
}
.maydon__yorliq--majburiy::after {
content: " *";
color: #dc2626;
}
.maydon__kirish {
width: 100%;
padding: 0.65rem 0.85rem;
border: 1px solid var(--chegara);
border-radius: 8px;
background: #fff;
transition: border-color 0.18s, box-shadow 0.18s;
}
.maydon__kirish:focus {
outline: none;
border-color: var(--asosiy);
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15);
}
.maydon__kirish::placeholder {
color: var(--matn-och);
}
.maydon__kirish:disabled {
background: var(--fon-yumshoq);
cursor: not-allowed;
}
.maydon__yordam {
font-size: 0.82rem;
color: var(--matn-och);
}
.maydon__xato {
font-size: 0.82rem;
color: #dc2626;
}
/* Xato holati */
.maydon--xato .maydon__kirish {
border-color: #dc2626;
background: #fef2f2;
}
/* Foydalanuvchi to'ldirgandan keyin tekshirish */
.maydon__kirish:not(:placeholder-shown):invalid {
border-color: #dc2626;
}
:not(:placeholder-shown):invalidOddiy :invalid foydalanuvchi hali hech narsa yozmasdan ham qizil ramka
ko'rsatadi - bu bezovta qiladi. Bu selektor esa faqat matn kiritilgandan keyin
tekshiradi.
Komponent: bildirishnoma #
.xabar {
display: flex;
gap: 0.8rem;
padding: 0.9rem 1.1rem;
border: 1px solid;
border-radius: 10px;
font-size: 0.93rem;
}
.xabar__ikonka { flex: none; font-size: 1.1rem; line-height: 1.4; }
.xabar__tana { flex: 1; }
.xabar__yopish {
flex: none;
background: none;
border: none;
cursor: pointer;
opacity: 0.6;
font-size: 1.2rem;
line-height: 1;
}
.xabar--muvaffaqiyat { background: #f0fdf4; border-color: #bbf7d0; color: #14532d; }
.xabar--xato { background: #fef2f2; border-color: #fecaca; color: #7f1d1d; }
.xabar--ogohlantirish{ background: #fffbeb; border-color: #fde68a; color: #78350f; }
.xabar--malumot { background: #eff6ff; border-color: #bfdbfe; color: #1e3a8a; }
<div class="xabar xabar--muvaffaqiyat" role="status">
<span class="xabar__ikonka" aria-hidden="true">✔</span>
<div class="xabar__tana">Ma'lumotlaringiz saqlandi.</div>
<button class="xabar__yopish" aria-label="Yopish">×</button>
</div>
Komponent: yorliqlar (tabs) #
.yorliqlar {
display: flex;
gap: 0.25rem;
border-bottom: 1px solid var(--chegara);
overflow-x: auto;
}
.yorliqlar__element {
padding: 0.7rem 1.1rem;
background: none;
border: none;
border-bottom: 2px solid transparent;
color: var(--matn-och);
font-weight: 600;
white-space: nowrap;
cursor: pointer;
transition: color 0.18s, border-color 0.18s;
}
.yorliqlar__element:hover {
color: var(--matn);
}
.yorliqlar__element[aria-selected="true"] {
color: var(--asosiy);
border-bottom-color: var(--asosiy);
}
Komponent: modal #
.modal-fon {
position: fixed;
inset: 0;
background: rgba(15, 23, 42, 0.55);
display: grid;
place-items: center;
padding: 1rem;
z-index: 1000;
}
.modal {
position: relative;
width: min(500px, 100%);
max-height: 85vh;
overflow-y: auto;
background: var(--fon);
border-radius: 16px;
padding: 1.75rem;
box-shadow: 0 24px 48px rgba(15, 23, 42, 0.25);
}
.modal__sarlavha {
margin: 0 0 0.4rem;
padding-right: 2rem;
font-size: 1.25rem;
}
.modal__yopish {
position: absolute;
top: 1rem;
right: 1rem;
width: 32px;
height: 32px;
border: none;
border-radius: 50%;
background: var(--fon-yumshoq);
cursor: pointer;
}
.modal__tugmalar {
display: flex;
gap: 0.6rem;
justify-content: flex-end;
margin-top: 1.5rem;
}
<dialog> tegiZamonaviy HTML da modal uchun tayyor element bor:
<dialog id="oyna" class="modal">
<h2>Tasdiqlash</h2>
<p>Rostdan ham o'chirmoqchimisiz?</p>
<form method="dialog">
<button class="tugma tugma--ikkilamchi">Bekor</button>
<button class="tugma tugma--xavfli">O'chirish</button>
</form>
</dialog>
document.getElementById("oyna").showModal();
<dialog> avtomatik ravishda: fokusni ushlab turadi, Esc bilan yopiladi va
orqa fonni bloklaydi. Bularni qo'lda yozish ancha murakkab.
Yordamchi klasslar #
/* Faqat ekran o'quvchisi uchun */
.vizual-yashirin {
position: absolute;
width: 1px; height: 1px;
padding: 0; margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
/* Matnni kesish */
.bir-satr {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.uch-satr {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
/* Konteyner */
.orash {
width: min(1200px, 100% - 2rem);
margin-inline: auto;
}
/* Vizual yashirish */
.yashirin { display: none !important; }
Komponent yozish qoidalari #
| Qoida | Sabab |
|---|---|
| Komponent o'z joyini bilmasin | Qayerga qo'ysangiz ham ishlasin |
Tashqi margin bermang | Joylashuvni ota element hal qilsin |
| Kenglikni belgilamang | Konteyner belgilasin |
| Har bir variant - modifikator | .tugma--katta, .tugma--xavfli |
| Bitta komponent - bitta fayl | Topish va o'zgartirish oson |
/* Yomon: komponent o'z joyini biladi */
.karta {
margin-bottom: 2rem;
width: 300px;
float: left;
}
/* Yaxshi: joylashuvni ota hal qiladi */
.karta {
background: #fff;
border-radius: 12px;
}
.kartalar {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 2rem;
}
komponentlar/papkasini yarating va CSS ni fayllarga bo'ling.- Reset faylini yozing (yuqoridagi namunani asos qiling).
.tugmakomponentini 4 ta variant va 3 ta o'lcham bilan yarating..maydonforma komponentini xato holati bilan yozing..xabarbildirishnomasini 4 ta turda qiling.- Barcha komponentlarni bitta "namunalar sahifasi" (styleguide) da ko'rsating.
- BEM qoidalariga rioya qiling - hech qanday ichma-ich selektor bo'lmasin.
- Har bir komponentda
:focus-visibleva:disabledholatlari bo'lsin.
Xulosa #
- BEM:
.blok,.blok__element,.blok--modifikator. - BEM ustunlikni tekis saqlaydi va nomlar to'qnashuvini yo'q qiladi.
- CSS ni asos / komponentlar / sahifalar ga bo'ling.
- Har bir loyiha reset bilan boshlanadi;
input { font: inherit }ni unutmang. - Komponent o'z joyini bilmasligi kerak - tashqi margin va kenglik bermang.
- Har bir interaktiv komponentda
:hover,:focus-visible,:disabledholatlari bo'lsin. - Modal uchun
<dialog>tegini ko'rib chiqing - u ko'p ishni o'zi bajaradi.
Keyingi bo'limda saytni tezlashtirish va kirish imkoniyatini yaxshilashni o'rganamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.