IlmHamroh
JavaScript Full-stack/5-qism. CSS asoslari va layout63/63-dars31 daqiqa
Mundarija (45)

Yakuniy loyiha: portfolio'ni CSS bilan bezash va responsive qilish

Qisqacha: 05-qism davomida o'sgan asosiy.css yetti bo'limli toza faylga yig'iladi: reset, o'zgaruvchilar, umumiy, layout, komponentlar, afzalliklar, chop etish. Qadamlar orasidagi ziddiyatlar tuzatiladi, qorong'i rejim qo'shiladi. Sayt 320–1280 pikselda, klaviatura, qorong'i rejim va qog'ozda tekshiriladi. Natija — Lighthouse Accessibility 100 va internetda yangilangan portfolio, HTML esa deyarli o'zgarmaydi.

Bu darsda

  • 62 ta portfolio qadamini yetti bo'limli asosiy.css ga yig'asiz.
  • Zid qoidalarni topib, qaysi biri qolishini asoslaysiz.
  • Portfolio'ga prefers-color-scheme bilan qorong'i rejim qo'shasiz.
  • Saytni DevTools, klaviatura, html-validate va Lighthouse bilan tekshirasiz.
  • Saytni qayta joylab, 100 ballik ro'yxat bo'yicha baholaysiz.

Oldin bilishingiz kerak: Yakuniy loyiha: HTML portfolio, Birinchi deploy, Intrinsic layout, Foydalanuvchi afzalliklari, Mobil tuzoqlar.

1. Nega bu kerak?

HTML qismining yakuniy loyihasida portfolio oq fonda qora matn edi. Keyin 62 dars davomida har darsning oxirgi mashqi unga bitta qadam qo'shdi.

Fayl "qatlam-qatlam" o'sdi: ba'zi qoidalarni keyingi dars almashtirdi, ba'zilari ikki joyda qoldi, bir nechtasi hatto bir-birini buzadi.

Ta'mirdan keyingi uyni eslang: ustalar ketdi, ko'chishdan oldin qoldiq gipsni supurasiz va har chiroqni yoqib ko'rasiz. Bu dars — aynan shu "qabul qilish".

2. Loyiha talablari

2.1 HTML'da nima o'zgaradi

05-qism davomida HTML'ga faqat kichik qo'shimchalar kirdi.

Fayl O'zgarish Dars
6 sahifa link rel="stylesheet", shrift preload CSS ulash, Web shriftlar
5 sahifa (404 dan tashqari) Skip link'ga class="otish" position
loyihalar/index.html div class="loyihalar", korinmas matn Grid'ga kirish, position
loyihalar/index.html Karta ro'yxatlariga role="list" shu dars
index.html Rasmga srcset va sizes Rasmlar CSS tomoni, shu dars
haqimda/index.html Jadval — 12 oy fixed va sticky

Matnni ham yangilang: "Keyingi qadam — CSS" o'rniga "Keyingi qadam — JavaScript"; "Nimalarni bilaman" va "Men haqimda" dagi dl ga CSS bilimlaringizni qo'shing.

2.2 CSS talablari

  • Bitta fayl: sayt/assets/css/asosiy.css, yetti izohli bo'lim.
  • Ranglar: faqat :root dagi o'zgaruvchilarda (chop etish qismidan tashqari).
  • Layout: markaziy ustun, header — Cluster, loyihalar — RAM to'ri, sticky footer.
  • Responsive: mobile-first; en bo'yicha media query — faqat bittasi (bosh sahifa "rasm"i).
  • Accessibility: skip link faqat fokusda, fokus halqasi, bosish nishonlari kamida 24×24.
  • Afzalliklar: qorong'i rejim, hover faqat sichqonchada, chop etish uslubi.

2.3 Sifat mezonlari

  • 320, 360, 768 va 1280 pikselda gorizontal skroll yo'q.
  • npm run check — 0 xato (Prettier + html-validate).
  • Lighthouse (Mobile): Performance ≥ 90, Accessibility 100, Best Practices ≥ 95, SEO 100.
  • Qorong'i rejimda ham hamma matn kontrasti ≥ 4.5:1.

2.4 Cheklovlar

  • style atributi, <style> tegi va JavaScript — yo'q.
  • class — faqat uchta: otish, loyihalar, korinmas. Qolgani — teg va atribut selektorlari.
  • !important — faqat [hidden] qoidasida (display darsidagi asoslangan istisno).

Tekshirib ko'ring: Nega portfolio'da .menyu, .karta kabi class'lar yo'q, lekin sayt baribir to'liq bezalgan?

Javob

HTML semantik: nav[aria-label="Asosiy menyu"], main > img, details[name="savollar"] — har element ma'nosi bilan topiladi (Atribut selektorlari, :has()). Class faqat ma'nosi yo'q joyga kerak bo'ldi: kartalar guruhi (div), skip link va ko'rinmas matn.

3. Ish tartibi: besh bosqich

# Bosqich Natija
1 Inventarizatsiya Qoidalar manbasi va ziddiyatlar
2 Skelet Yetti bo'limli bo'sh fayl
3 Yig'ish To'ldirilgan bo'limlar
4 Tekshirish DevTools, klaviatura, html-validate, Lighthouse
5 Deploy Yangilangan sayt internetda

Eski faylni asosiy-eski.css deb sayt/ dan tashqariga ko'chiring — solishtirish uchun.

4. 1-bosqich: inventarizatsiya va ziddiyatlar

4.1 Faylni o'qib chiqing

Har qoida yoniga qaysi darsdan kelganini yozing: /* Auto margin darsi */. Ikki joyda uchragan selektor (header, .loyihalar) — ziddiyatga birinchi nomzod.

Keyin DevTools → Styles'da ustidan chizilgan deklaratsiyalarni qidiring (DevTools'da CSS): boshqa qoida yutgan, demak ulardan biri ortiqcha.

4.2 Topilgan ziddiyatlar va qarorlar

Namunaviy yechimni Chrome'da yig'ib topganlarimiz:

Joy Nima zid Qaror
header Flex naqshlari flex, Media queries darsida @media, Intrinsic layout darsida Cluster Intrinsic layout Cluster, media blok o'chadi
Menyu ul Flex'da tekislash va Flex naqshlari darsida ikki xil gap Flex naqshlari: gap + havola padding (bosish nishoni)
.loyihalar 1fr 1fr → RAM → media → yana RAM RAM (Intrinsic layout) + fluid gap (Fluid tipografiya)
Non yo'li Ro'yxatlar stili inline, Auto margin flex va "…" Auto margin
Bosh sahifa rasmi Normal oqim float, grid-template-areas grid, Rasmlar CSS tomoni sizes float o'chadi, sizes qayta hisoblanadi
tbody tr:last-child Tuzilma pseudo-klasslari "oxirgi qator — joriy oy", fixed va sticky darsida 12 oy Qoida o'chadi
Forma rangi Holat pseudo-klasslari darsidagi #b4461a :root ga ko'chmagan --rang-urgu

Yana uchtasi faqat brauzerda, o'lchaganda ko'rindi.

1. Grid main cho'zilib ketadi. Flex naqshlari darsida sticky footer uchun main { flex: 1 } yozdik — main ekranning bo'sh joyini oladi. Layout naqshlari darsida esa shu main ni grid qildik. Qisqa sahifada ortiqcha bo'y grid qatorlariga bo'linadi: 1280 pikselda sarlavha, kirish matni va kartalar orasida 100 pikseldan ortiq bo'shliq chiqdi. Tuzatish — Grid'da tekislash darsidagi align-content: start.

2. width: auto endi ishlamaydi. Layout naqshlari darsidagi width: auto breakout to'riga butun enni berishi kerak edi. Lekin body endi flex ustun, main da esa margin-inline: auto — bunday flex elementi mazmuniga qarab qisqaradi (Auto margin). O'lchadik: 1280 pikselda main 1265 emas, 920 piksel. Tuzatish — inline-size: 100%.

3. Subgrid va konteyner bitta kartada. subgrid darsida karta ichini ota to'rga uladik, Container queries darsida esa o'sha article ni konteyner qildik. Chrome'da uchta karta bilan tekshirdik: container-type bor kartalarda subgrid ishlamadi, sanalar "zinapoya" bo'ldi. Konteyner o'z ichini tashqi to'rdan uzib qo'yadi: container-type siz uchala karta bir chiziqqa tushdi. Qaror: subgrid qoladi, havolalar esa Intrinsic layout darsidagi Cluster bilan o'raladi. Container queries «Bahor»da va 06-qism komponentlarida ishlatilaveradi.

Maslahat: Har tuzatishdan keyin sahifani 360 va 1280 pikselda qayta oching — bitta tuzatish boshqa joyni buzishi mumkin.

5. 2-bosqich: tayyor skelet

Tartib kaskadga mos: umumiy va yengil qoidalar tepada, aniq va holatga bog'liqlari pastda (Kaskad).

flowchart TD
  A["1. Reset<br/>box-sizing, rasm, shrift"] --> B["2. O'zgaruvchilar<br/>:root, @font-face"]
  B --> C["3. Umumiy<br/>body, sarlavha, havola"]
  C --> D["4. Layout<br/>ustun, header, to'rlar"]
  D --> E["5. Komponentlar<br/>menyu, karta, forma"]
  E --> F["6. Afzalliklar<br/>hover, qorong'i rejim"]
  F --> G["7. Chop etish<br/>@media print"]

Nimaga qarang: har bo'lim oldingisiga tayanadi. Qorong'i rejim faqat o'zgaruvchilarni almashtiradi — oxirida tursa ham hammasiga ta'sir qiladi.

css
/* Portfolio — asosiy uslublar (05-qism yakuni) */

/* ===== 1. Reset ===== */
/* ===== 2. O'zgaruvchilar va shrift ===== */
/* ===== 3. Umumiy ===== */
/* ===== 4. Layout ===== */
/* ===== 5. Komponentlar ===== */
/* ===== 6. Afzalliklar va qurilma ===== */
/* ===== 7. Chop etish ===== */

Har bo'limni eski faylingizdan to'ldiring, manba darsni izohda qoldiring.

6. 3-bosqich: yig'ish — yechim bo'laklarda

Avval o'zingiz yig'ing, keyin solishtiring. Qatorlar telefon uchun 70 belgida bo'lingan — npm run format ularni qayta tekislaydi, ma'nosi o'zgarmaydi.

6.1 Reset

Talab: box-sizing, [hidden] himoyasi, rasm reseti, forma elementlariga sayt shrifti, figure va sup.

Yechim: reset
css
/* ===== 1. Reset ===== */

/* O'lcham border'gacha hisoblansin (box-sizing darsi) */
*,
*::before,
*::after {
  box-sizing: border-box;
}

/* hidden atributi har doim yutsin (display darsi) */
[hidden]:not([hidden="until-found"]) {
  display: none !important;
}

/* Rasm ustundan chiqmasin, nisbati saqlansin (Rasm va media darsi) */
img,
video {
  display: block;
  max-width: 100%;
  height: auto;
}

/* Forma elementlari sayt shriftini olsin (Meros va Mobil tuzoqlar
   darslari) */
button,
input,
textarea {
  font: inherit;
}

figure {
  margin: 0;
}

/* Izoh raqami qatorni kengaytirmasin (Qator balandligi darsi) */
sup {
  line-height: 0;
}

font: inherit Meros va Mobil tuzoqlar darslarida ikki marta yozilgan edi — bittasi qoldi.

6.2 O'zgaruvchilar va shrift

Talab: oklch() palitra (Ranglar 2), hosila ranglar color-mix() bilan (Ranglar 3), qatlamlar shkalasi (z-index), @font-face (Web shriftlar, Variable shriftlar). Forma xatosi rangi ham shu yerga ko'chsin.

Yechim: o'zgaruvchilar va shrift
css
/* ===== 2. O'zgaruvchilar va shrift ===== */

:root {
  color-scheme: light dark;

  /* Palitra (CSS o'zgaruvchilari 1; oklch — Ranglar 2 darsi) */
  --rang-matn: oklch(27.2% 0.019 161);
  --rang-fon: oklch(98.2% 0.004 157.2);
  --rang-asosiy: oklch(48.4% 0.097 158.9);
  --rang-ikkinchi: oklch(49.9% 0.016 162);
  --rang-urgu: oklch(53.7% 0.153 39.8); /* forma xatosi */

  /* Brend rangidan hisoblanadi (Ranglar 3 darsi) */
  --rang-chegara: color-mix(
    in oklch,
    var(--rang-asosiy) 25%,
    var(--rang-fon)
  );
  --rang-fon-och: color-mix(
    in oklch,
    var(--rang-asosiy) 8%,
    var(--rang-fon)
  );

  /* Qatlamlar shkalasi (z-index darsi) */
  --qatlam-yopishqoq: 10;
  --qatlam-menyu: 20;
  --qatlam-ustki: 30;
  --qatlam-otish: 40;
}

/* Sarlavha shrifti — Rubik, SIL OFL 1.1 (Web shriftlar va Variable
   shriftlar darslari) */
@font-face {
  font-family: "Sarlavha";
  src: url("../fonts/sarlavha.woff2") format("woff2");
  font-weight: 300 900;
  font-display: swap;
}
  • --rang-urgu — «Bahor» palitrasidagi nom, portfolio'da forma xatosi uchun: aynan #b4461a, fonda 5.2:1 (hisobladik).
  • color-scheme: light dark — "sahifa ikkala rejimni ham biladi" (Ranglar 3). Usiz qorong'i rejimda maydonlar va skrollbar oppoq qoladi.

6.3 Umumiy

Talab: html, body, sarlavhalar, havolalar, fokus halqasi, belgilash, kod shrifti.

Yechim: umumiy qoidalar
css
/* ===== 3. Umumiy ===== */

html {
  scrollbar-gutter: stable; /* Overflow darsi */
  scrollbar-color: var(--rang-asosiy) var(--rang-fon-och);
  -webkit-text-size-adjust: 100%; /* Mobil tuzoqlar darsi */
  text-size-adjust: 100%;
}

body {
  font-family: system-ui, sans-serif;
  /* 360 da 16px, 1280 da 18px (Fluid tipografiya darsi) */
  font-size: clamp(1rem, 0.9511rem + 0.2174vw, 1.125rem);
  line-height: 1.5; /* Qator balandligi darsi */
  overflow-wrap: break-word; /* Matnni o'rash darsi */
  color: var(--rang-matn);
  /* Tepadan yumshoq yorug'lik (Gradientlar darsi) */
  background:
    linear-gradient(var(--rang-fon-och), var(--rang-fon) 24rem)
    no-repeat var(--rang-fon);
}

/* Sarlavhalar (Mantiqiy pseudo-klasslar, shrift va matn darslari,
   Fluid tipografiya) */
:where(h1, h2, h3) {
  color: var(--rang-asosiy);
}

h1,
h2 {
  font-family: "Sarlavha", system-ui, sans-serif;
  font-synthesis: none;
  line-height: 1.2;
  text-wrap: balance;
}

h1 {
  font-size: clamp(1.75rem, 1.4565rem + 1.3043vw, 2.5rem);
  font-weight: 750;
  letter-spacing: -0.01em;
}

h2 {
  font-size: clamp(1.375rem, 1.3261rem + 0.2174vw, 1.5rem);
  font-weight: 600;
}

p,
li,
dd {
  text-wrap: pretty;
}

/* Sarlavhadan keyingi kirish matni (Asosiy selektorlar va O'lcham
   birliklari darslari) */
h1 + p {
  font-size: 1.125em;
}

/* Havolalar (Kaskad va Matn bezagi darslari) */
a {
  color: var(--rang-asosiy);
  text-decoration-thickness: max(1px, 0.0625em);
  text-underline-offset: 0.15em;
}

a[href^="mailto:"] {
  font-weight: bold;
}

/* Boshqa saytga havola: ko'z uchun belgi, quloq uchun so'z
   (Pseudo-elementlar darsi) */
a[href^="https://"]::after {
  content: " ↗";
  content: " ↗" / ", boshqa sayt";
}

/* Klaviatura fokusi — hamma elementlar uchun (Holat pseudo-klasslari
   darsi) */
:focus-visible {
  outline: 3px solid var(--rang-asosiy);
  outline-offset: 2px;
}

::selection {
  background-color: var(--rang-asosiy);
  color: var(--rang-fon);
}

code {
  font-family:
    ui-monospace, "Cascadia Code", "Source Code Pro", Menlo,
    Consolas, "DejaVu Sans Mono", monospace; /* Shrift asoslari */
}
  • h1 + p endi 1.125em, rem emas: Fluid tipografiya darsidan beri body 18 pikselgacha o'sadi, rem da kirish matni kompyuterda oddiy matnga tenglashib qolardi.
  • ::selection dagi #ffffff (Pseudo-elementlar) var(--rang-fon) bo'ldi — qorong'i rejimda oq matn och yashil fonda o'qilmasdi.
  • O'lcham birliklari darsidagi main p { max-width: 65ch; } o'chdi: ustunning o'zi 70ch.

6.4 Layout

Talab: sticky footer, markaziy ustun, header, footer, bosh sahifa "rasm"i va breakout to'ri — uchta brauzer tuzatishi bilan.

Yechim: layout
css
/* ===== 4. Layout ===== */

/* Sticky footer: body — ustun, main bo'sh joyni oladi (Flex naqshlari
   darsi) */
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
  margin: 0;
}

main {
  flex: 1;
}

/* Markaziy ustun (Matematik funksiyalar, Margin sirlari va Mantiqiy
   xususiyatlar darslari) */
header,
main,
footer {
  inline-size: min(100% - 2rem, 70ch);
  margin-inline: auto;
}

/* Header — Cluster: joy yetsa bir qatorda (Intrinsic layout darsi) */
header {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  column-gap: 1rem;
}

footer {
  margin-block-start: 3rem; /* Margin sirlari darsi */
  border-block-start: 1px solid currentColor; /* Ranglar 1 darsi */
  color: var(--rang-ikkinchi);
}

footer a {
  color: inherit; /* Meros darsi */
}

footer p:last-child {
  font-size: 0.875rem; /* Tuzilma pseudo-klasslari darsi */
}

/* Bosh sahifa: keng ekranda ikki ustunli "rasm" (grid-template-areas
   darsi) */
@media (width >= 40rem) {
  main:has(> img) {
    display: grid;
    grid-template-columns: 3fr 2fr;
    grid-template-areas:
      "sarlavha sarlavha"
      "kirish   rasm"
      "loyiha   bilim";
    column-gap: 2rem;
    align-content: start; /* main flex: 1 bilan cho'zilmasin */
  }

  main:has(> img) > h1 {
    grid-area: sarlavha;
  }

  main:has(> img) > p {
    grid-area: kirish;
  }

  main:has(> img) > img {
    grid-area: rasm;
  }

  main:has(> img) > section:first-of-type {
    grid-area: loyiha;
  }

  main:has(> img) > section:last-of-type {
    grid-area: bilim;
  }
}

/* Loyihalar sahifasi: kartalar matndan kengroq (Layout naqshlari
   darsi) */
main:has(> .loyihalar) {
  display: grid;
  grid-template-columns:
    [toliq-start] minmax(1rem, 1fr)
    [keng-start] minmax(0, 8rem)
    [kontent-start] min(100% - 2rem, 70ch)
    [kontent-end] minmax(0, 8rem)
    [keng-end] minmax(1rem, 1fr) [toliq-end];
  row-gap: 1.5rem;
  align-content: start;
  inline-size: 100%;
}

main:has(> .loyihalar) > * {
  grid-column: kontent;
  margin-block: 0;
}

/* h1 tepadagi odatiy joyini qaytarib olsin
   (Meros darsidagi revert) */
main:has(> .loyihalar) > h1 {
  margin-block-start: revert;
}

main > .loyihalar {
  grid-column: keng;
}
  • Bitta media query qoldi. Intrinsic layout darsida "en bo'yicha birorta ham blok qolmasin" degandik — header va loyihalar uchun bu bajarildi. Bosh sahifa "rasm"ida esa layout butunlay o'zgaradi. Media query'siz yozish — maqsad emas, vosita.
  • revert (Meros darsidan) — h1 brauzer bergan tepa margin'ini qaytarib oladi. Usiz telefonda "Loyihalar" sarlavhasi o'ralgan menyuga yopishib qolardi — Chrome'da ko'rdik.
  • float yo'q. Normal oqim darsidagi float telefonda rasmni 45% ga siqardi, Rasmlar CSS tomoni darsidagi sizes esa butun en uchun hisoblangan edi. Endi telefonda rasm butun enda, keng ekranda — grid ustunida.

sizes ni yangi CSS'ga moslang: body margin'i Flex naqshlari darsidan beri 0, ustun 100vw - 2rem. 40rem dan rasm 2fr ustunda — Chrome'da 640 pikselda 230, 1280 da 259 piksel.

html
<img src="assets/images/ish-joyi.jpg"
     srcset="assets/images/ish-joyi.jpg 480w,
             assets/images/ish-joyi-960.jpg 960w"
     sizes="(width >= 40rem) 260px, (width >= 32rem) 480px,
            calc(100vw - 2rem)"
     alt="Noutbukda ochiq turgan HTML kod"
     width="480" height="320" fetchpriority="high">

Tekshirdik (har safar keshsiz oynada): 360, 768 va 1280 pikselda oddiy ekran ish-joyi.jpg ni, 2x ekran ish-joyi-960.jpg ni yukladi.

6.5 Komponentlar

Talab: skip link, menyular, non yo'li, kartalar, savol-javob, forma, dl, jadval, rasmlar, 404.

Yechim: skip link, menyular, non yo'li
css
/* ===== 5. Komponentlar ===== */

/* --- Skip link va ko'rinmas matn (position, z-index va Mantiqiy
   xususiyatlar darslari) --- */
.korinmas,
.otish:not(:focus) {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.otish:focus {
  position: absolute;
  inset-block-start: 0.5rem;
  inset-inline-start: 0.5rem;
  z-index: var(--qatlam-otish);
  padding: 0.5rem 1rem;
  background-color: var(--rang-asosiy);
  color: var(--rang-fon);
}

/* --- Menyular (Ro'yxatlar stili, Flexbox'ga kirish, Flex'da
   tekislash va Flex naqshlari darslari) --- */
nav ul,
nav ol {
  list-style: none;
  padding-inline-start: 0;
  margin: 0;
}

/* Bosish nishoni: kamida 24 piksel (WCAG 2.5.8, O'lchamlar va Flex
   naqshlari darslari) */
header a {
  display: block;
  padding-block: 0.25rem;
}

nav[aria-label="Asosiy menyu"] ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  margin-inline: -0.5rem; /* matn ustun chetiga tekislansin */
}

nav[aria-label="Asosiy menyu"] a {
  padding-inline: 0.5rem;
  text-decoration: none;
}

/* Joriy sahifa: rang + qalinlik + chiziq (Atribut selektorlari,
   Ranglar 1 va Matn bezagi darslari) */
nav[aria-label="Asosiy menyu"] [aria-current="page"] {
  color: var(--rang-matn);
  font-weight: bold;
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.3em;
}

/* --- Non yo'li: bir qator, oxirgisi sig'masa "…"
   (Auto margin darsi) --- */
nav[aria-label="Non yo'li"] {
  margin-block-start: 1rem;
  font-size: 0.875rem;
}

nav[aria-label="Non yo'li"] ol {
  display: flex;
  gap: 0.5rem;
}

nav[aria-label="Non yo'li"] li {
  display: flex;
  flex: none;
}

nav[aria-label="Non yo'li"] li + li::before {
  content: "/" / "";
  margin-inline-end: 0.5rem;
  color: var(--rang-ikkinchi);
}

nav[aria-label="Non yo'li"] li:last-child {
  flex-shrink: 1;
  min-width: 0;
}

nav[aria-label="Non yo'li"] [aria-current="page"] {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
  • margin-inline: -0.5rem — yangi qator, Margin sirlari darsidagi manfiy margin. Havolalar padding i "Bosh sahifa" ni ism ostidan 8 piksel o'ngga surgan edi. Manfiy margin ro'yxatni ikki tomonga kengaytiradi — matn yana ustun chetida.
  • Non yo'liga margin-block-start: 1rem: u main ning birinchi bolasi, tepa margin'i yo'q edi va telefonda menyuga yopishib qolardi.
Yechim: kartalar va savol-javob
css
/* --- Kartalar: loyiha, savol-javob, fieldset (CSS o'zgaruvchilari 2
   va Chegaralar darslari) --- */
.loyihalar > article,
details[name="savollar"],
fieldset {
  border: 1px solid var(--karta-chegara, var(--rang-chegara));
  border-radius: 0.5rem;
}

/* Loyihalar to'ri — RAM (minmax(), Fluid tipografiya va Intrinsic
   layout darslari) */
.loyihalar {
  display: grid;
  grid-template-columns:
    repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
  gap: clamp(1rem, 0.6087rem + 1.7391vw, 2rem);
}

/* Karta: ichi ota to'rga ulanadi — subgrid (subgrid darsi) */
.loyihalar > article {
  display: grid;
  grid-row: span 4;
  grid-template-rows: subgrid;
  row-gap: 0.5rem;
  padding: 1rem;
  box-shadow:
    0 1px 2px color-mix(in oklch, var(--rang-matn) 8%, transparent),
    0 4px 12px color-mix(in oklch, var(--rang-matn) 10%, transparent);
}

.loyihalar > article:first-child {
  /* Tuzilma pseudo-klasslari va Grid'ga kirish darslari */
  background-color: var(--rang-fon-och);
}

.loyihalar > article > * {
  margin: 0;
}

/* Havolalar — Cluster: sig'sa bir qatorda (Intrinsic layout;
   Container queries o'rniga) */
.loyihalar ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1rem;
  list-style: none;
  padding: 0;
}

/* --- Savol-javob (Atribut selektorlari, Pseudo-elementlar, CSS
   o'zgaruvchilari 2 va Margin sirlari darslari) --- */
details[name="savollar"] {
  padding: 0.25em 0.75em;
}

details[name="savollar"] + details[name="savollar"] {
  margin-block-start: 0.5rem;
}

details[name="savollar"][open] {
  --karta-chegara: var(--rang-asosiy);
  background-color: var(--rang-fon-och);
}

details[name="savollar"] summary::marker {
  color: var(--rang-asosiy);
}

Karta havolalari endi belgisiz ro'yxat va u nav ichida emas — Ro'yxatlar stili darsidagi Safari tuzog'i. loyihalar/index.html dagi ikkala ul ga o'sha darsdagi yechim:

html
<!-- [html-validate-disable-next no-redundant-role -- Safari] -->
<ul role="list">
Yechim: forma, dl, jadval, rasm, 404
css
/* --- Aloqa formasi (display, O'lchamlar, Flex'da tekislash, Grid'da
   joylashtirish va Grid'da tekislash darslari) --- */
form {
  display: grid;
  grid-template-columns:
    repeat(auto-fit, minmax(min(14rem, 100%), 1fr));
  gap: 1rem;
}

form > p {
  display: grid;
  align-content: start;
  gap: 0.25rem;
  margin: 0;
}

form > p:has(textarea),
form > fieldset {
  grid-column: 1 / -1;
}

input:not([type="radio"]),
textarea {
  padding: 0.5em;
}

textarea {
  min-block-size: 8rem;
}

span[id$="-yordam"] {
  font-size: 0.875rem;
  color: var(--rang-ikkinchi);
}

fieldset p {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

input:checked + label {
  font-weight: bold;
}

/* Tugma: brend rangida (O'lchamlar va Chegaralar darslari) */
button {
  min-block-size: 2.75rem;
  padding-inline: 1.5em;
  border: 0;
  border-radius: 0.5rem;
  background-color: var(--rang-asosiy);
  color: var(--rang-fon);
}

form > button {
  justify-self: start;
}

/* Xato faqat mehmon ishlab bo'lgach (Holat pseudo-klasslari va
   Mantiqiy pseudo-klasslar darslari) */
input:user-invalid,
textarea:user-invalid {
  border: 2px solid var(--rang-urgu);
}

label:has(~ :user-invalid),
fieldset:has(:user-invalid) legend {
  color: var(--rang-urgu);
}

/* --- Bilimlar: ikki ustun, torda bitta (Flex algoritmi darsi) --- */
dl {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1rem;
}

dt {
  flex: 0 0 8rem;
  font-weight: bold;
}

dd {
  flex: 1 1 20rem;
  margin: 0;
}

/* --- O'qish rejasi jadvali
   (Ro'yxatlar stili va sticky darslari) --- */
main table {
  border-collapse: collapse;
}

main caption {
  text-align: start;
  font-weight: bold;
  padding-block-end: 0.5rem;
}

main th,
main td {
  padding: 0.5rem 0.75rem;
  border-block-end: 1px solid var(--rang-chegara);
  text-align: start;
}

thead th {
  position: sticky;
  inset-block-start: 0;
  z-index: var(--qatlam-yopishqoq);
  background-color: var(--rang-fon);
}

/* --- Rasmlar (Rasm va media darsi) --- */
main > img {
  border-radius: 0.5rem;
}

figcaption {
  margin-block-start: 0.5rem;
  color: var(--rang-ikkinchi);
  font-size: 0.875rem;
}

/* --- 404: id'si yo'q main — faqat 404.html da (Viewport birliklari
   va Fonlar darslari) --- */
main:not([id]) {
  padding-block-start: 20vh;
  padding-block-start: 20svh;
  background: url("../../favicon.svg") no-repeat right 1rem
    bottom 1rem / 4rem;
}
  • Tugma endi brend rangida — skip link bilan bir xil juftlik, kontrast 5.8:1. Bu yagona yangi "bezak": brauzerning kulrang tugmasi saytga begona ko'rinardi.
  • 404 da main ning id si ham, skip link ham yo'q — takrorlanadigan menyu yo'q, u kerak emas.

6.6 Afzalliklar: hover va qorong'i rejim

Favicon va web manifest darsida "qorong'i rejim ranglarini ham o'zingiz berishingiz kerak bo'ladi" degan edik — endi beramiz. Palitra o'zgaruvchilarda, shuning uchun @media (prefers-color-scheme: dark) ichida beshta o'zgaruvchini qayta aniqlash yetadi. --rang-chegara va --rang-fon-och color-mix() bilan hisoblanadi — o'zi moslashadi.

Yechim: afzalliklar
css
/* ===== 6. Afzalliklar va qurilma ===== */

/* Hover faqat sichqonchali qurilmada (Ranglar 3, Matn bezagi va Mobil
   tuzoqlar darslari) */
@media (hover: hover) {
  a:not([aria-current="page"]):hover {
    background-color: var(--rang-fon-och);
    text-decoration-thickness: 2px;
  }

  header nav a:not([aria-current="page"]):hover {
    color: oklch(from var(--rang-asosiy) calc(l - 0.1) c h);
  }
}

/* Qorong'i rejim — faqat ekranda
   (Foydalanuvchi afzalliklari darsi) */
@media screen and (prefers-color-scheme: dark) {
  :root {
    --rang-matn: oklch(93% 0.012 160);
    --rang-fon: oklch(21% 0.02 160);
    --rang-asosiy: oklch(80% 0.11 158.9);
    --rang-ikkinchi: oklch(76% 0.016 162);
    --rang-urgu: oklch(75% 0.13 39.8);
  }

  .loyihalar > article {
    box-shadow: none; /* qorong'i fonda soya ko'rinmaydi */
  }
}

Uchta qaror:

  • screen and — qog'oz doim oq. Usiz qorong'i rejimdagi odam chop etgan rezyumeda sarlavhalar och yashil chiqardi.
  • Soya o'chadi. Soya --rang-matn dan olingan va qorong'ida karta atrofida och "nur" berardi. Rangdan boshqa narsa — Foydalanuvchi afzalliklari darsidagi qoida bo'yicha @media ishi.
  • Kontrast qorong'i fonda (formula bilan hisobladik): matn 14.4:1, asosiy 9.9:1, ikkinchi 8.3:1, xato 7.6:1, menyu hover'i 6.1:1.

Ikkala palitra ketma-ket — namoyish uchun vaqtinchalik .yorug va .qorongi class'lari bilan (portfolio'ga ko'chmaydi):

html
<style>
  .yorug {
    color-scheme: light;
    --rang-matn: oklch(27.2% 0.019 161);
    --rang-fon: oklch(98.2% 0.004 157.2);
    --rang-asosiy: oklch(48.4% 0.097 158.9);
    --rang-urgu: oklch(53.7% 0.153 39.8);
  }
  .qorongi {
    color-scheme: dark;
    --rang-matn: oklch(93% 0.012 160);
    --rang-fon: oklch(21% 0.02 160);
    --rang-asosiy: oklch(80% 0.11 158.9);
    --rang-urgu: oklch(75% 0.13 39.8);
  }
  .yorug, .qorongi {
    margin-block: 0.5rem;
    padding: 1rem;
    border-radius: 0.5rem;
    font-family: system-ui, sans-serif;
    color: var(--rang-matn);
    background-color: var(--rang-fon);
  }
  h2 { margin-top: 0; color: var(--rang-asosiy); }
  a { color: var(--rang-asosiy); }
  strong { color: var(--rang-urgu); }
  input { display: block; margin-block: 0.5rem; font: inherit; }
  button {
    min-block-size: 2.75rem;
    padding-inline: 1.5em;
    border: 0;
    border-radius: 0.5rem;
    font: inherit;
    background-color: var(--rang-asosiy);
    color: var(--rang-fon);
  }
</style>
<div class="yorug">
  <h2>Loyihalar</h2>
  <p>Matn va <a href="#">havola</a>.</p>
  <p><strong>Email noto'g'ri yozilgan</strong></p>
  <input aria-label="Email" value="ali@example">
  <button>Yuborish</button>
</div>
<div class="qorongi">
  <h2>Loyihalar</h2>
  <p>Matn va <a href="#">havola</a>.</p>
  <p><strong>Email noto'g'ri yozilgan</strong></p>
  <input aria-label="Email" value="ali@example">
  <button>Yuborish</button>
</div>

Nimaga qarang: ikkinchi blokda maydon ham qorong'i — buni color-scheme: dark qildi, maydonga rang bermadik. Tugma ikkala rejimda bitta qoida bilan chizilgan.

6.7 Chop etish

Talab: Foydalanuvchi afzalliklari darsidagi rezyume uslubi, skip link selektori — .otish (o'sha darsdagi va'da).

Yechim: chop etish
css
/* ===== 7. Chop etish (Foydalanuvchi afzalliklari darsi) ===== */
@media print {
  header nav,
  .otish {
    display: none;
  }

  body {
    color: black;
    background: white;
    font-size: 11pt;
  }

  a {
    color: inherit;
  }

  a[href^="http"]::after {
    content: " (" attr(href) ")";
  }

  section,
  table {
    break-inside: avoid;
  }

  h2 {
    break-after: avoid;
  }
}

@page {
  size: A4;
  margin: 15mm;
}

body > a:first-child endi .otish: selektor o'ringa emas, ma'noga tayanadi.

Tekshirib ko'ring: Qorong'i palitra faylning eng oxirida, :root esa boshida. Nega qorong'i ranglar komponentlar qoidalaridan keyin yozilgan bo'lsa ham hamma joyda ishlaydi?

Javob

Komponentlar rangni saqlamaydi — var(--rang-asosiy) ni o'qiydi, qiymat esa hisoblash bosqichida olinadi (CSS o'zgaruvchilari 2). Tartib faqat ikki :root qoidasi orasida muhim: pastdagisi yutadi. Qorong'i blok yorug' :root dan oldin tursa, yorug' qiymatlar uni bosib ketardi.

7. Natija: loyihalar sahifasi

Eng ko'p tushunchani loyihalar sahifasi yig'adi. Quyida uning haqiqiy qoidalari (sarlavha shrifti natijada Google Fonts'dan):

html
<link rel="stylesheet"
  href="https://fonts.googleapis.com/css2?family=Rubik:wght@300..900">
<style>
  :root {
    --rang-matn: oklch(27.2% 0.019 161);
    --rang-fon: oklch(98.2% 0.004 157.2);
    --rang-asosiy: oklch(48.4% 0.097 158.9);
    --rang-ikkinchi: oklch(49.9% 0.016 162);
    --rang-chegara: color-mix(in oklch,
      var(--rang-asosiy) 25%, var(--rang-fon));
    --rang-fon-och: color-mix(in oklch,
      var(--rang-asosiy) 8%, var(--rang-fon));
  }
  *, *::before, *::after { box-sizing: border-box; }
  body {
    margin: 0;
    font-family: system-ui, sans-serif;
    font-size: clamp(1rem, 0.9511rem + 0.2174vw, 1.125rem);
    line-height: 1.5;
    color: var(--rang-matn);
    background:
      linear-gradient(var(--rang-fon-och), var(--rang-fon) 24rem)
      no-repeat var(--rang-fon);
  }
  h1, h2 {
    font-family: Rubik, system-ui, sans-serif;
    line-height: 1.2;
    color: var(--rang-asosiy);
  }
  h1 { font-size: clamp(1.75rem, 1.4565rem + 1.3043vw, 2.5rem); }
  h2 { font-size: clamp(1.375rem, 1.3261rem + 0.2174vw, 1.5rem); }
  a {
    color: var(--rang-asosiy);
    text-underline-offset: 0.15em;
  }
  header, main, footer {
    inline-size: min(100% - 2rem, 70ch);
    margin-inline: auto;
  }
  header {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    column-gap: 1rem;
  }
  header a { display: block; padding-block: 0.25rem; }
  nav ul { list-style: none; margin: 0; padding: 0; }
  nav[aria-label="Asosiy menyu"] ul {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    margin-inline: -0.5rem;
  }
  nav[aria-label="Asosiy menyu"] a {
    padding-inline: 0.5rem;
    text-decoration: none;
  }
  nav[aria-label="Asosiy menyu"] [aria-current="page"] {
    color: var(--rang-matn);
    font-weight: bold;
    text-decoration: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: 0.3em;
  }
  main:has(> .loyihalar) {
    display: grid;
    grid-template-columns:
      [toliq-start] minmax(1rem, 1fr)
      [keng-start] minmax(0, 8rem)
      [kontent-start] min(100% - 2rem, 70ch)
      [kontent-end] minmax(0, 8rem)
      [keng-end] minmax(1rem, 1fr) [toliq-end];
    row-gap: 1.5rem;
    align-content: start;
    inline-size: 100%;
  }
  main:has(> .loyihalar) > * {
    grid-column: kontent;
    margin-block: 0;
  }
  main:has(> .loyihalar) > h1 { margin-block-start: revert; }
  main > .loyihalar { grid-column: keng; }
  .loyihalar {
    display: grid;
    grid-template-columns:
      repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
    gap: clamp(1rem, 0.6087rem + 1.7391vw, 2rem);
  }
  .loyihalar > article {
    display: grid;
    grid-row: span 4;
    grid-template-rows: subgrid;
    row-gap: 0.5rem;
    padding: 1rem;
    border: 1px solid var(--rang-chegara);
    border-radius: 0.5rem;
  }
  .loyihalar > article:first-child {
    background-color: var(--rang-fon-och);
  }
  .loyihalar > article > * { margin: 0; }
  .loyihalar ul {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1rem;
    list-style: none;
    padding: 0;
  }
  footer {
    margin-block-start: 3rem;
    border-block-start: 1px solid currentColor;
    color: var(--rang-ikkinchi);
  }
</style>
<header>
  <p><a href="#">Aziz Karimov</a></p>
  <nav aria-label="Asosiy menyu">
    <ul>
      <li><a href="#">Bosh sahifa</a></li>
      <li><a href="#">Men haqimda</a></li>
      <li><a href="#" aria-current="page">Loyihalar</a></li>
      <li><a href="#">Aloqa</a></li>
    </ul>
  </nav>
</header>
<main id="asosiy">
  <h1>Loyihalar</h1>
  <p>HTML va CSS qismida qilgan ishlarim.</p>
  <div class="loyihalar">
    <article>
      <h2>Choyxona «Bahor» sayti</h2>
      <p><time datetime="2026-09">2026-yil sentabr</time></p>
      <p>To'rt sahifali sayt: menyu jadvali, stol band qilish
      formasi va 404 sahifasi. Validatordan xatosiz o'tgan.</p>
      <ul role="list">
        <li><a href="#">Loyiha haqida batafsil</a></li>
        <li><a href="#">Saytni ochish</a></li>
      </ul>
    </article>
    <article>
      <h2>Semantik blog maqolasi</h2>
      <p><time datetime="2026-08">2026-yil avgust</time></p>
      <p>"Osh sirlari" maqolasi: landmarklar va izohli rasmlar.</p>
      <ul role="list">
        <li><a href="#">Saytni ochish</a></li>
      </ul>
    </article>
  </div>
</main>
<footer>
  <p>© 2026 Aziz Karimov.</p>
</footer>

Nimaga qarang:

  • 360: menyu ism ostida, ikki qatorda; kartalar ustma-ust.
  • 1280: ism va menyu bir chiziqda; kartalar yonma-yon, matn ustunidan kengroq, sanalar bir chiziqda — subgrid.

Natijada faqat sticky footer'ning min-height: 100dvh i yo'q: dvh bo'lsa, oyna 400 pikselga qotib, sahifa kesilardi.

8. 4-bosqich: tekshirish

Sonlar — namunaviy yechimda Chrome'da (Windows, Segoe UI) o'lchaganimiz.

8.1 Ekran enlari va gorizontal skroll

DevTools qurilma rejimida har sahifani 320, 360, 768 va 1280 pikselda oching. Console'ga yozing:

js
document.documentElement.scrollWidth -
  document.documentElement.clientWidth;

Musbat son — gorizontal skroll bor, aybdorni Responsive dizayn darsidagi usul bilan toping. Bu JavaScript'ni hozir tushunish shart emas — 09-qismda o'rganasiz. Namunaviy yechimda telefon enlarida 0, kompyuterda -15 chiqdi — scrollbar-gutter yo'lagi (Overflow). Musbat son yo'q.

Namunaviy yechimda:

En Header Loyihalar Bosh sahifa rasmi
360 Ism tepada, menyu 2 qator 1 ustun, 328 Butun enda, 328
768 Bir chiziqda 2 ustun, 349 dan O'ng ustunda, 242
1280 Bir chiziqda 2 ustun, 452 dan O'ng ustunda, 259

Header taxminan 496 pikseldan bir chiziqqa o'tadi — breakpoint'siz, Cluster enni o'zi topdi.

8.2 Klaviatura va fokus

Bosh sahifada Tab bosing:

  1. Chap yuqorida skip link chiqadi (360 da 196×40 piksel); fokussiz u 1×1 va ko'rinmaydi.
  2. Enter, keyin Tab — fokus "Choyxona «Bahor» sayti" havolasida: menyu o'tkazib yuborildi.
  3. Har qadamda 3 piksellik halqa ko'rinsin — havola, tugma, maydon, summary da.

8.3 Bosish nishonlari

DevTools'da o'lchadik:

  • Menyu va ism havolalari 32 piksel baland (1280 da 35), eng tori "Aloqa" — 60 piksel. Tugma — 44.
  • Matn ichidagi havolalar 21–22 piksel — WCAG 2.5.8 ularni istisno qiladi (O'lchamlar).
  • Non yo'li havolalari 21 piksel, radio tugmalar 13×13, lekin 24 piksellik doirasiga boshqa nishon tegmaydi — oraliq istisnosi.

8.4 Qorong'i rejim va chop etish

Styles'dagi mo'yqalam tugmasi → prefers-color-scheme: dark (Foydalanuvchi afzalliklari): hamma sahifada o'qilmaydigan matn yoki oq "orol" qolmasin. Keyin Ctrl + P → PDF. "Men haqimda" namunamizda ikki varaq chiqdi: menyu va skip link yo'q, jadval butun, sarlavhalar yorug' palitrada — tizim qorong'i bo'lsa ham.

8.5 html-validate va Prettier

bash
npm run format
npm run check

Diqqat: html-validate 11 da recommended to'plamidagi require-sri qoidasi har link rel="stylesheet" da xato beradi (tekshirdik): SRI "integrity" attribute is required on <link> element — "<link> elementida SRI integrity atributi majburiy". SRI boshqa domendagi fayl uchun kerak (HTML xavfsizligi), o'z asosiy.css ingizga emas. .htmlvalidate.json ning rules qismiga qo'shing:

json
{
  "rules": {
    "require-sri": ["error", { "target": "crossorigin" }]
  }
}

target: "crossorigin" — "faqat boshqa domendan ulangan fayllarni tekshir". Shundan keyin namunaviy yechim 0 xato bilan o'tdi.

8.6 Lighthouse: 95 dan 100 ga

Yakuniy loyiha darsida CSS'siz sahifa Accessibility'da 95 olgan edi. Yagona qizil qator — "Touch targets do not have sufficient size or spacing" ("bosish nishonlari o'lchami yoki oralig'i yetarli emas"). Tuzatish Flex naqshlari darsida qilingan. Ikki marta o'lchadik — Lighthouse 12.8, Mobile, lokal server:

Sahifa Performance Accessibility BP / SEO
Bosh sahifa 99–100 100 100 / 100
Men haqimda 99–100 100 100 / 100
Loyihalar 99 100 100 / 100
«Bahor» loyihasi 99–100 100 100 / 100
Aloqa 98–99 100 100 / 100
404 99–100 100 100 / 50

Nazorat uchun asosiy.css ni vaqtincha uzib ko'rdik: Accessibility yana 95, yagona xato — "Touch targets". Demak 95 → 100 aynan CSS'ning ishi.

404 dagi SEO 50 — xato emas: unda ataylab noindex bor (Qidiruv tizimlari uchun meta teglar). Performance internetda biroz farq qiladi — deploy'dan keyin PageSpeed Insights'da qayta o'lchang.

8.7 Eski brauzerlar

Yangi imkoniyatlar "bo'lmasa — oddiyroq" tamoyilida yozilgan (Brauzer mosligi):

Imkoniyat Holati Eski brauzerda
text-wrap: balance, nisbiy rang, scrollbar-gutter, @page Yangi Baseline (2024) Oddiy o'rash; hover rangi, sakramaslik va varaq sozlamasi yo'q
scrollbar-color Yangi Baseline (2025-12) Tizim skrollbari
text-wrap: pretty, ::selection, ::marker, ui-monospace, break-after: avoid Baseline emas Oddiy o'rash va belgi, keyingi shrift, sarlavha ajralib qolishi mumkin
text-size-adjust Baseline emas -webkit- zaxirasi bilan yozilgan

Birortasi yo'q bo'lsa ham sahifa buzilmaydi, o'qiladi va ishlaydi.

9. 5-bosqich: qayta deploy

Git'ni hali bilmaysiz — u 07-qismda. Shuning uchun Birinchi deploy darsidagi yo'l bilan yangilaymiz.

Netlify Drop'da: loyiha sahifasi → Deploys → pastdagi ramkaga sayt/ papkasining o'zini tashlang. Manzil o'zgarmaydi.

GitHub Pages'da (login.github.io): repo → Add file → Upload files → sayt/ ning ichidagi hamma narsani tashlang. Yangi papkalar tuzilmasi bilan yuklanadi, bir xil nomli fayllar ustidan yoziladi. Izoh CSS: 05-qism yakuni → Commit changes → bir necha daqiqa kuting.

Brauzer eski asosiy.css ni keshda ushlab turishi mumkin (HTTP kesh). Sayt eskicha ko'rinsa — Ctrl + F5.

Deploy'dan keyingi tekshiruv:

  • DevTools → Network: asosiy.css va sarlavha.woff2 — 200, shrift bir marta yuklangan.
  • Mavjud bo'lmagan manzil (/yoq-sahifa) — bezalgan 404, o'ng pastda favicon.
  • Telefonda: maydon bosilganda sahifa kattalashmaydi, yotiq holatda skroll yo'q, qorong'i rejimda sayt ham qorong'i (Mobil tuzoqlar).
  • PageSpeed Insights (pagespeed.web.dev) — Mobile natijasini yozib qo'ying.

10. Baholash ro'yxati

Majburiy shartlar: sayt internetda yangi CSS bilan ochiladi; npm run check — 0 xato; HTML'da style atributi va tegi yo'q.

Ballar (jami 100, o'tish — 80):

Bo'lim Nima tekshiriladi Ball
Tuzilma 7 izohli bo'lim, takror qoida yo'q, !important faqat [hidden] da 10
Palitra Ctrl + F → #: rang faqat :root da (favicon'dan tashqari) 10
Responsive 320, 360, 768, 1280 da gorizontal skroll yo'q (Console tekshiruvi) 10
Layout Header Cluster, loyihalar RAM, en bo'yicha bitta @media 10
Tipografiya Fluid shrift, sarlavha.woff2 bir marta, font-display: swap 5
Skip link Faqat fokusda ko'rinadi, Enter dan keyin fokus main da 10
Fokus va bosish Har elementda halqa; menyu havolalari ≥ 24×24 (o'lchangan) 10
Qorong'i rejim Emulyatsiyada hamma matn o'qiladi, maydonlar qorong'i 10
Chop etish Menyu va skip link yo'q, tashqi havola manzili chiqadi 5
Audit Lighthouse: Accessibility 100, Perf ≥ 90, BP ≥ 95, SEO 100 10
Deploy Deploy'dan keyingi ro'yxatning hamma bandi bajarildi 10

Har bo'limda: hammasi bajarilgan — to'liq ball, bitta kamchilik — yarmi, ko'p — 0. 90–100 — a'lo; 80–89 — kamchiliklarni 06-qism davomida tuzating; 80 dan kam — ball yo'qolgan bo'lim darslariga qayting.

11. Ko'p uchraydigan xatolar

11.1 Qadamlarni ustma-ust nusxalash

header uch joyda, .loyihalar to'rt joyda. Tuzatish: har selektor — bitta joyda.

11.2 Qorong'i rejimda "unutilgan" rang

Qolib ketgan color: #1f2a24 qorong'i fonda ko'rinmaydi. Tuzatish: Ctrl + F → # — hammasi :root da bo'lsin.

11.3 sizes CSS bilan birga o'zgarmagan

Layout o'zgardi, sizes esa eskicha — telefon keraksiz katta faylni yuklaydi. Tuzatish: rasm eni o'zgarsa, sizes ni qayta hisoblang.

12. Mashqlar

1-mashq (oson): radio tugmalar barmoqqa mos

Bosish nishonlarini o'lchaganda radio tugmalar 13×13 piksel chiqdi. Ular Lighthouse'dan o'tadi, lekin telefonda mo'ljalga olish qiyin. Ularni 24×24 qiling; yorliq bilan oraliqni faqat gap bersin.

Ishora: O'lchamlar darsidagi inline-size va block-size; brauzer radio'ga o'z margin'ini beradi.

Yechim

"Aloqa formasi" qismiga:

css
input[type="radio"] {
  inline-size: 1.5rem;
  block-size: 1.5rem;
  margin: 0;
}

Chrome'da tekshirdik: ikkala radio 24×24 piksel, nuqtasi ham kattalashdi. margin: 0 brauzer margin'ini olib tashlaydi — oraliqni Flex'da tekislash darsidagi gap beradi.

2-mashq (o'rta): o'z brend rangingiz

--rang-asosiy ni ko'kka almashtiring: yorug' rejimda oklch(48% 0.12 250), qorong'ida oklch(80% 0.1 250).

  1. Qaysi ranglar o'zi o'zgardi?
  2. Ikkala rejimda kontrastni DevTools rang tanlagichida tekshiring.
Yechim
  1. Faqat --rang-asosiy ning ikki qatori o'zgaradi. Sarlavha, havola, fokus halqasi, tugma, skip link va skrollbar o'zi ko'k bo'ladi; --rang-chegara va --rang-fon-och ham — ular color-mix() dan (Ranglar 3). Matn va fon deyarli kulrang, ularning tusini (161) xohlasangiz 250 ga yaqinlashtiring.
  2. Formula bilan hisobladik: yorug' fonda oklch(48% 0.12 250) 6.2:1, qorong'i fonda oklch(80% 0.1 250) 9.5:1. Ikkalasi ham 4.5:1 dan yuqori.

3-mashq (qiyin): uchinchi loyiha kartasi

Loyihalar sahifasiga uchinchi karta qo'shing — "Shaxsiy portfolio sayti": sana, tavsif va "Saytni ochish" havolasi. 360, 768 va 1280 pikselda nechta ustun chiqadi, kartalar ichi bir chiziqdami?

Ishora: kartadagi elementlar soni subgrid'dagi span ga mos bo'lsin (subgrid). Kartalar to'ri kengligini Layout naqshlari darsidagi breakout beradi.

Yechim
html
<article>
  <h2>Shaxsiy portfolio sayti</h2>
  <p><time datetime="2026-10">2026-yil oktabr</time></p>
  <p>Shu sayt: HTML, keyin CSS — Flexbox, Grid, responsive,
  qorong'i rejim.</p>
  <!-- [html-validate-disable-next no-redundant-role -- Safari] -->
  <ul role="list">
    <li>
      <a href="https://example.com/">Saytni ochish<span
        class="korinmas"> (Shaxsiy portfolio sayti)</span></a>
    </li>
  </ul>
</article>

Kartada to'rtta bola: h2, ikkita p, ul — span 4 o'zgarmaydi. Chrome'da o'lchadik:

  • 360: bitta ustun, kartalar 328 pikseldan.
  • 768: ikki ustun, 349 pikseldan; uchinchi karta ikkinchi qatorda.
  • 1280: uch ustun, 290 pikseldan — to'r 935 piksel, 3 × 256 + 2 × 32 = 832 sig'adi. Sarlavha, sana, tavsif va havolalar uchala kartada bir chiziqda.

Breakout'siz, 70ch lik ustunda (679 piksel) uchinchi karta sig'masdi.

13. Portfolio'ga qo'shing

  • Uchinchi karta — 3-mashqdagi "Shaxsiy portfolio sayti".
  • «Bahor» loyiha sahifasi — "Nima qildim" ga CSS bandini qo'shing, "Natija" dagi Lighthouse sonlarini yangilang.
  • Rezyume — "Ko'nikmalar" ga: "CSS: Flexbox, Grid, responsive, accessibility (Lighthouse 100)" — sayt havolasi bilan.

14. 05-qism yakuni: endi nimalarni qila olasiz

Tabriklaymiz — CSS asoslari qismi tugadi! Endi:

  • Selektorlar va kaskad: class'siz ham aniq tanlaysiz, qaysi qoida nega yutganini tushuntirasiz.
  • Qiymatlar va bezak: birliklar, clamp(), o'zgaruvchilar, oklch(), box model, fonlar, shriftlar.
  • Joylashuv: oqim, position, Flexbox va Grid — subgrid gacha.
  • Responsive: mobile-first, media va container queries, fluid tipografiya, afzalliklar.

Eng muhimi — ish usuli: avval ma'no, keyin ko'rinish; har qadamdan keyin brauzerda o'lchash.

Oldinda nima bor

06-qismda CSS jonlanadi: transformlar, animatsiyalar, zamonaviy CSS va dizayn tizimi. Bitta asosiy.css fayllarga va qatlamlarga bo'linadi, --rang-* o'zgaruvchilari dizayn tokenlariga aylanadi. Qism oxirida Figma dizayni asosida landing quriladi (Yakuniy loyiha: landing). 07-qismda — Git: faylma-fayl yuklash o'rniga bitta buyruq.

15. Real ishda

  • Kod ko'rigi (code review). Jamoada har o'zgarishni boshqa dasturchi o'qiydi va birinchi so'raydi: "bu qoida bor narsaga zid emasmi?" Ziddiyatlarni topish — aynan shu ko'nikma.
  • CSS auditi. Katta saytlarda CSS vaqti-vaqti bilan bugungidek tozalanadi; DevTools'dagi Coverage paneli ishlatilmagan qatorlarni ko'rsatadi.
  • Intervyuda: "Qorong'i rejimni qanday qildingiz?", "Media query'siz responsive qanday?", "Skip link nimaga kerak?" — o'z kodingiz bilan javob berasiz.

Xulosa

  • asosiy.css — yetti bo'lim: reset → o'zgaruvchilar → umumiy → layout → komponentlar → afzalliklar → chop etish.
  • Qadamlar ustma-ust qo'shilmaydi: har selektor bitta joyda, ziddiyat DevTools'da o'lchab hal qilinadi.
  • Palitra o'zgaruvchilarda bo'lgani uchun qorong'i rejim — beshta qator va color-scheme.
  • Tekshiruv: 4 ta en, klaviatura, qorong'i rejim, chop etish, html-validate va Lighthouse — Accessibility 95 → 100.

Keyingi dars: 2D transformlar: siljitish, burish, kattalashtirish — 06-qism boshlanadi: elementlarni joyidan qo'zg'atmasdan siljitish, burish va kattalashtirishni o'rganamiz.

Manbalar

  • MDN: "prefers-color-scheme", "color-scheme", "Subgrid", "CSS container queries" — developer.mozilla.org
  • W3C: "Understanding SC 2.5.8: Target Size (Minimum)" — w3.org/WAI/WCAG22/Understanding
  • html-validate: "require-sri" qoidasi — html-validate.org/rules/require-sri.html
  • web-features (Baseline ma'lumotlari) — github.com/web-platform-dx/web-features
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Yakuniy loyiha: portfolio'ni CSS bilan bezash va responsive qilish — IlmHamroh