IlmHamroh
JavaScript Full-stack/6-qism. CSS: harakat, zamonaviy CSS va dizayn15/57-dars20 daqiqa
Mundarija (31)

CSS top layer: dialog va popover'ni stillash, ::backdrop va animatsiya

Qisqacha: Modal dialog va popover top layer'ga — sahifadagi hamma narsa ustidagi alohida qatlamga chiqadi, shuning uchun ularga z-index kerak emas va otaning overflow yoki transform i ularni kesmaydi. Orqadagi parda — ::backdrop, ochiq holat — :modal, [open] va :popover-open bilan tanlanadi. Popover'ga display ni faqat :popover-open ichida bering, aks holda u yopiq holatda ham ko'rinadi. Ochilish va yopilish animatsiyasi — @starting-style va transition-behavior: allow-discrete bilan.

Bu darsda

  • Top layer nima ekanini va u z-index muammolarini qanday yo'q qilishini tushuntira olasiz.
  • Brauzer dialog va popover'ga beradigan standart stillarni bilasiz va ularni o'zgartirasiz.
  • ::backdrop ni bo'yaysiz va xiralashtirasiz.
  • Popover'dagi display tuzog'ini tuzatasiz.
  • Oyna va popover'ga ochilish hamda yopilish animatsiyasini qo'shasiz.

Oldin bilishingiz kerak: dialog: native modal oyna, Popover API, z-index va stacking context, Kirish va chiqish animatsiyalari.

1. Nega bu kerak?

O'tgan darsda View Transitions bilan holatlar orasida silliq o'tishni ko'rdik. Bugun HTML qismida qurilgan ikki elementga qaytamiz.

dialog darsida «Bahor» bron sahifasiga "Bronni bekor qilasizmi?" oynasini qo'ygan edik. Brauzer uni tekin ko'rsatdi: markazda, qora ramka bilan, orqasida xira parda. Ishlaydi, lekin chiroyli emas — ramka qo'pol, parda deyarli sezilmaydi. Popover API darsidagi "Ish vaqti" popover'i ham shunday: oddiy oq quti.

O'sha darslarda uchta va'da bergan edik:

  1. Oyna ortidagi pardani (::backdrop) bo'yash va xiralashtirish.
  2. Popover'ni bezash va uning :popover-open holati.
  3. Popover'ga display berilsa, u yopiq holatda ham ko'rinib qolishi — buni hal qilish.

z-index darsida esa "modal oynalar uchun z-index poygasiz yo'l bor" degandik. Bugun hammasini bajaramiz.

2. Top layer: hamma narsaning ustida

2.1 Eslatma: z-index poygasi

z-index va stacking context darsidagi muammoni eslang. Oynani position: fixed va z-index: 9999 bilan yasadingiz. Lekin u transform li kartaning ichida turibdi — karta o'z stacking context'ini yaratgan, oyna uning ichida "qamalib" qoldi. Boshqa bir banner z-index: 10000 oldi va oyna uning ostiga tushdi. Otada overflow: hidden bo'lsa, oyna yana kesiladi.

2.2 Top layer

Top layer (eng ustki qatlam) — sahifaning oddiy qatlamlaridan butunlay tashqaridagi alohida qavat. Unga faqat brauzer element joylay oladi: showModal() bilan ochilgan dialog, ochiq popover va to'liq ekran rejimidagi element. dialog darsidagi o'xshatish: stol ustidagi qog'ozlar ustiga qo'yilgan shisha.

Top layer'dagi element uchun:

  • z-index ahamiyatsiz — u har qanday z-index dan yuqori.
  • Otaning overflow: hidden, transform va stacking context'i unga ta'sir qilmaydi.
  • Bir nechta element bo'lsa, oxirgi ochilgani eng ustida.

Tekshirib ko'ramiz. Oyna transform va overflow: hidden li kichik qutining ichida, sahifada esa z-index: 9999 li qizg'ish banner bor:

html
<style>
  body { font-family: system-ui, sans-serif; }
  .quti {
    height: 48px;
    overflow: hidden;
    transform: translateX(0);
    border: 2px dashed #5b6660;
  }
  .banner {
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: 9999;
    padding: 16px;
    background-color: #b4461a;
    color: #fffaf0;
  }
</style>
<div class="quti">
  <button type="button" commandfor="oyna" command="show-modal">
    Oynani ochish
  </button>
  <dialog id="oyna">
    <p>Men 48 pikselli qutining ichidaman.</p>
    <form method="dialog"><button>Yopish</button></form>
  </dialog>
</div>
<p class="banner">Banner: z-index 9999</p>

Nimaga qarang: tugmani bosing. Oyna 48 pikselli qutining ichida yozilgan, lekin to'liq ko'rinadi — overflow: hidden uni kesmadi. Pastdagi qizg'ish banner z-index: 9999 bo'lsa ham, brauzerning och kulrang pardasi uni ham biroz qoraytiradi — banner endi bosilmaydi. Chrome'da tekshirdik: banner ustiga bosilganda bosish bannerga emas, oynaning pardasiga tushadi. Parda ham top layer'da, banner esa uning ostida. Tugma oynani JavaScript'siz ochadi — Invoker commands darsidagi command="show-modal".

Maslahat: Chrome DevTools'ning Elements panelida top layer'dagi elementlar alohida #top-layer bo'limida ko'rsatiladi. Oyna yoki popover "yo'qolib" qolsa, avval shu yerga qarang.

Tekshirib ko'ring: Non-modal oyna (<dialog open> yoki show()) ham top layer'ga chiqadimi?

Javob

Yo'q. Faqat showModal() (yoki command="show-modal") bilan ochilgan modal oyna top layer'ga chiqadi. open atributi bilan ochilgan oyna oddiy element kabi sahifa ichida turadi — unga z-index ta'sir qiladi, overflow: hidden uni kesadi. Popover esa auto, manual va hint turlarining hammasida top layer'ga chiqadi.

3. Brauzer nima beradi va nimani o'zgartiramiz

3.1 Standart stillar

Chrome'da ochiq elementlarning hisoblangan stillarini o'lchadik:

Modal dialog Popover
Joylashuv fixed, inset: 0, margin: auto xuddi shunday
Ichki bo'shliq padding: 1em (16px) padding: 0.25em (4px)
Ramka 3px solid (matn rangida) xuddi shunday
Fon oq (tizim rangi Canvas) xuddi shunday
::backdrop rgba(0, 0, 0, 0.1) shaffof

fixed + inset: 0 + margin: auto — position darsidagi markazlash usuli. Oyna shu sabab o'rtada turadi. Modal oynaning eng katta o'lchami ham cheklangan: max-width va max-height — calc(100% - 6px - 2em), ya'ni ekrandan biroz kichik. Kontent uzun bo'lsa, oyna ichida skroll paydo bo'ladi.

3.2 «Bahor» oynasini bezaymiz

html
<style>
  body { font-family: system-ui, sans-serif; }
  dialog {
    max-inline-size: min(90vw, 28rem);
    padding: 24px;
    border: none;
    border-radius: 16px;
    background-color: #fffaf0;
    color: #1f2a24;
    box-shadow: 0 12px 32px #1f2a2440;
  }
  dialog::backdrop {
    background-color: #1f2a24b3;
    backdrop-filter: blur(3px);
  }
  dialog h2 {
    margin-block-start: 0;
    color: #2f6b3a;
  }
  dialog form {
    display: flex;
    justify-content: end;
    gap: 8px;
  }
  dialog button {
    padding: 8px 16px;
    border: 2px solid #2f6b3a;
    border-radius: 8px;
    background-color: transparent;
    color: #2f6b3a;
    font: inherit;
  }
  dialog button[value="ha"] {
    background-color: #b4461a;
    border-color: #b4461a;
    color: #fffaf0;
  }
  dialog button:focus-visible {
    outline: 3px solid #1a5d1a;
    outline-offset: 2px;
  }
</style>
<h1>Bron: 4-stol, 19:00</h1>
<p>Osh va ko'k choy buyurtma qilingan.</p>
<button type="button" commandfor="bekor" command="show-modal">
  Bronni bekor qilish
</button>
<dialog id="bekor" aria-labelledby="bekor-sarlavha">
  <h2 id="bekor-sarlavha">Bronni bekor qilasizmi?</h2>
  <p>4-stol bugun 19:00 ga band qilingan edi.</p>
  <form method="dialog">
    <button value="yoq" autofocus>Yo'q, qolsin</button>
    <button value="ha">Ha, bekor qilish</button>
  </form>
</dialog>

Nimaga qarang: tugmani bosing. Oyna qaymoq rangli, burchaklari yumaloq, ostida yumshoq soya. Orqadagi sahifa to'q yashil-kulrang parda ortida va xiralashgan — sarlavha harflari o'qilmaydi. Fokus "Yo'q, qolsin" tugmasida (autofocus) — Tab bosib, yashil fokus halqasini ko'ring.

Kod bo'yicha:

  • max-inline-size: min(90vw, 28rem) — telefonda ekranning 90% i, kompyuterda 28rem dan oshmaydi (Matematik funksiyalar).
  • border: none — brauzerning 3 piksellik ramkasi o'rniga soya.
  • ::backdrop — Pseudo-elementlar darsida ko'rgan parda. #1f2a24b3 — «Bahor» matn rangi, oxiridagi b3 — taxminan 70% qoplama (30% i shaffof).
  • backdrop-filter: blur(3px) — parda ortidagi hamma narsani xiralashtiradi. Baseline ma'lumotiga ko'ra u yangi Baseline (2024-yil sentabr): eski brauzerda xiralik bo'lmaydi, faqat rangli parda qoladi — o'qish uchun bu yetarli.
  • Xavfli amal ("Ha, bekor qilish") qizg'ish, xavfsizi — sukut bo'yicha fokusda. Tasodifan Enter bosilsa, bron saqlanib qoladi.

Bu stillar — top layer'ni o'rganish uchun. «Bahor»ning to'liq oyna komponenti tokenlar va tugmalar tizimi bilan Modal oyna va skroll bloklash darsida quriladi va shu oyna ham o'shani oladi — bu darsdagi alohida qoidalar u yerda keraksiz bo'ladi.

3.3 Ochiq holatni tanlash

Selektor Qachon mos keladi
dialog[open] Oyna ochiq (modal ham, non-modal ham)
dialog:modal Faqat showModal() bilan ochilgan oyna
:popover-open Ochiq popover
[popover] Popover atributi bor element (ochiq yoki yopiq)
::backdrop Modal oyna yoki popover ortidagi parda

Yangi :open pseudo-klassi ham bor: dialog:open — dialog[open] bilan bir xil ma'noda, details:open ham shunday. Baseline ma'lumotiga ko'ra u 2026-yil mayida Baseline bo'lgan — juda yangi, shuning uchun hozircha [open] xavfsizroq.

:modal qachon kerak? Bitta dialog ba'zan modal, ba'zan oddiy ochilsa: modal holatda soya va parda, oddiy holatda — yengilroq ko'rinish.

Tekshirib ko'ring: Oyna foniga qaymoq rang berdingiz, lekin orqadagi sahifa hali ham deyarli qoraymayapti. Qaysi selektorga rang berish kerak?

Javob

dialog::backdrop ga. Oyna foni (dialog) va parda (::backdrop) — ikki alohida narsa. Parda oynaning ortida, butun ekranni qoplaydi. Brauzer unga atigi 10% qora beradi, shuning uchun o'zingiz qalinroq rang yozasiz.

4. Popover'ni bezash va display tuzog'i

4.1 Tuzoq

«Bahor»ning "Ish vaqti" popover'i ichida ikki qator bor, ularni grid bilan tekislamoqchimiz:

html
<style>
  body { font-family: system-ui, sans-serif; }
  .xato[popover] {
    display: grid;
    grid-template-columns: auto auto;
    gap: 4px 16px;
  }
</style>
<button type="button" popovertarget="vaqt1">❌ Ish vaqti</button>
<div id="vaqt1" class="xato" popover>
  <span>Du–Ju</span><span>7:00–23:00</span>
  <span>Sha–Ya</span><span>8:00–24:00</span>
</div>

Nimaga qarang: tugma bosilmagan, lekin jadval sahifada ko'rinib turibdi. Tugmani bossangiz ham, tashqariga bossangiz ham — u yo'qolmaydi. Chrome'da tekshirdik: yopiq popover'ning hisoblangan display qiymati grid.

Sabab — Kaskad. Popover yopiq bo'lganda uni brauzerning o'z stili yashiradi: [popover]:not(:popover-open) { display: none; }. Siz yozgan .xato[popover] { display: grid; } esa muallif stili — u brauzer stilidan doim yutadi. display darsidagi [hidden] tuzog'i bilan bir xil hikoya.

4.2 Tuzatish

display ni faqat ochiq holatga bering:

html
<style>
  body { font-family: system-ui, sans-serif; }
  .ish-vaqti:popover-open {
    display: grid;
    grid-template-columns: auto auto;
    gap: 4px 16px;
  }
  .ish-vaqti {
    padding: 16px;
    border: 2px solid #2f6b3a;
    border-radius: 12px;
    background-color: #fffaf0;
    color: #1f2a24;
    box-shadow: 0 8px 24px #1f2a2433;
  }
  .ish-vaqti strong {
    grid-column: 1 / -1;
    color: #2f6b3a;
  }
</style>
<button type="button" popovertarget="vaqt2">✅ Ish vaqti</button>
<div id="vaqt2" class="ish-vaqti" popover>
  <strong>«Bahor» ish vaqti</strong>
  <span>Du–Ju</span><span>7:00–23:00</span>
  <span>Sha–Ya</span><span>8:00–24:00</span>
</div>

Nimaga qarang: endi jadval faqat tugma bosilganda chiqadi — ekran o'rtasida, yashil ramka va soya bilan. Tashqariga bosing yoki Esc — yopiladi (Popover API darsidagi light dismiss). Ramka, fon va soya yopiq holat qoidasida ham turibdi — ular display emas, zararsiz.

Qoida: popover'ning ko'rinishini (rang, ramka, shrift) oddiy selektorga, joylashuv turini (display) esa faqat :popover-open ga yozing. Oyna ham xuddi shunday: dialog { display: flex; } yopiq oynani ko'rsatib qo'yadi — dialog[open] { display: flex; } deb yozing.

Popover'ni tugma yoniga "bog'lab" qo'yish — keyingi darsning mavzusi: Anchor positioning.

Tekshirib ko'ring: dialog { display: flex; flex-direction: column; } yozildi. Sahifa ochilganda nima bo'ladi?

Javob

Yopiq oyna sahifada oddiy blok sifatida ko'rinib qoladi. Yopiq dialog ni ham brauzer stili display: none bilan yashiradi, muallif stili esa undan yutadi. Tuzatish: dialog[open] { display: flex; ... } — faqat ochiq holatda.

5. Ochilish va yopilish animatsiyasi

5.1 Nega bu qiyin edi

Oyna yopiq holatda display: none. Kirish va chiqish animatsiyalari darsidan eslang: display: none dan chiqqan elementning "oldingi holati" yo'q, transition'ga boshlanish nuqtasi kerak. Yopilishda esa element darhol display: none bo'ladi — so'nish animatsiyasini ko'rsatishga ulgurmaydi. O'sha darsdagi uch vosita bu yerda ham ishlaydi:

  • @starting-style — ochilishdagi boshlanish holati.
  • transition-behavior: allow-discrete (yoki transition ichida allow-discrete so'zi) — display ni ham transition'ga qo'shadi: yopilishda element animatsiya tugaguncha ko'rinib turadi.
  • overlay — top layer'ga xos xususiyat. Uni ham allow-discrete bilan transition'ga qo'shsangiz, yopilayotgan oyna animatsiya tugaguncha top layer'da qoladi.

5.2 To'liq andoza

html
<style>
  body { font-family: system-ui, sans-serif; }
  dialog {
    padding: 24px;
    border: none;
    border-radius: 16px;
    background-color: #fffaf0;
    opacity: 0;
    translate: 0 24px;
    transition:
      opacity 0.25s ease-out,
      translate 0.25s ease-out,
      display 0.25s allow-discrete,
      overlay 0.25s allow-discrete;
  }
  dialog[open] {
    opacity: 1;
    translate: 0 0;
  }
  @starting-style {
    dialog[open] {
      opacity: 0;
      translate: 0 24px;
    }
  }
  dialog::backdrop {
    background-color: #1f2a2400;
    transition:
      background-color 0.25s,
      display 0.25s allow-discrete,
      overlay 0.25s allow-discrete;
  }
  dialog[open]::backdrop {
    background-color: #1f2a24b3;
  }
  @starting-style {
    dialog[open]::backdrop {
      background-color: #1f2a2400;
    }
  }
</style>
<button type="button" commandfor="yangi-taom" command="show-modal">
  Yangi taom haqida
</button>
<dialog id="yangi-taom">
  <p>Bugundan menyuda — tandir go'sht!</p>
  <form method="dialog"><button>Yopish</button></form>
</dialog>

Nimaga qarang: tugmani bosing — oyna 24 piksel pastdan ko'tarilib, asta paydo bo'ladi, parda ham asta qorayadi. "Yopish" ni bosing — oyna pastga tushib so'nadi, parda ham so'nadi. Hammasi chorak soniyada.

Chrome'da o'lchadik (0,4 s li sinov nusxasida): yopilgandan 0,2 soniya keyin oyna opacity si 0.21 edi, display hali block — animatsiya davom etyapti. 0,6 soniyadan keyin display: none. Parda ham shu vaqtda so'nib borayotgan edi.

Kodni o'qiymiz. Avval uch holatni diagrammada ko'ring:

stateDiagram-v2
    direction LR
    Yopiq: Yopiq (shaffof, pastda)
    Boshi: Boshlanish (@starting-style)
    Ochiq: Ochiq (dialog[open])
    Yopiq --> Boshi: tugma bosildi
    Boshi --> Ochiq: 0.25 s o'tish
    Ochiq --> Yopiq: «Yopish», 0.25 s

Nimaga qarang: ochilishda oyna @starting-style dagi holatdan boshlaydi. Yopilishda boshlanish holati kerak emas — oyna ochiq holatdan to'g'ri yopiq holatga qaytadi.

  • Uch holat. Yopiq (dialog — shaffof va pastda), ochiq (dialog[open]), ochilish boshlanishi (@starting-style). Ochilish: boshlanishdan ochiqqa. Yopilish: ochiqdan yopiqqa.
  • translate — 2D transformlar darsidagi alohida xususiyat. transform ni ishlatmadik: brauzer oynani margin: auto bilan markazlaydi, translate esa unga qo'shimcha siljish beradi.
  • ::backdrop ning o'z transition'i. Parda alohida pseudo-element — unga o'z @starting-style i kerak. #1f2a2400 — xuddi shu rang, lekin to'liq shaffof: rangdan rangga o'tish silliq bo'lishi uchun transparent o'rniga shunday yozdik.

5.3 Brauzer mosligi

Baseline ma'lumotiga ko'ra:

  • @starting-style va transition-behavior — yangi Baseline, 2024-yil avgustidan.
  • overlay — Baseline emas: faqat Chrome va Edge'da (117-versiyadan). MDN'ning brauzerlar jadvalida Firefox va Safari'da yo'q.

overlay bo'lmagan brauzerda oyna yopilish boshlanishi bilan top layer'dan chiqadi. Pardasi darhol yo'qolishi mumkin va oyna animatsiya davomida oddiy qatlamda turadi. Ochilish animatsiyasi esa to'liq ishlaydi. Qolgan hammasi — oynaning o'zi, ochilishi, yopilishi — hamma joyda ishlaydi. Bu yana progressive enhancement (Brauzer mosligi darsida): asosiy ish hamma brauzerda bajariladi, bezak esa imkoni bor joyda qo'shiladi.

5.4 Harakatni kamaytirish

"Pastdan ko'tarilish" — harakat. prefers-reduced-motion darsidagi qoida: o'chirish emas, almashtirish. Harakat kamaytirilganda siljishni olib tashlaymiz, shaffoflik o'zgarishi qolsin:

css
@media (prefers-reduced-motion: reduce) {
  dialog,
  dialog[open] {
    translate: none;
  }
}

@starting-style dagi translate: 0 24px ham bekor bo'ladimi? Ha: ikkala qoida bir xil og'irlikda, media query esa keyin yozilgan — kaskadda keyingisi yutadi. Chrome'da prefers-reduced-motion: reduce bilan o'lchadik: ochilish paytida translate doim none, opacity esa 0 dan 1 ga silliq o'sdi. O'zingiz tekshirish uchun: DevTools → Rendering → prefers-reduced-motion: reduce.

Tekshirib ko'ring: Ochilish silliq, lekin yopilishda oyna bir zumda yo'qoladi. transition ro'yxatida opacity va translate bor. Nima yetishmayapti?

Javob

display 0.25s allow-discrete (va Chrome uchun overlay 0.25s allow-discrete). Yopilishda brauzer oynaga display: none beradi. allow-discrete bo'lmasa, bu darhol sodir bo'ladi — so'nish animatsiyasi ko'rinishga ulgurmaydi. allow-discrete esa display ni animatsiya oxirigacha kechiktiradi.

6. Popover animatsiyasi va turlari

Popover uchun andoza xuddi shunday, faqat selektor boshqa:

css
[popover] {
  opacity: 0;
  scale: 0.95;
  transition:
    opacity 0.2s,
    scale 0.2s,
    display 0.2s allow-discrete,
    overlay 0.2s allow-discrete;
}

:popover-open {
  opacity: 1;
  scale: 1;
}

@starting-style {
  :popover-open {
    opacity: 0;
    scale: 0.95;
  }
}

Andoza dialog'dagi bilan bir xil, faqat siljish o'rniga scale — popover 95% kattalikdan to'liq kattalikka o'sadi. Chrome'da tekshirdik: popover yopilgandan 0,2 soniya keyin (0,4 s li sinovda) display hali grid edi, animatsiya tugagach — none.

Popover'ning uch turi — auto, manual, hint (Popover API) — CSS'da bir xil bezaladi: hammasi top layer'da, hammasi :popover-open bilan tanlanadi. Farq faqat xulqda. popover="hint" esa hali Baseline emas: Baseline ma'lumotiga ko'ra Chrome va Edge'da (151-versiyadan) hamda Firefox'da (153-versiyadan) bor, Safari'da yo'q. Safari uni manual deb tushunadi — stillar baribir ishlaydi.

Popover ::backdrop i ham bor, lekin sukut bo'yicha shaffof. Menyu popover'i ortini biroz qoraytirish kerak bo'lsa: [popover]::backdrop { background-color: #1f2a2433; }. Lekin ehtiyot bo'ling: parda "sahifa to'silgan" degan his beradi, popover esa sahifani to'smaydi — foydalanuvchini adashtirmang.

Tekshirib ko'ring: Popover'ga z-index: 5 yozilgan, sahifadagi sarlavhada esa z-index: 100. Ochiq popover sarlavha ostida qoladimi?

Javob

Yo'q. Ochiq popover top layer'da — u sahifaning oddiy qatlamlaridan tashqarida. Top layer'dagi elementga z-index umuman ta'sir qilmaydi, shuning uchun 5 ham, 100 ham farq qilmaydi.

7. Ko'p uchraydigan xatolar

7.1 display yopiq holatga yozilgan

Belgisi: popover yoki oyna sahifada doim ko'rinib turadi. Tuzatish: display ni :popover-open yoki dialog[open] ga ko'chiring.

7.2 z-index bilan kurash

Oyna nimanidir ostida qolyapti, z-index: 99999 berildi — foydasiz. Sabab: oyna showModal() bilan emas, show() yoki open atributi bilan ochilgan — u top layer'da emas. Tuzatish: modal kerak bo'lsa command="show-modal"; non-modal oynaga esa oddiy stacking context qoidalari ishlaydi.

7.3 Yopilish animatsiyasi ko'rinmaydi

Ochilish silliq, yopilish esa bir zumda. Sabab: transition ro'yxatida display ... allow-discrete yo'q — element darhol display: none bo'lyapti. Tuzatish: display 0.25s allow-discrete va (Chrome uchun) overlay 0.25s allow-discrete qo'shing.

7.4 Fokus halqasi ko'rinmaydi

Oyna foni qaymoq rang, tugmalar fokus halqasi esa brauzerning ko'k chizig'i — past kontrast. Klaviatura foydalanuvchisi (Bobur) qaysi tugmada turganini bilmaydi. Tuzatish: oyna ichidagi :focus-visible ga fonda aniq ko'rinadigan rang bering (Holat pseudo-klasslari). Oyna o'zining halqasini (dialog:focus-visible) o'chirmang — autofocus yo'q bo'lsa, fokus oynaning o'ziga tushishi mumkin.

8. Mashqlar

Mashqlarni kurs/mashqlar/06/ papkasida bajaring.

1-mashq (oson): parda rangi

«Bahor» bron sahifasidagi modal oyna pardasi «Bahor» asosiy yashil rangida (#2f6b3a), 60% qoplamali bo'lsin. Oynaning brauzer ramkasi olib tashlansin, burchaklari 12px yumaloq bo'lsin.

Ishora: shaffoflik uchun 8 xonali hex — oxirgi ikki belgi 99 taxminan 60% (Ranglar 1).

Yechim
css
dialog {
  border: none;
  border-radius: 12px;
}

dialog::backdrop {
  background-color: #2f6b3a99;
}

99 o'n oltilikda 153, 153 / 255 ≈ 0.6. oklch(from ...) yoki color-mix() bilan ham yozsa bo'ladi (Ranglar 3): color-mix(in oklch, #2f6b3a 60%, transparent).

2-mashq (o'rta): menyu popover'i

Menyu sahifasida "Allergenlar" tugmasi popover ochsin. Popover ichida ul ro'yxat (yong'oq, sut, bug'doy). Talablar:

  1. Popover ochiq bo'lganda — display: flex, flex-direction: column, gap: 8px.
  2. Qaymoq fon, yashil ramka, 12px burchak.
  3. Ochilishda 0,2 soniyada paydo bo'lsin, yopilishda so'nsin.

Ishora: «Popover'ni bezash va display tuzog'i» va «Popover animatsiyasi» bo'limlari. ul ning standart chekinishini Ro'yxatlar stili darsidagidek olib tashlang.

Yechim
html
<style>
  body { font-family: system-ui, sans-serif; }
  #allergen {
    padding: 16px;
    border: 2px solid #2f6b3a;
    border-radius: 12px;
    background-color: #fffaf0;
    opacity: 0;
    transition:
      opacity 0.2s,
      display 0.2s allow-discrete,
      overlay 0.2s allow-discrete;
  }
  #allergen:popover-open {
    display: flex;
    flex-direction: column;
    gap: 8px;
    opacity: 1;
  }
  @starting-style {
    #allergen:popover-open { opacity: 0; }
  }
  #allergen ul {
    margin: 0;
    padding-inline-start: 1.25em;
  }
</style>
<button type="button" popovertarget="allergen">Allergenlar</button>
<div id="allergen" popover>
  <strong>Taomlarimizda bo'lishi mumkin:</strong>
  <ul>
    <li>yong'oq</li>
    <li>sut</li>
    <li>bug'doy</li>
  </ul>
</div>

#allergen — id selektori, faqat mashq uchun: bitta popover. Real saytda bir nechta popover bir xil ko'rinsa, umumiy [popover] qoidasi qulayroq.

3-mashq (qiyin): modal va non-modal — bitta oyna

Bitta dialog ikki usulda ochilsin: "Tez ko'rish" tugmasi — oddiy (command="show"), "Batafsil" tugmasi — modal (command="show-modal"). Modal holatda oyna soyali va pardali, oddiy holatda — faqat ingichka ramka, sahifa oqimida.

Ishora: :modal va dialog[open] farqi — «Ochiq holatni tanlash» jadvali. Non-modal oyna sahifa oqimida turadi, shuning uchun uning joylashuvi position ga bog'liq.

Yechim
html
<style>
  body { font-family: system-ui, sans-serif; }
  dialog {
    border: 1px solid #2f6b3a;
    border-radius: 8px;
    background-color: #fffaf0;
  }
  dialog:modal {
    border: none;
    padding: 24px;
    box-shadow: 0 12px 32px #1f2a2440;
  }
  dialog:modal::backdrop {
    background-color: #1f2a24b3;
  }
</style>
<button type="button" commandfor="osh" command="show">
  Tez ko'rish
</button>
<button type="button" commandfor="osh" command="show-modal">
  Batafsil
</button>
<dialog id="osh">
  <p>Osh — 35 000 so'm. Guruch, sabzi, qo'y go'shti.</p>
  <form method="dialog"><button>Yopish</button></form>
</dialog>

"Tez ko'rish" oynani tugmalar ostida, oddiy blok sifatida ochadi: ingichka ramka, orqadagi sahifa ishlayveradi. "Batafsil" esa uni top layer'ga chiqaradi: soya, parda, orqa sahifa inert. Oyna oddiy ochiq turganda "Batafsil" bosilsa-chi? Chrome 154 da tekshirdik: oyna modalga aylandi. Boshqa brauzerlarda bu xulq farq qilishi mumkin — ishonchli yo'l: avval yopish. ::backdrop faqat modal oynada chiziladi, shuning uchun dialog:modal::backdrop o'rniga dialog::backdrop yozsa ham natija bir xil — lekin :modal niyatni aniq aytadi.

4-mashq: Portfolio qadami — "Sayt haqida" popover'i

Portfolio'da hali oyna ham, popover ham yo'q. Bosh sahifa footer'iga kichik "Sayt haqida" popover'ini qo'shamiz — portfolio egasi saytni nima bilan yasaganini aytadi. Shu bilan birga butun sayt uchun top layer uslublarini tayyorlaymiz: Modal oyna darsida aloqa sahifasiga birinchi oynani qo'shganingizda ular tayyor bo'ladi.

  1. index.html footer'ida tugma va popover (HTML pastda, yechimda).
  2. asosiy.css ga: popover va modal oyna uchun umumiy ko'rinish — portfolio o'zgaruvchilari bilan (--rang-fon, --rang-matn, --rang-chegara); modal parda — --rang-matn asosida, yarim shaffof.
  3. Ochilish/yopilish — shaffoflik bilan, 0,2 soniya; harakat kamaytirilganda ham shaffoflik qolaversin (u siljish emas).
  4. Popover ichida display ishlatsangiz — faqat ochiq holatda.
  5. Qorong'i rejimda tekshiring (DevTools → Rendering → prefers-color-scheme: dark). So'ng npm run check.

Ishora: parda rangi — color-mix(in oklch, var(--rang-matn) 60%, transparent) (Ranglar 3). Tugma bosilganda popover Esc va tashqariga bosish bilan yopilishini tekshiring.

Yechim

index.html footer'i (Skroll xulqi darsidagi "Yuqoriga" havolasidan keyin):

html
<footer>
  <!-- ... email va Telegram paragrafi o'zgarishsiz ... -->
  <p><a href="#asosiy">Yuqoriga</a></p>
  <p>
    <button type="button" popovertarget="sayt-haqida">
      Sayt haqida
    </button>
  </p>
  <div id="sayt-haqida" popover>
    <p>Bu sayt HTML va CSS bilan qo'lda yozilgan:
       freymvorksiz, JavaScript'siz.</p>
  </div>
  <!-- ... mualliflik paragrafi (small) o'zgarishsiz ... -->
</footer>

asosiy.css ning «Komponentlar» qismiga:

css
/* --- Top layer: popover va modal oyna (Top layer darsi) --- */
[popover],
dialog {
  max-inline-size: min(100% - 2rem, 28rem);
  padding: 1rem 1.25rem;
  border: 1px solid var(--rang-chegara);
  border-radius: 0.5rem;
  background-color: var(--rang-fon);
  color: var(--rang-matn);
  box-shadow: 0 8px 24px
    color-mix(in oklch, var(--rang-matn) 20%, transparent);
}

dialog::backdrop {
  background-color:
    color-mix(in oklch, var(--rang-matn) 60%, transparent);
}

/* Ochilish va yopilish — faqat shaffoflik (harakat emas) */
[popover],
dialog {
  opacity: 0;
  transition:
    opacity 0.2s,
    display 0.2s allow-discrete,
    overlay 0.2s allow-discrete;
}

:popover-open,
dialog[open] {
  opacity: 1;
}

@starting-style {
  :popover-open,
  dialog[open] {
    opacity: 0;
  }
}

/* Popover ichidagi paragraf chetga yopishmasin */
[popover] > p {
  margin: 0;
}
  • display umuman yozilmadi — popover brauzerning display: block i bilan qoladi. Shuning uchun «display tuzog'i» bu yerda xavf emas. Keyinroq grid kerak bo'lsa — :popover-open ga.
  • Shaffoflik harakat emas, u bosh aylantirmaydi — prefers-reduced-motion bloki kerak emas. Harakat etikasi darsidagi "o'chirish emas, almashtirish" ning o'zi.
  • Qorong'i rejimda --rang-fon, --rang-matn va --rang-chegara o'zgaradi — popover ham, parda ham avtomatik moslashadi.
  • min(100% - 2rem, 28rem) — portfolio ustunidagi min(100% - 2rem, 70ch) bilan bir xil g'oya (Yakuniy loyiha). Top layer'da "100%" — ekran eni.
  • Tugma portfolio'ning mavjud tugma stilini oladi (aloqa formasidagi kabi) — alohida bezash shart emas.
  • [popover], dialog ikki qoidaga bo'lindi: biri ko'rinish, biri ochilish. O'qish uchun qulay, lekin selektor takrorlanadi — Stylelint darsida linter buni ushlaydi va ikkalasini bitta qoidaga birlashtiramiz.

html-validate ga e'tibor bering: popover va popovertarget — standart atributlar, xato bermaydi. id="sayt-haqida" kebab-case — id-pattern qoidasidan o'tadi.

9. Real ishda

  • Modal oynalar — tasdiqlash, kirish formasi, rasm galereyasi. Ilgari har loyiha o'z z-index: 9999 li div ini yozardi. Bugun dialog + CSS; kutubxonalar (Radix, shadcn/ui) ham ichkarida shu elementlarga o'tmoqda.
  • Menyular va maslahatlar — popover + Anchor positioning. To'liq komponentlar — Modal oyna va skroll bloklash va Tooltip, dropdown va toast darslarida.
  • Dizayn tizimlarida oyna, popover va parda uchun alohida tokenlar bo'ladi: soya, radius, parda rangi, animatsiya davomiyligi.
  • Intervyuda: "Top layer nima va u z-index dan nimasi bilan farq qiladi?", "Popover nega yopilmayapti?" — endi ikkalasiga ham javob bera olasiz.

Xulosa

  • Top layer — sahifa qatlamlaridan tashqaridagi qavat: modal dialog va popover shu yerga chiqadi, z-index, overflow va transform ularga ta'sir qilmaydi.
  • Brauzer standartlari: markazda (fixed + margin: auto), 3px ramka, oq fon; modal parda — rgba(0, 0, 0, 0.1).
  • ::backdrop — parda: rang va backdrop-filter: blur(). Ochiq holat — [open], :modal, :popover-open.
  • display ni faqat ochiq holatga yozing, aks holda yopiq popover va oyna ko'rinib qoladi.
  • Animatsiya — @starting-style + display/overlay bilan allow-discrete; overlay hozircha faqat Chrome'da.
  • Siljishni harakat kamaytirilganda olib tashlang, shaffoflik qolsin.

Keyingi dars: Anchor positioning — popover va maslahatlarni o'z tugmasi yoniga "bog'lash" va ekranga sig'masa, avtomatik boshqa tomonga o'tkazishni o'rganamiz.

Manbalar

  • MDN: "Top layer", "::backdrop", ":modal", ":popover-open", ":open", "overlay", "@starting-style", "transition-behavior", "backdrop-filter" — developer.mozilla.org
  • HTML Standard: "The dialog element", "The popover attribute" — html.spec.whatwg.org
  • web-features (Baseline ma'lumotlari): "dialog", "popover", "popover-hint", "backdrop", "modal", "open-pseudo", "overlay", "starting-style", "transition-behavior", "backdrop-filter" — github.com/web-platform-dx/web-features
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
CSS top layer: dialog va popover'ni stillash, ::backdrop va animatsiya — IlmHamroh