IlmHamroh
JavaScript Full-stack/5-qism. CSS asoslari va layout59/63-dars22 daqiqa
Mundarija (41)

CSS container queries: komponent o'z konteyneriga moslashadi

Qisqacha: Media query ekran eniga qaraydi, container query esa komponent turgan quti eniga. Otaga container-type: inline-size yozasiz — u "konteyner" bo'ladi. @container (width >= 25rem) { ... } ichidagi qoidalar faqat shu quti yetarlicha keng bo'lganda ishlaydi. Natijada bitta taom kartasi keng ustunda yotiq, tor yon panelda tik — CSS bitta. Container query 2023-yildan hamma asosiy brauzerda bor, o'zgaruvchiga qaraydigan style query esa faqat 2026-yil mayidan — u yangi.

Bu darsda

  • Nega media query komponent uchun yetmasligini misolda ko'rsatasiz.
  • container-type, container-name va @container shartini yozasiz.
  • cqi va boshqa konteyner birliklari bilan o'lchamni quti eniga bog'laysiz.
  • Style va scroll-state so'rovlari nima ekanini va ularning brauzer holatini bilasiz.
  • Qachon media query, qachon container query kerakligini qoida bilan tanlaysiz.

Oldin bilishingiz kerak: Media queries, Mobile-first, Intrinsic layout, Grid'ga kirish, CSS o'zgaruvchilari 2.

1. Nega bu kerak?

Intrinsic layout darsida sahifani media query'siz moslashadigan qilgan edik. Lekin komponentning ichki tuzilishi-chi? «Bahor» taom kartasi ikki joyda turadi:

  • Menyu sahifasida — keng asosiy ustunda. Bu yerda surat chapda, matn o'ngda bo'lsa, joy tejaladi.
  • "Bugungi taklif" yon panelida — tor ustunda. Bu yerda surat tepada, matn pastda bo'lishi kerak.

Media queries bilan yozib ko'ramiz. Kompyuter ekranida kartalar yotiq bo'lsin:

html
<style>
  body {
    margin: 0;
    padding: 1rem;
    display: grid;
    gap: 1rem;
    font-family: system-ui, sans-serif;
  }
  @media (width >= 40rem) {
    body {
      grid-template-columns: 1fr 15rem;
    }
  }
  img {
    display: block;
    max-width: 100%;
    height: auto;
  }
  .taom-karta {
    border: 2px solid #2f6b3a;
    padding: 0.75rem;
  }
  .taom-karta h3 {
    margin: 0;
  }
  @media (width >= 40rem) {
    .taom-karta {
      display: grid;
      grid-template-columns: 9rem 1fr;
      column-gap: 1rem;
    }
    .taom-karta img {
      grid-row: span 3;
    }
  }
</style>
<main>
  <article class="taom-karta">
    <img alt="Bir tarelka Toshkent oshi" width="300" height="200"
      src="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'
      viewBox='0 0 300 200'><rect width='300' height='200'
      fill='%23fde2c4'/><circle cx='150' cy='100' r='70'
      fill='%232f6b3a'/></svg>">
    <h3>Osh</h3>
    <p>Rustam akaning to'y oshi, bedana tuxumi bilan.</p>
    <p>35 000 so'm</p>
  </article>
</main>
<aside>
  <article class="taom-karta">
    <img alt="Lag'mon kosada" width="300" height="200"
      src="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'
      viewBox='0 0 300 200'><rect width='300' height='200'
      fill='%23fde2c4'/><circle cx='150' cy='100' r='70'
      fill='%23b4461a'/></svg>">
    <h3>Bugungi taklif: lag'mon</h3>
    <p>Qo'lda cho'zilgan xamir, achchiq sous.</p>
    <p>28 000 so'm</p>
  </article>
</aside>

Nimaga qarang: "Kompyuter" tugmasini bosing. Menyudagi osh kartasi chiroyli: surat chapda, matn o'ngda. Yon paneldagi lag'mon kartasi esa siqilib qoldi — 15rem ustunga yana 9rem surat tiqildi, matnga deyarli joy qolmadi. Media query faqat "ekran kengmi?" deb so'raydi. Karta qayerda turgani uni qiziqtirmaydi.

Idishga quyilgan suvni eslang. Suv xonaning kattaligiga qaramaydi — qaysi idishga quyilsa, o'sha shaklni oladi. Komponent ham ekranga emas, o'zi turgan qutiga qarasin. Buning vositasi — container query (konteyner so'rovi): ota qutining o'lchami yoki xususiyatiga qarab qoida qo'llaydigan @container qoidasi.

2. Birinchi container query

2.1 Ikki qadam: konteyner va so'rov

1-qadam. Ota elementga aytamiz: "sen — konteynersan, bolalaring eningni so'rashi mumkin":

css
main,
aside {
  container-type: inline-size;
}

2-qadam. Kartaning yotiq ko'rinishini @media o'rniga @container ichiga yozamiz:

css
@container (width >= 25rem) {
  .taom-karta {
    display: grid;
    grid-template-columns: 9rem 1fr;
    column-gap: 1rem;
  }
  .taom-karta img {
    grid-row: span 3;
  }
}

O'qilishi: "kartaning eng yaqin konteyneri kamida 25rem keng bo'lsa — kartani ikki ustunli qil". Shart xuddi media query'dagidek yoziladi: width >= 25rem, and, or, not — Media queries darsidagi range sintaksisi. Eski (min-width: 25rem) shakli ham ishlaydi.

2.2 Natija: bitta CSS, ikki xil karta

html
<style>
  body {
    margin: 0;
    padding: 1rem;
    display: grid;
    gap: 1rem;
    font-family: system-ui, sans-serif;
  }
  @media (width >= 40rem) {
    body {
      grid-template-columns: 1fr 15rem;
    }
  }
  main,
  aside {
    container-type: inline-size;
  }
  img {
    display: block;
    max-width: 100%;
    height: auto;
  }
  .taom-karta {
    border: 2px solid #2f6b3a;
    padding: 0.75rem;
  }
  .taom-karta h3 {
    margin: 0;
  }
  @container (width >= 25rem) {
    .taom-karta {
      display: grid;
      grid-template-columns: 9rem 1fr;
      column-gap: 1rem;
    }
    .taom-karta img {
      grid-row: span 3;
    }
  }
</style>
<main>
  <article class="taom-karta">
    <img alt="Bir tarelka Toshkent oshi" width="300" height="200"
      src="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'
      viewBox='0 0 300 200'><rect width='300' height='200'
      fill='%23fde2c4'/><circle cx='150' cy='100' r='70'
      fill='%232f6b3a'/></svg>">
    <h3>Osh</h3>
    <p>Rustam akaning to'y oshi, bedana tuxumi bilan.</p>
    <p>35 000 so'm</p>
  </article>
</main>
<aside>
  <article class="taom-karta">
    <img alt="Lag'mon kosada" width="300" height="200"
      src="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'
      viewBox='0 0 300 200'><rect width='300' height='200'
      fill='%23fde2c4'/><circle cx='150' cy='100' r='70'
      fill='%23b4461a'/></svg>">
    <h3>Bugungi taklif: lag'mon</h3>
    <p>Qo'lda cho'zilgan xamir, achchiq sous.</p>
    <p>28 000 so'm</p>
  </article>
</aside>

Nimaga qarang: uchta tugmani navbat bilan bosing.

  • Telefon (360). Ikkala karta tik: surat tepada. Ustun bitta, ikkala konteyner ham ~328 piksel — 25rem (400 piksel) dan tor.
  • Planshet (768). Endi ikki ustun. Osh kartasi yotiq, lag'mon kartasi tik. Ular yonma-yon, bir xil CSS bilan — lekin har biri o'z qutisiga qaraydi.
  • Kompyuter (1280). Osh kartasi yotiq. Yon panel 15rem — lag'mon hali ham tik.

Chrome'da o'lchadik: 768 piksellik ekranda main 480 piksel keng (shartdan o'tadi), aside esa 240 piksel (o'tmaydi). Ustunlar sonini hali ham @media hal qilyapti, karta ichini esa @container. Ikkalasi birga ishlaydi.

2.3 Qo'lda torting: konteyner eni o'zgarsa

Ekran bir xil, faqat quti eni o'zgarsa-chi? Quyidagi natijada ikkita konteyner bor: tepadagisi — to'liq enda, pastdagisi — 18rem (288 piksel). Kompyuterda qutining o'ng pastki burchagidagi belgini sichqoncha bilan torting. Bu belgini resize: horizontal beradi: foydalanuvchi qutini o'zi kengaytira oladi (u faqat overflow bilan ishlaydi, Overflow). Baseline ma'lumotiga ko'ra resize — Baseline emas: telefon brauzerlarida (Safari iOS, Firefox Android) yo'q. Telefonda ekranlar tugmalaridan foydalaning.

html
<style>
  body {
    font-family: system-ui, sans-serif;
  }
  section {
    container-type: inline-size;
    resize: horizontal;
    overflow: hidden;
    border: 1px dashed #5b6660;
    padding: 0.5rem;
    margin-bottom: 1rem;
  }
  section + section {
    width: 18rem;
  }
  .taom-karta {
    border: 2px solid #2f6b3a;
    padding: 0.5rem;
  }
  .taom-karta h3,
  .taom-karta p {
    margin: 0;
  }
  @container (width >= 25rem) {
    .taom-karta {
      display: flex;
      justify-content: space-between;
      align-items: baseline;
    }
  }
</style>
<section>
  <article class="taom-karta">
    <h3>Manti</h3>
    <p>30 000 so'm</p>
  </article>
</section>
<section>
  <article class="taom-karta">
    <h3>Manti</h3>
    <p>30 000 so'm</p>
  </article>
</section>

Nimaga qarang: planshet va kompyuter enida tepadagi kartada nom va narx bir qatorda, uchlarda. Pastdagisida — ustma-ust. Pastki qutini sichqoncha bilan kengaytiring: 400 pikseldan o'tgan zahoti karta ham bir qatorga o'tadi. Ekran o'zgarmadi — faqat quti.

Tekshirib ko'ring: Ekran 1280 piksel. Karta 20rem enli yon panelda turibdi, yon panel — konteyner. @container (width >= 25rem) qoidasi ishlaydimi? @media (width >= 25rem) bo'lsa-chi?

Javob

@container — yo'q: kartaning konteyneri 20rem, shart esa 25rem. @media — ha: u ekranni so'raydi, ekran esa 1280 piksel (80rem). «Nega bu kerak?» bo'limidagi siqilgan karta aynan shu farqdan chiqdi.

3. container-type: qaysi qiymat va nega

3.1 Uch qiymat

Qiymat Nimani so'rash mumkin Qachon
inline-size Faqat en Deyarli doim
size En va bo'y Bo'yi aniq berilgan quti
normal O'lchamni emas (boshlang'ich qiymat) —

inline-size — Mantiqiy xususiyatlar darsidagi "qator yo'nalishi bo'yicha o'lcham". O'zbekcha kabi chapdan o'ngga yoziladigan matnda bu — en.

3.2 Nega "faqat en"? Aylanma bog'liqlik

Brauzer oldiga muammo qo'yamiz. Qoida: "konteyner keng bo'lsa — kartani kichraytir". Konteyner eni esa kartadan kelsa-chi?

flowchart TD
  A["Konteyner keng"] --> B["Shart bajarildi:<br/>karta kichraydi"]
  B --> C["Konteyner torayadi"]
  C --> D["Shart bajarilmadi:<br/>karta kattalashadi"]
  D --> A

Nimaga qarang: strelkalar aylana yasadi — brauzer hech qachon to'xtay olmaydi.

Brauzer bu aylanani oddiy qoida bilan uzadi: container-type: inline-size berilgan element o'z enini bolalaridan olmaydi. En faqat otadan — ustundan, grid yo'lagidan — keladi. Bu containment (o'z ichiga yopish) deyiladi: konteyner ichidagi narsa uning eniga ta'sir qilmaydi.

Bu qoidaning tuzog'i bor. Eni mazmundan keladigan elementni konteyner qilsangiz, uning eni nolga tushadi. Chrome'da tekshirdik:

html
<style>
  body {
    font-family: system-ui, sans-serif;
  }
  p {
    width: fit-content;
    border: 2px solid #b4461a;
    container-type: inline-size;
    margin-bottom: 3rem;
  }
</style>
<p>Osh — 35 000 so'm</p>
<p style="container-type: normal">Osh — 35 000 so'm</p>

Nimaga qarang: birinchi paragrafning qizg'ish ramkasi nol enli chiziqqa aylandi, matn so'zma-so'z tashqariga tushdi. Ikkinchisi (normal) — odatiy. inline-block, width: fit-content va o'smaydigan flex element — uchalasining eni mazmundan keladi. Chrome'da uchalasida ham en 0 chiqdi. Konteyner qiling — eni tashqaridan keladigan blokni: main, aside, section, grid yacheykasi.

3.3 size — bo'yi ham kerak bo'lsa

container-type: size bilan bo'yni ham so'rash mumkin: @container (height > 20rem) yoki (orientation: landscape). Lekin endi bo'y ham bolalardan kelmaydi. Chrome'da tekshirdik: size berilgan, bo'yi yozilmagan div ning bo'yi — 0 piksel, ichida matn bo'lsa ham. Shuning uchun size — faqat bo'yi aniq qutilar uchun: height: 100svh li to'liq ekranli blok (Viewport birliklari) yoki qat'iy o'lchamli vidjet.

3.4 Konteyner o'zini so'ray olmaydi

@container ichidagi qoida konteynerning bolalariga tegadi, konteynerning o'ziga emas. «Bitta CSS, ikki xil karta» natijasida konteyner — main, o'zgargan esa — uning ichidagi .taom-karta. Kartaning o'zini konteyner qilsangiz, @container karta ichidagi surat va matnni o'zgartira oladi, lekin kartaning o'z display: grid ini — yo'q. Shuning uchun konteyner odatda "o'ram": komponent turadigan ustun yoki yacheyka.

Tekshirib ko'ring: Stajyor .taom-karta { container-type: inline-size; } yozdi va @container (width >= 25rem) { .taom-karta { display: grid; } } qo'shdi. Karta hech qachon ikki ustunli bo'lmayapti. Nega?

Javob

Karta o'zini so'ray olmaydi. .taom-karta qoidasi kartaning otasidan boshlab eng yaqin konteynerni qidiradi. Otasida container-type yo'q, undan tepada ham yo'q — shart hech qachon bajarilmaydi. Tuzatish: container-type ni ota — main yoki aside — ga yozing.

4. Nomli konteynerlar

4.1 Eng yaqin konteyner muammosi

@container (...) nomsiz yozilsa, brauzer elementning eng yaqin konteyner-otasini oladi. Ichma-ich konteynerlar bo'lsa, bu siz kutgan quti bo'lmasligi mumkin. Masalan, menyuda section ham konteyner, uning ichidagi har li ham. Karta li ni so'raydi, siz esa section ni nazarda tutgan edingiz.

Yechim — konteynerga nom berish:

css
main {
  container-name: kartalar;
  container-type: inline-size;
}

@container kartalar (width >= 25rem) {
  .taom-karta {
    display: grid;
    grid-template-columns: 9rem 1fr;
  }
}

Endi so'rov faqat kartalar nomli eng yaqin otaga qaraydi. Oradagi nomsiz konteynerlar o'tkazib yuboriladi.

4.2 Qisqa yozuv container

Ikki qatorni bittaga yig'ish mumkin — CSS nima darsidagi qisqa yozuv kabi. Tartib: avval nom, /, keyin tur:

css
main {
  container: kartalar / inline-size;
}

Bitta elementda bir necha nom ham bo'ladi: container-name: kartalar menyu; — bo'sh joy bilan. Nomni o'zingiz tanlaysiz, u class emas va HTML'da ko'rinmaydi.

Maslahat: Kichik loyihada nomsiz so'rov ham yetadi. Komponent turli sahifalarda ichma-ich qutilarga tushishi mumkin bo'lsa — nom bering.

5. Konteyner birliklari: cqi va boshqalar

5.1 Oltita birlik

Viewport birliklari darsida vw — oyna enining 1 foizi edi. Konteyner birliklari xuddi shunday, faqat oyna o'rniga — eng yaqin konteyner:

Birlik 1 birlik =
cqw / cqh Konteyner eni / bo'yining 1%
cqi / cqb Inline / block o'lchamning 1%
cqmin / cqmax Kichik / katta tomonning 1%

Amalda cqi eng ko'p ishlatiladi: u inline-size konteyner bilan mos keladi. cqh va cqb faqat size turidagi konteynerda ma'noli.

5.2 Sarlavha quti bilan birga o'sadi

html
<style>
  body {
    font-family: system-ui, sans-serif;
  }
  section {
    container-type: inline-size;
    border: 1px dashed #5b6660;
    padding: 0 0.75rem;
    margin-bottom: 1rem;
  }
  section + section {
    width: 50%;
  }
  h3 {
    color: #2f6b3a;
    font-size: clamp(1rem, 0.25rem + 3cqi, 2.25rem);
  }
</style>
<section>
  <h3>Choyxona «Bahor» — menyu</h3>
</section>
<section>
  <h3>Choyxona «Bahor» — menyu</h3>
</section>

Nimaga qarang: ikkala sarlavhaning CSS'i bir xil, lekin keng qutidagisi kattaroq. Chrome'da o'lchadik: kompyuter enida 36 va 23 piksel, planshetda 26 va 16, telefonda ikkalasi ham 16. clamp() (Matematik funksiyalar) o'lchamni chegaralaydi: sarlavha 1rem dan kichik va 2.25rem dan katta bo'lmaydi.

Bu — Fluid tipografiya darsidagi vw formulasining konteyner varianti: sarlavha ekranga emas, o'z qutisiga qarab o'sadi. Formulada rem qismi qolishi muhim. Faqat cqi da berilgan shrift foydalanuvchining shrift sozlamasiga javob bermaydi — vw dagi muammoning o'zi (Viewport birliklari).

5.3 Konteyner yo'q bo'lsa

Chrome'da tekshirdik: atrofida konteyner bo'lmagan elementga width: 50cqi yozsak, u 50svw bilan bir xil chiqdi. Spetsifikatsiya ham shunday deydi: konteyner topilmasa, birlik kichik viewport birligiga (svw, svh) aylanadi. Xato chiqmaydi, lekin natija siz kutgandek bo'lmaydi. Shuning uchun ota konteyner borligini tekshiring.

Tekshirib ko'ring: Konteyner eni 600 piksel. font-size: 3cqi necha piksel?

Javob

18 piksel. 1cqi = 600 ning 1 foizi = 6 piksel, 3cqi = 18. Konteyner 300 pikselga torayib qolsa — 9 piksel, bu o'qish uchun juda kichik. Shuning uchun shriftga konteyner birligini doim clamp() va rem bilan birga yozing.

6. Shartdagi birliklar: rem ishlating

Shartda rem ham, em ham yoziladi. Chrome'da tekshirdik: rem sahifaning ildiz shriftidan (html) olinadi, em esa konteynerning o'z shriftidan. Konteyner shrifti 32 piksel bo'lsa, @container (width >= 20em) — 640 piksel. Media query'da esa em doim brauzerning boshlang'ich shriftiga (odatda 16 piksel) teng edi (Media queries). Chalkashmaslik uchun kursdagi qaror: container query shartlarida rem yozamiz.

7. Style queries: o'zgaruvchiga qarab

7.1 G'oya

CSS o'zgaruvchilari 2 darsida achchiq kartani --achchiq: ; hiylasi bilan qizg'ish qilgan edik va "buning uchun rasmiy vositalar kelmoqda" degan edik. Mana biri — style query (uslub so'rovi): konteynerdagi CSS o'zgaruvchisining qiymatini so'rash.

html
<style>
  body {
    font-family: system-ui, sans-serif;
  }
  .taom-karta {
    border: 2px solid #2f6b3a;
    padding: 0 0.75rem;
    margin-bottom: 0.75rem;
  }
  .taom-karta.achchiq {
    --achchiq: ha;
  }
  @container style(--achchiq: ha) {
    h3 {
      color: #b4461a;
    }
    h3::after {
      content: " — achchiq";
      font-weight: normal;
    }
  }
</style>
<article class="taom-karta">
  <h3>Osh</h3>
  <p>35 000 so'm</p>
</article>
<article class="taom-karta achchiq">
  <h3>Lag'mon</h3>
  <p>28 000 so'm</p>
</article>

Nimaga qarang: lag'mon sarlavhasi qizg'ish va yonida "— achchiq" yozuvi paydo bo'ldi. Osh o'zgarmadi. Achchiq kartaga faqat bitta o'zgaruvchi berilgan, qolganini @container style(...) qildi. CSS o'zgaruvchilari 2 darsidagi bo'sh joy hiylasi endi kerak emas — qiymat oddiy so'z: ha.

7.2 Ikki farq

  • container-type shart emas. Style query uchun har element o'z-o'zidan konteyner. Shuning uchun h3 o'z otasidan — kartadan — so'raydi.
  • Karta o'z ramkasini o'zgartira olmaydi. «Konteyner o'zini so'ray olmaydi» qoidasi bu yerda ham ishlaydi. Kartaning border ini o'zgartirish uchun o'zgaruvchini kartaning otasiga yozish kerak bo'lardi.

Hozircha faqat CSS o'zgaruvchilarini so'rash mumkin: style(color: red) kabi oddiy xususiyat — brauzerlarda yo'q. style(--daraja > 2) kabi solishtirish ham hali Baseline emas — faqat tenglik.

7.3 Brauzer holati

Baseline ma'lumotiga ko'ra style queries — yangi Baseline: hamma asosiy brauzerda faqat 2026-yil 19-maydan beri (Chrome 111, Safari 18, Firefox 151). Eski brauzer @container style(...) blokini tushunmaydi va butunlay tashlab ketadi. Yuqoridagi natijada bu xavfsiz: lag'mon oddiy yashil karta bo'lib qoladi, sahifa buzilmaydi — Brauzer mosligi darsidagi progressive enhancement. Muhim ma'lumotni (narx, "tugadi" belgisi) faqat style query'ga ishonmang.

Tekshirib ko'ring: .taom-karta.achchiq { --achchiq: ha; } va @container style(--achchiq: ha) { .taom-karta { border-color: #b4461a; } } yozildi. Achchiq kartaning ramkasi qizg'ish bo'ladimi?

Javob

Yo'q. .taom-karta qoidasi kartaning otasini so'raydi, otada esa --achchiq yo'q (u kartaning o'zida). Ramka yashil qoladi. Ichidagi h3 esa kartani so'raydi — shuning uchun sarlavha o'zgaradi.

8. Scroll-state queries: skroll holatiga qarab

Uchinchi tur so'rov quti skroll holatini so'raydi:

  • stuck — position: sticky element chetga "yopishdimi" (fixed va sticky).
  • snapped — element skroll-snap bilan joyiga "tushdimi" (skroll-snap'ni Skroll xulqi darsida o'rganamiz, hozir bilish shart emas).
  • scrollable — quti yana aylantirilishi mumkinmi.

Misol: menyu sarlavhasi yopishganda to'q yashil bo'lsin.

html
<style>
  body {
    font-family: system-ui, sans-serif;
  }
  section {
    height: 12rem;
    overflow-y: auto;
    border: 1px solid #c9d6cf;
  }
  header {
    position: sticky;
    top: 0;
    container-type: scroll-state;
  }
  header h2 {
    margin: 0;
    padding: 0.5rem;
    background-color: #fffaf0;
  }
  @container scroll-state(stuck: top) {
    header h2 {
      background-color: #2f6b3a;
      color: #fffaf0;
    }
  }
  p {
    padding: 0 0.5rem;
  }
</style>
<section>
  <p>Pastga aylantiring.</p>
  <header><h2>Issiq taomlar</h2></header>
  <p>Osh — 35 000 so'm</p>
  <p>Lag'mon — 28 000 so'm</p>
  <p>Manti — 30 000 so'm</p>
  <p>Shashlik — 18 000 so'm</p>
  <p>Chuchvara — 25 000 so'm</p>
  <p>Ko'k choy — 5 000 so'm</p>
</section>

Nimaga qarang: qutini pastga aylantiring. Sarlavha tepaga yopishgan zahoti fon to'q yashilga aylanadi, yuqoriga qaytarsangiz — yana qaymoq rang. Chrome 154 da tekshirdik. Konteyner — sticky header, o'zgaradigani — uning ichidagi h2 (konteyner o'zini so'ray olmaydi).

Baseline ma'lumotiga ko'ra scroll-state queries — Baseline emas: faqat Chrome va Edge 133 dan boshlab bor, Firefox va Safari'da yo'q. U yerda sarlavha yopishadi, lekin rangi o'zgarmaydi. Shuning uchun uni faqat bezak uchun ishlating.

9. Media query yoki container query?

Qaror qoidasi bitta savoldan: "bu qoida nimaga bog'liq?"

Nimaga bog'liq Vosita Misol
Butun sahifa, ekran @media Ustunlar soni, navbar, sahifa chetlari
Komponent turgan joy @container Karta yotiq/tik, jadval yoki ro'yxat
Foydalanuvchi, qurilma @media Qorong'i rejim, sensorli ekran, chop etish

«Nega bu kerak?» bo'limidagi xato aynan shu edi: karta joyiga bog'liq, biz esa ekranni so'radik.

Uchinchi qator muhim: konteyner "foydalanuvchi qorong'i rejimni tanladimi?" yoki "sensorli ekranmi?" degan savolga javob bermaydi. Bular faqat @media da — Foydalanuvchi afzalliklari darsida ko'ramiz.

Container query media query bilan birga ishlaydi — «Bahor» sahifasida ko'rganimizdek. U Intrinsic layout darsidagi auto-fit to'r bilan ayniqsa yaxshi qovushadi: to'r ustun sonini o'zi o'zgartiradi, @container karta ichini yangi enga moslaydi.

Baseline ma'lumotiga ko'ra container queries (o'lcham bo'yicha) va konteyner birliklari — Baseline: 2023-yil fevralidan beri hamma asosiy brauzerda bor (Chrome 105, Firefox 110, Safari 16). "Keng tarqalgan" maqomini esa 2025-yil avgustida oldi — bugun bemalol ishlating.

Tekshirib ko'ring: Uch vazifa: (a) telefonda navbar havolalari ustma-ust, kompyuterda bir qatorda; (b) izoh bloki asosiy ustunda keng, yon panelda ixcham; (c) chop etganda menyu tugmalari yashirilsin. Har biriga qaysi vosita?

Javob

(a) @media — navbar sahifaning skeleti, ekranga bog'liq. (b) @container — bitta komponent ikki xil joyda. (c) @media print — chop etish qurilmaga bog'liq; uni Foydalanuvchi afzalliklari darsida yozamiz.

10. DevTools'da container query

Elements panelida container-type berilgan element yonida kichik container belgisi chiqadi. Kartani tanlasangiz, Styles bo'limida @container (width >= 25rem) qoidasi ko'rinadi. Ustiga sichqonchani olib borsangiz, sahifada so'ralayotgan quti belgilanadi. Shart bajarilmagan bo'lsa, qoida ko'rinmaydi yoki xira bo'ladi (DevTools'da CSS).

Tez sinov: qurilma rejimida (Ctrl + Shift + M) oyna enini sichqoncha bilan torting va shart qaysi enda yoqilishini kuzating.

11. Ko'p uchraydigan xatolar

11.1 container-type unutilgan

@container yozilgan, lekin hech bir otada container-type yo'q. Brauzer xato bermaydi — shart hech qachon bajarilmaydi. Tuzatish: o'ram elementga container-type: inline-size.

11.2 Element o'zini so'rayapti

Konteyner va o'zgartirilayotgan element — bitta. Tuzatish: konteynerni bir pog'ona tepaga — otaga ko'chiring.

11.3 Eni nolga tushdi

inline-block, fit-content yoki flex element konteyner qilindi — eni 0, matn so'zma-so'z tushdi. Tuzatish: eni tashqaridan keladigan element tanlang yoki unga en bering (flex: 1, width: 100%).

11.4 size va bo'y

container-type: size — quti bo'yi 0 ga tushdi, pastdagi kontent ustiga chiqdi. Tuzatish: faqat en kerak bo'lsa — inline-size.

11.5 Shriftda faqat cqi

font-size: 4cqi — tor qutida juda kichik, shrift sozlamasiga javob bermaydi. Tuzatish: clamp(1rem, 0.5rem + 4cqi, 2rem).

11.6 Style query'da oddiy xususiyat

@container style(display: grid) — brauzerlar hozircha faqat -- bilan boshlanadigan o'zgaruvchilarni so'raydi. Tuzatish: holatni o'zgaruvchiga yozing: --korinish: ixcham.

12. Mashqlar

Mashqlarni kurs/mashqlar/05/ papkasida bajaring.

1-mashq (oson): Ishlaydimi?

Har holatda karta @container (width >= 25rem) bo'yicha yotiq bo'ladimi? Ekran — 1280 piksel.

  1. Karta main ichida, main { container-type: inline-size; }, main eni 50rem.
  2. Karta aside ichida, aside eni 30rem, lekin container-type faqat main da.
  3. Karta li ichida, li { container-type: inline-size; }, li eni 20rem, li esa 50rem enli main ichida.
Yechim
  1. Ha — konteyner 50rem, shart 25rem.
  2. Yo'q — aside konteyner emas, undan tepada ham konteyner yo'q; shart bajarilmaydi. aside ning eni ahamiyatsiz.
  3. Yo'q — nomsiz so'rov eng yaqin konteynerni oladi: li (20rem). main ning 50rem i tekshirilmaydi. main ni so'rash kerak bo'lsa — unga nom bering («Nomli konteynerlar» bo'limi).

2-mashq (o'rta): Narx jadvali — tor joyda ro'yxat

«Bahor»ning ichimliklar bloki ikki joyda turadi: menyuda (keng) va bron sahifasining yon panelida (tor). Keng joyda nom va narx bir qatorda, uchlarda. Tor joyda nom tepada, narx ostida va qizg'ish. Quyidagi HTML'ga CSS yozing, konteyner — section, chegara — 22rem.

html
<section>
  <h2>Ichimliklar</h2>
  <p><span class="taom-nomi">Ko'k choy</span>
    <span class="narx">5 000 so'm</span></p>
  <p><span class="taom-nomi">Qora choy</span>
    <span class="narx">5 000 so'm</span></p>
</section>

Ishora: mobile-first (Mobile-first) — avval tor holat (span lar display: block, display), keyin @container (width >= 22rem) ichida keng holat (p ga display: flex va justify-content: space-between, Flex'da tekislash).

Yechim
html
<style>
  body {
    font-family: system-ui, sans-serif;
  }
  section {
    container-type: inline-size;
    border: 1px solid #c9d6cf;
    padding: 0 0.75rem;
    margin-bottom: 1rem;
  }
  section + section {
    width: 12rem;
  }
  .taom-nomi,
  .narx {
    display: block;
  }
  .narx {
    color: #b4461a;
    font-variant-numeric: tabular-nums;
  }
  @container (width >= 22rem) {
    section p {
      display: flex;
      justify-content: space-between;
    }
    .narx {
      color: inherit;
    }
  }
</style>
<section>
  <h2>Ichimliklar</h2>
  <p><span class="taom-nomi">Ko'k choy</span>
    <span class="narx">5 000 so'm</span></p>
  <p><span class="taom-nomi">Qora choy</span>
    <span class="narx">5 000 so'm</span></p>
</section>
<section>
  <h2>Ichimliklar</h2>
  <p><span class="taom-nomi">Ko'k choy</span>
    <span class="narx">5 000 so'm</span></p>
  <p><span class="taom-nomi">Qora choy</span>
    <span class="narx">5 000 so'm</span></p>
</section>
  • Tepadagi section keng — nom chapda, narx o'ngda. Pastdagisi 12rem — ro'yxat ko'rinishi, narx qizg'ish. Telefon enida (360) tepadagisi ham ~320 piksel — 22rem (352) dan tor, u ham ro'yxatga o'tadi.
  • p flex bo'lganda uning bolalari flex elementga aylanadi va display: block ahamiyatini yo'qotadi — shuning uchun tor holat qoidasini alohida bekor qilish kerak emas.
  • .narx ning rangi keng holatda inherit bilan qaytarildi — Meros darsidagi kalit so'z.

3-mashq (qiyin): Stajyorning uch xatosi

Stajyor bosh sahifadagi "Bugungi taklif" blokini container query bilan yozdi, lekin blok hech qachon o'zgarmayapti:

css
.aksiya {
  display: inline-block;
  container-type: inline-size;
}
@container taklif (width >= 25rem) {
  .aksiya {
    display: grid;
    grid-template-columns: 1fr auto;
  }
}
.aksiya h2 {
  font-size: 4cqi;
}

Uchta xatoni toping va tuzating. Blok HTML'da <section class="aksiya"> ichida h2 va p bor, section esa main ichida.

Yechim
  1. inline-block + container-type — eni mazmundan keladi, containment uni 0 ga tushiradi («Aylanma bog'liqlik» bo'limi). Blok eni ustundan kelsin: display ni olib tashlang.
  2. Element o'zini so'rayapti va nom yo'q — .aksiya taklif nomli konteynerni otalardan qidiradi, lekin bunday nom hech qayerda yo'q. Nom .aksiya ning o'zida bo'lsa ham, u o'zini so'ray olmasdi. Konteyner — main, nom — taklif.
  3. 4cqi shrift — tor joyda juda kichik, shrift sozlamasiga javob bermaydi. clamp() va rem bilan.
css
main {
  container: taklif / inline-size;
}
@container taklif (width >= 25rem) {
  .aksiya {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    column-gap: 1rem;
  }
}
.aksiya h2 {
  font-size: clamp(1.25rem, 0.75rem + 3cqi, 2rem);
}

.aksiya h2 dagi cqi endi main ning enidan hisoblanadi — eng yaqin konteyner shu.

4-mashq: Portfolio qadami — loyiha kartalari o'z eniga moslashadi

Portfoliongizning loyihalar/index.html sahifasida article kartalar .loyihalar to'rida turibdi (Grid'ga kirish va auto-fit darslari). To'r ekranga qarab ustun sonini o'zgartiradi, shuning uchun karta eni oldindan ma'lum emas: planshetda bitta keng karta, kompyuterda ikkita torroq karta bo'lishi mumkin.

  1. Har article ni konteyner qiling.
  2. Karta keng bo'lsa (kamida 28rem), pastdagi havolalar ro'yxati (ul) bir qatorga tizilsin: marker'siz, havolalar orasida 1rem.
  3. Karta sarlavhasi (h2) karta eniga qarab 1.25rem dan 1.75rem gacha o'ssin.
  4. DevTools'da 768 va 1280 piksel enda tekshiring: qaysi enda kartalar keng holatda?

Ishora: article — grid elementi, uning eni to'r yo'lagidan keladi (mazmundan emas), shuning uchun "eni nolga tushdi" tuzog'i bu yerda yo'q. @container ichidagi ul va h2 — article ning bolalari, konteynerning o'zi emas. Marker'ni olib tashlash — list-style: none va padding: 0 (Ro'yxatlar stili).

Yechim
css
/* Loyiha kartalari — o'z eniga qarab */
.loyihalar > article {
  container-type: inline-size;
}

.loyihalar h2 {
  font-size: clamp(1.25rem, 1rem + 2cqi, 1.75rem);
}

@container (width >= 28rem) {
  .loyihalar ul {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    list-style: none;
    padding: 0;
  }
}

Natijada ikki xil enli karta:

html
<style>
  body {
    font-family: system-ui, sans-serif;
    color: #1f2a24;
    background-color: #f7faf8;
  }
  .loyihalar {
    display: grid;
    grid-template-columns:
      repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
    gap: 1rem;
  }
  .loyihalar > article {
    container-type: inline-size;
    border: 1px solid #c9d6cf;
    padding: 0 1rem;
  }
  .loyihalar h2 {
    color: #1f6f4a;
    font-size: clamp(1.25rem, 1rem + 2cqi, 1.75rem);
  }
  @container (width >= 28rem) {
    .loyihalar ul {
      display: flex;
      flex-wrap: wrap;
      gap: 1rem;
      list-style: none;
      padding: 0;
    }
  }
</style>
<div class="loyihalar">
  <article>
    <h2>Choyxona «Bahor» sayti</h2>
    <p>To'rt sahifali sayt: menyu, bron formasi, 404.</p>
    <ul>
      <li><a href="bahor/">Loyiha haqida batafsil</a></li>
      <li><a href="https://example.com/bahor/">Saytni ochish</a></li>
    </ul>
  </article>
  <article>
    <h2>Semantik blog maqolasi</h2>
    <p>"Osh sirlari": landmarklar va izohli rasmlar.</p>
    <ul>
      <li><a href="https://example.com/blog/">Saytni ochish</a></li>
    </ul>
  </article>
</div>
  • Telefon (360): bitta ustun, karta ichi ~310 piksel — 28rem (448) dan tor. Havolalar oddiy ro'yxat.
  • Planshet (768): to'r ikki ustunga o'tdi, har karta ~370 piksel — yana tor, ro'yxat.
  • Kompyuter (1280): kartalar ~620 piksel — havolalar bir qatorda, sarlavha kattaroq.

Kuzating: 768 da ekran "katta", lekin karta tor — media query bu yerda xato qarorga kelardi. Sizning .loyihalar to'ringiz boshqacha bo'lsa (masalan, main ustuni 70ch bilan cheklangan), kartalar enini DevTools'da o'lchang va chegarani (28rem) shunga qarab tanlang.

Diqqat: Portfolio kartalari subgrid darsidan beri ota to'rga ulangan, natijada esa subgrid yo'q. Konteyner o'z ichini tashqi to'rdan uzadi: Chrome'da tekshirdik — container-type qo'shilgan kartalarda subgrid ishlamay qoldi, sanalar yana "zinapoya" bo'ldi. Kartangizda shunday bo'lsa — DevTools'da ko'ring. Yakuniy loyiha darsida subgrid'ni qoldirib, bu container query'ni olib tashlaymiz; havolalarni esa Intrinsic layout darsidagi Cluster bilan o'raymiz.

13. Real ishda

  • Dizayn tizimlari va komponent kutubxonalari komponentni "qayerga qo'yilishini bilmasdan" yozadi. Container query shuning uchun paydo bo'ldi.
  • Tailwind (kursda alohida o'rganamiz) buni @container class'lari bilan qo'llaydi: otaga @container, bolaga @md:flex kabi.
  • Kartalar darsida kartaning gorizontal va vertikal variantini aynan container query bilan quramiz.
  • Intervyuda so'raladi: "Container query media query'dan nimasi bilan farq qiladi?", "Nega container-type: size kam ishlatiladi?", "Element o'zini so'ray oladimi?". Endi uchalasiga ham javob bera olasiz.

Xulosa

  • @media ekranni so'raydi, @container — komponent turgan qutini.
  • Konteyner — ota: container-type: inline-size; qoida uning bolalariga tegadi, o'ziga emas.
  • Containment tufayli konteyner eni mazmundan kelmaydi — eni mazmundan keladigan elementni konteyner qilmang.
  • Nom (container: kartalar / inline-size) ichma-ich konteynerlarda kerakli qutini tanlaydi.
  • cqi — konteyner enining 1 foizi; shriftda doim clamp() va rem bilan.
  • Style queries — yangi Baseline (2026-yil may), scroll-state — Baseline emas (faqat Chrome/Edge): faqat bezak uchun.

Keyingi dars: Rasmlar CSS tomoni — image-set() bilan fon rasmlarini ekranga moslaymiz, sizes ni CSS layout'dan hisoblaymiz va aspect-ratio bilan sakrashning oldini olamiz.

Manbalar

  • MDN: "CSS container queries", "container-type", "container", "Container size and style queries", "Container scroll-state queries" — developer.mozilla.org
  • W3C: "CSS Conditional Rules Module Level 5" (@container), "CSS Containment Module Level 3" (container units) — w3.org/TR/css-conditional-5, w3.org/TR/css-contain-3
  • web-features (Baseline ma'lumotlari): "container-queries", "container-style-queries", "container-scroll-state-queries" — github.com/web-platform-dx/web-features
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
CSS container queries: komponent o'z konteyneriga moslashadi — IlmHamroh