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

CSS navbar va mobil menyu: yopishqoq header, popover va JavaScript'siz gamburger

Qisqacha: Navbar — kompyuterda bir qatordagi havolalar, telefonda "Menyu" tugmasi ortidagi panel. Bugun buning uchun JavaScript shart emas: nav ga popover atributi, tugmaga popovertarget beriladi — brauzer ochish-yopishni, Esc ni, aria-expanded ni va fokusni o'zi boshqaradi. Keng ekranda media query popover'ni oddiy qatorga aylantiradi. Yopishqoq header — position: sticky + yarim shaffof fon va backdrop-filter, uning ostida sarlavhalar yo'qolmasligi uchun — scroll-padding-top. Ichki menyu — details.

Bu darsda

  • Navbar'ni flex bilan qurasiz va joriy sahifa havolasini faqat rang bilan emas, belgilab ko'rsatasiz.
  • Yopishqoq header'ni shaffof fon va xiralash bilan yozasiz, langar havolalar uning ostida qolmasligini ta'minlaysiz.
  • Telefonda "Menyu" tugmasi bilan ochiladigan yon panelni JavaScript'siz, popover bilan quring va uni kompyuterda oddiy qatorga aylantirasiz.
  • Gamburger menyuning boshqa usullarini (JavaScript, checkbox hiylasi, details) solishtirib, qaysi birini qachon tanlashni bilasiz.
  • Ichki menyu va telefondagi pastki panelning CSS tomonini yozasiz.

Oldin bilishingiz kerak: Flex naqshlari, position: fixed va sticky, Mobil qurilma tuzoqlari, Top layer, Popover API.

1. Nega bu kerak?

O'tgan darsda kartalar bilan ishladik. Endi saytning eng tepasiga chiqamiz — har sahifada bor, har mehmon birinchi ko'radigan komponentga.

«Bahor» menyusida to'rtta havola: Bosh sahifa, Menyu, Blog, Aloqa. Kompyuterda ular bir qatorga bemalol sig'adi. Telefonda esa ikki qatorga o'tib, ekranning yuqori qismini egallaydi. Bundan tashqari, mehmon menyu sahifasini pastga surib ketsa, yuqoriga qaytish uchun uzoq aylantiradi.

Bu mavzuda oldingi darslar ko'p va'da bergan:

  1. Flex naqshlari darsida: "gamburger tugmasi bilan ochiladigan to'liq mobil menyu JavaScript va boshqa vositalarni talab qiladi". Bugun ko'rasiz — endi talab qilmaydi.
  2. Intrinsic layout darsida: telefonda menyuni tugma ortiga yashirish.
  3. position: fixed va sticky darsida: surganda yashirinib, tepaga surganda qaytadigan header.
  4. Kirish va chiqish animatsiyalari darsida: faqat hover'da ochiladigan menyu o'rniga accessible navbar.
  5. UI/UX asoslari darsida: telefondagi pastki panelning CSS tomoni.

2. Asos: flex navbar

2.1 Tuzilma

«Bahor» header'i Ko'p sahifali sayt darsidan beri o'zgarmagan: logotip havolasi va nav ichidagi ro'yxat. Joylashuv — Flex naqshlari darsidagi "logotip chapda, menyu o'ngda": justify-content: space-between va flex-wrap.

2.2 Joriy sahifa

Mehmon qaysi sahifada turganini bilishi kerak. HTML buni aria-current="page" bilan aytadi (Ko'p sahifali sayt), ekran o'quvchi "joriy sahifa" deb e'lon qiladi. CSS esa shu atributni selektor qiladi (Atribut selektorlari):

css
nav[aria-label="Asosiy menyu"] [aria-current="page"] {
  color: var(--rang-asosiy);
  font-weight: bold;
  text-decoration: underline 2px;
  text-underline-offset: 0.3em;
}

Faqat rang yetmaydi: rangni ajratmaydigan odam uchun qalinlik va chiziq ham bor (Rang nazariyasi darsidagi WCAG 1.4.1). Alohida .aktiv class'i kerak emas — HTML'dagi atribut ma'lumotning yagona manbai.

3. Yopishqoq header

3.1 Sticky + shaffof fon + xiralash

Header surilganda ham tepada tursin — position: sticky; top: 0 (position: fixed va sticky). Zamonaviy saytlarda uning foni yarim shaffof: ostidan o'tayotgan kontent biroz ko'rinadi, lekin xiralashgan — matn baribir o'qiladi. Bu backdrop-filter — element ortidagi narsaga filtr (Filterlar).

html
<style>
  :root {
    --rang-fon: #fffaf0;
    --rang-matn: #1f2a24;
    --rang-asosiy: #2f6b3a;
  }
  html { scroll-padding-block-start: 4rem; }
  body {
    margin: 0;
    font-family: system-ui, sans-serif;
    background: var(--rang-fon);
    color: var(--rang-matn);
  }
  header {
    position: sticky;
    inset-block-start: 0;
    z-index: 10;
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    gap: 0.5rem 1rem;
    padding: 0.5rem 1rem;
    border-block-end: 1px solid #c9d6cf;
    background: color-mix(in oklch, var(--rang-fon) 80%, transparent);
    backdrop-filter: blur(8px);
  }
  @supports not (backdrop-filter: blur(1px)) {
    header { background: var(--rang-fon); }
  }
  header > a {
    color: var(--rang-asosiy);
    font-weight: bold;
    text-decoration: none;
  }
  nav ul {
    display: flex;
    gap: 1rem;
    margin: 0;
    padding: 0;
    list-style: none;
  }
  nav a { color: inherit; }
  section { padding: 1rem; }
  section:last-child { min-block-size: 30rem; }
  section h2 { margin-block-start: 0; color: var(--rang-asosiy); }
  .chiziqli {
    block-size: 12rem;
    background: repeating-linear-gradient(135deg,
      #f2c46d 0 1rem, #2f6b3a 1rem 2rem);
  }
</style>
<header>
  <a href="#bosh">Choyxona «Bahor»</a>
  <nav aria-label="Asosiy menyu">
    <ul>
      <li><a href="#menyu">Menyu</a></li>
      <li><a href="#aloqa">Aloqa</a></li>
    </ul>
  </nav>
</header>
<section id="bosh">
  <h2>Xush kelibsiz</h2>
  <div class="chiziqli"></div>
</section>
<section id="menyu">
  <h2>Menyu</h2>
  <p>Osh — 35 000, lag'mon — 28 000, manti — 30 000 so'm.</p>
  <div class="chiziqli"></div>
</section>
<section id="aloqa">
  <h2>Aloqa</h2>
  <p>Telefon: +998 90 000 00 00. Har kuni 7:00–23:00.</p>
  <div class="chiziqli"></div>
</section>

Nimaga qarang: natija oynasini pastga suring. Header tepada qoladi, uning ostidan sariq-yashil chiziqlar o'tadi — ular ko'rinadi, lekin xira va rangi so'ngan. "Choyxona «Bahor»" yozuvi baribir aniq o'qiladi. Endi "Aloqa" havolasini bosing: oyna "Aloqa" bo'limiga sakraydi va sarlavha header ostida emas, undan pastda to'liq ko'rinadi.

  • color-mix(... 80%, transparent) — fon rangining 80% i (Ranglar 3). Juda shaffof fon (masalan 30%) ustida matn o'qilmay qoladi — ostidan yorqin rasm o'tsa, kontrast yo'qoladi. 80% + xiralash — xavfsiz o'rtacha.
  • backdrop-filter: blur(8px) — Baseline ma'lumotiga ko'ra yangi Baseline (2024-yil sentabr): eski brauzerlarda ishlamaydi. Shuning uchun @supports not bilan zaxira: xiralash yo'q bo'lsa, fon to'liq qaymoq — shaffof fon ustida matn aralashib ketmasin (Brauzer mosligi).
  • z-index: 10 — «Bahor» qatlamlaridagi --qatlam-yopishqoq qiymati (z-index). Karta hover'da ko'tarilsa ham, header ostida qoladi.

3.2 scroll-padding-top: sarlavha header ostida qolmasin

Langar havolasini bosganda brauzer nishonni oynaning eng tepasiga olib keladi. Lekin tepada yopishqoq header turibdi — sarlavha uning ostida qoladi. Skroll xulqi darsida ko'rgan scroll-padding bu yerda yordam beradi: skroll konteyneri (html) ga "tepadan 4rem joy qoldir" deymiz.

Chrome'da o'lchadik (natija oynasi 400 piksel): "Aloqa" bosilgandan keyin bo'lim oyna tepasidan 64 piksel pastdan boshlanadi, sarlavha esa 80 pikselda. Header balandligi 38 piksel — sarlavha to'liq ko'rinadi. scroll-padding siz bo'lim eng tepadan boshlandi va sarlavha 16 pikselda — header ostida qolib ketdi.

scroll-padding-block-start — scroll-padding-top ning mantiqiy nomi (Mantiqiy xususiyatlar). Header balandligi o'zgarsa (masalan, telefonda ikki qatorga o'tsa), qiymatni ham moslang. Aniqroq yo'l — balandlikni o'zgaruvchiga olish: header { min-block-size: var(--header-balandlik); } va html { scroll-padding-block-start: var(--header-balandlik); }.

Tekshirib ko'ring: Header 56 piksel. scroll-padding-top: 56px yozildi. Sarlavha header'ga yopishib turibdi — "nafas olmayapti". Nima qilasiz?

Javob

Header balandligiga biroz joy qo'shing: calc(56px + 1rem) yoki 4.5rem. Nishon header ostidan emas, undan biroz pastdan boshlansin. Yoki nishonning o'ziga scroll-margin-top: 1rem bering (Skroll xulqi) — u faqat shu elementga ta'sir qiladi.

3.3 Surganda yashirinadigan header

position: fixed va sticky darsida bergan va'da: pastga surganda header yashirinsin, tepaga surganda qaytsin — telefonda ekran joyini tejaydi. CSS tomoni oddiy — bitta atribut va translate:

css
header[data-yashirin] {
  translate: 0 -100%;
}

@media (prefers-reduced-motion: no-preference) {
  header {
    transition: translate 0.25s ease-out;
  }
}

Lekin qaysi tomonga surilayotganini bilish — skroll yo'nalishini kuzatish. Buni JavaScript qiladi: u data-yashirin atributini qo'yadi va olib tashlaydi. JavaScript'ni 08-qismdan o'rganasiz; atributlar bilan ishlash — Atributlar va dataset darsida. CSS'da hozircha yagona yo'l yo'q: Chrome'da tajribaviy scroll-state so'rovlari bor, lekin ular Baseline emas (faqat Chrome va Edge).

4. Telefonda: "Menyu" tugmasi

4.1 To'rt usul

Menyuni tugma ortiga yashirishning to'rt yo'li bor. Ularni solishtiramiz:

Usul JavaScript Esc, tashqariga bosish Ekran o'quvchi
Tugma + aria-expanded + skript Kerak Skript yozadi To'g'ri, agar skript to'g'ri
Checkbox hiylasi Yo'q Yo'q "Belgilash katakchasi" — noto'g'ri
details Yo'q Yo'q "Yoyiladigan tugma" — yaxshi
Popover Yo'q Brauzer o'zi "Tugma, yig'ilgan/yoyilgan" — to'g'ri

Checkbox hiylasi — eski usul: yashirin input type="checkbox" va uning label i "tugma" vazifasini bajaradi, CSS esa :checked ~ nav bilan menyuni ko'rsatadi. JavaScript'siz ishlaydi, lekin ekran o'quvchi "belgilash katakchasi, belgilanmagan" deydi — Malika menyu tugmasini topa olmaydi. label ga Tab bilan borilmaydi, Esc ishlamaydi. Uni eski kodlarda uchratasiz — o'zingiz yozmang.

details (details va summary) yaxshiroq: summary — haqiqiy tugma, ochiq/yopiq holatni ekran o'quvchi aytadi. Lekin u tashqariga bosganda va Esc da yopilmaydi, menyu esa sahifa oqimida — ochilganda kontentni pastga suradi. Kichik ichki menyular uchun juda yaxshi (buni pastda ko'ramiz).

Popover esa aynan menyu uchun yaratilgan. Popover API darsidan eslang: tugma popovertarget bilan popover'ni ochadi va yopadi. Chrome'da tekshirdik:

  • tugma accessibility daraxtida (ekran o'quvchi ko'radigan tuzilmada) expanded: false, ochilgandan keyin expanded: true — aria-expanded ni brauzer o'zi qo'ydi;
  • ochilgandan keyin Tab fokusni to'g'ridan-to'g'ri menyuning birinchi havolasiga olib bordi — garchi nav HTML'da uzoqda bo'lsa ham;
  • Esc menyuni yopdi va fokus tugmaga qaytdi.

Bularning hammasini skript bilan yozish — o'nlab qator va o'nlab tuzoq. Popover — yangi Baseline: Baseline ma'lumotiga ko'ra popover atributi 2025-yil yanvaridan, uning CSS tomoni (:popover-open) 2024-yil aprelidan hamma asosiy brauzerda. Eski brauzerda yo'q — u holda nima bo'lishini pastda ko'ramiz.

4.2 Popover menyu: telefonda yon panel, kompyuterda qator

Bitta HTML, ikki ko'rinish. Telefonda menyu o'ngdan chiqadigan panel (off-canvas — "ekran tashqarisidan kiradigan"), kompyuterda oddiy qator:

html
<style>
  :root {
    --rang-fon: #fffaf0;
    --rang-matn: #1f2a24;
    --rang-asosiy: #2f6b3a;
    --rang-asosiy-toq: #1a5d1a;
  }
  * { box-sizing: border-box; }
  body {
    margin: 0;
    font-family: system-ui, sans-serif;
    background: var(--rang-fon);
    color: var(--rang-matn);
  }
  header {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    gap: 0.5rem 1rem;
    padding: 0.5rem 1rem;
    border-block-end: 1px solid #c9d6cf;
  }
  header > a {
    color: var(--rang-asosiy);
    font-weight: bold;
    text-decoration: none;
  }
  header button {
    display: inline-flex;
    align-items: center;
    gap: 0.5em;
    min-block-size: 2.75rem;
    padding: 0 1em;
    border: 2px solid var(--rang-asosiy);
    border-radius: 0.5rem;
    background: transparent;
    color: var(--rang-asosiy);
    font: inherit;
    font-weight: 600;
  }
  .sprite { display: none; }
  .ikonka {
    flex: none;
    inline-size: 1.25em;
    block-size: 1.25em;
    fill: currentColor;
  }
  :focus-visible {
    outline: 3px solid var(--rang-asosiy-toq);
    outline-offset: 2px;
    box-shadow: 0 0 0 2px var(--rang-fon);
  }
  main { padding-inline: 1rem; }
  nav ul { margin: 0; padding: 0; list-style: none; }
  nav a {
    display: block;
    padding: 0.75rem 1rem;
    border-radius: 0.5rem;
    color: inherit;
    text-decoration: none;
  }
  nav [aria-current="page"] {
    color: var(--rang-asosiy);
    font-weight: bold;
    text-decoration: underline 2px;
    text-underline-offset: 0.3em;
  }
  /* Telefon: menyu — o'ngdan chiqadigan panel */
  #asosiy-menyu {
    inset: 0 0 0 auto;
    inline-size: min(18rem, 85%);
    block-size: 100%;
    margin: 0;
    padding: 1rem;
    border: 0;
    background: var(--rang-fon);
    color: var(--rang-matn);
    box-shadow: -8px 0 24px #1f2a2440;
  }
  #asosiy-menyu::backdrop { background: #1f2a2466; }
  #asosiy-menyu [popovertargetaction="hide"] {
    margin-block-end: 1rem;
  }
  @media (prefers-reduced-motion: no-preference) {
    #asosiy-menyu {
      translate: 100% 0;
      transition:
        translate 0.25s ease-out,
        display 0.25s allow-discrete,
        overlay 0.25s allow-discrete;
    }
    #asosiy-menyu:popover-open { translate: 0 0; }
    @starting-style {
      #asosiy-menyu:popover-open { translate: 100% 0; }
    }
  }
  /* Kompyuter: menyu doim ko'rinadi, qatorda */
  @media (width >= 40rem) {
    header button { display: none; }
    #asosiy-menyu {
      display: block;
      position: static;
      inline-size: auto;
      block-size: auto;
      padding: 0;
      background: none;
      box-shadow: none;
      translate: none;
    }
    #asosiy-menyu ul { display: flex; gap: 0.25rem; }
    #asosiy-menyu a { padding: 0.5rem 0.75rem; }
  }
</style>
<svg class="sprite">
  <symbol id="i-menyu" viewBox="0 0 24 24" fill="none"
    stroke="currentColor" stroke-width="2">
    <path d="M4 7h16M4 12h16M4 17h16" />
  </symbol>
</svg>
<header>
  <a href="#bosh">Choyxona «Bahor»</a>
  <button type="button" popovertarget="asosiy-menyu">
    <svg class="ikonka" aria-hidden="true">
      <use href="#i-menyu"/></svg>
    Menyu
  </button>
  <nav id="asosiy-menyu" aria-label="Asosiy menyu" popover>
    <button type="button" popovertarget="asosiy-menyu"
      popovertargetaction="hide">Yopish</button>
    <ul>
      <li><a href="#bosh" aria-current="page">Bosh sahifa</a></li>
      <li><a href="#menyu">Menyu</a></li>
      <li><a href="#blog">Blog</a></li>
      <li><a href="#aloqa">Aloqa</a></li>
    </ul>
  </nav>
</header>
<main id="bosh">
  <p>1998-yildan beri Chilonzorda.</p>
</main>

Nimaga qarang: telefon enida (360) header'da logotip va " Menyu" tugmasi. Tugmani bosing — o'ng tomondan qaymoq panel suzib kiradi, orqadagi sahifa qorayadi. Panelda "Yopish" tugmasi va to'rt havola, "Bosh sahifa" qalin va tagiga chizilgan. Pardaga bosing yoki Esc — panel o'ngga qaytib ketadi. Kompyuter enida (768, 1280) tugma yo'q, havolalar logotip bilan bir qatorda.

Chrome'da ikkala enda tekshirdik: 360 da tugma bosilgach, panel translate i 0,25 soniyada 100% dan 0 ga keldi, eni — 288 piksel (18rem). 800 da nav hisoblangan position i static, havolalar bir qatorda.

Bitta g'alati holat: natijadagi ekran tugmalari bilan kompyuterdan telefonga o'tsangiz, panel bir lahza ko'rinib, o'ngga suzib ketadi. Bu display ning chorak soniyalik o'tishi — qator endi yopiq popover bo'ldi va "yopilish animatsiyasi" ishladi. Sahifani telefonda to'g'ridan-to'g'ri ochgan mehmon buni ko'rmaydi: 360 enida yuklanganda panel darhol display: none.

4.3 Kodni o'qiymiz

Telefon holati. Popover brauzerning o'z stillari bilan keladi: position: fixed, inset: 0, margin: auto — ya'ni ekran o'rtasida (Top layer). Biz ularni qayta yozdik:

  • inset: 0 0 0 auto — tepa, o'ng, past — 0; chap — auto. Panel o'ng chetga yopishadi.
  • block-size: 100% — top layer'da "100%" — ekran balandligi. inline-size: min(18rem, 85%) — telefonda ekranning 85% idan oshmaydi, chapda sahifa bir chetgina ko'rinib turadi: foydalanuvchi "bu ustidagi panel" ekanini tushunadi.
  • Animatsiya — Top layer darsidagi andoza: @starting-style (yangi Baseline, 2024-yil avgust) + display/overlay bilan allow-discrete. Faqat no-preference ichida: harakat kamaytirilganda panel darhol paydo bo'ladi. Eski brauzerda ham shunday — animatsiyasiz, lekin ishlaydi.
  • "Yopish" tugmasi — popovertargetaction="hide": faqat yopadi. Ko'rinadigan yopish tugmasi Esc ni bilmaydigan va pardaga bosishni kutmaydigan foydalanuvchi uchun.

Kompyuter holati. Mana eng qiziq joy. Top layer darsida "popover'ga display bersangiz, u yopiq holatda ham ko'rinib qoladi" deb ogohlantirgan edik. Bu tuzoq edi — bugun esa aynan shu xulqdan foydalanamiz. Keng ekranda #asosiy-menyu { display: block; position: static; } yozildi. Muallif stili brauzerning [popover]:not(:popover-open) { display: none } qoidasidan yutadi (Kaskad) — yopiq popover oddiy blok bo'lib, header oqimida turadi. position: static uni fixed dan qaytaradi, qolgan qatorlar brauzer bergan ramka, fon va hoshiyani olib tashlaydi.

Popover'ni bilmaydigan brauzer popover atributini tanimaydi. Unda yashirish qoidasi ham yo'q — menyu telefonda ham oddiy ro'yxat bo'lib ko'rinadi. Tugma esa hech narsa qilmaydi. Sahifa baribir ishlaydi: bu Brauzer mosligi darsidagi progressive enhancement.

Diqqat: Telefonda popover'da translate: 100% 0 — yopiq panelning "boshlang'ich" holati. Kompyuter qoidasida translate: none yozilmasa, no-preference blokidagi qiymat keng ekranda ham ishlaydi va qatordagi menyu ekrandan o'ngga chiqib ketadi. Chrome'da tekshirdik: translate: none siz 1280 da birinchi havola 1264-pikseldan boshlandi — menyu deyarli butunlay ekrandan o'ngga chiqib ketdi.

Tekshirib ko'ring: Keng ekran blokidan display: block qatorini o'chirib qo'ydingiz. Kompyuterda menyu nima bo'ladi?

Javob

Menyu yo'qoladi. Popover yopiq bo'lsa, brauzer uni display: none bilan yashiradi. Kompyuterda tugma ham yashirin — menyuni ochishning yo'li qolmaydi. Aynan display: block yopiq popover'ni oddiy blokka aylantirib, qatorda ko'rsatadi.

4.4 inert: yashirin menyu Tab da qolmasin

Ba'zi saytlar yon panelni popover'siz qiladi: panel doim DOM'da (sahifa tuzilmasida), yopiq holatda translate: 100% bilan ekrandan tashqarida. Ko'zga ko'rinmaydi — lekin klaviatura uni ko'radi. Bobur Tab bosadi va fokus ko'rinmas panel havolalariga ketadi — ekranda fokus "yo'qoladi".

Yechim — inert atributi (Global atributlar): u elementni fokus, bosish va ekran o'quvchidan butunlay chiqaradi. Uni panel yopilganda JavaScript qo'yadi. CSS'da esa visibility: hidden ham xuddi shu ishni qiladi — ko'rinmas element Tab tartibidan chiqadi. Popover yo'lida bu muammo umuman yo'q: yopiq popover display: none.

5. Ichki menyu: details

"Menyu" havolasi ostida bo'limlar bor: issiq taomlar, salatlar, ichimliklar (Sahifa ichidagi havolalar darsidagi langarlar). Ular uchun ochiladigan ichki menyu (dropdown):

html
<style>
  :root {
    --rang-fon: #fffaf0;
    --rang-matn: #1f2a24;
    --rang-asosiy: #2f6b3a;
    --rang-asosiy-toq: #1a5d1a;
  }
  body {
    font-family: system-ui, sans-serif;
    background: var(--rang-fon);
    color: var(--rang-matn);
  }
  nav > ul {
    display: flex;
    gap: 0.25rem;
    margin: 0;
    padding: 0;
    list-style: none;
  }
  nav a, nav summary {
    display: block;
    padding: 0.5rem 0.75rem;
    border-radius: 0.5rem;
    color: inherit;
    text-decoration: none;
    cursor: pointer;
  }
  nav summary { list-style: none; }
  nav summary::-webkit-details-marker { display: none; }
  nav summary::after {
    content: "▾" / "";
    display: inline-block;
    margin-inline-start: 0.25em;
  }
  nav details[open] > summary::after { rotate: 180deg; }
  nav details { position: relative; }
  nav details ul {
    position: absolute;
    inset-block-start: 100%;
    inset-inline-start: 0;
    z-index: 20;
    min-inline-size: 12rem;
    margin: 0.25rem 0 0;
    padding: 0.25rem;
    list-style: none;
    border: 1px solid #c9d6cf;
    border-radius: 0.5rem;
    background: var(--rang-fon);
    box-shadow: 0 8px 24px #1f2a2433;
  }
  nav :focus-visible {
    outline: 3px solid var(--rang-asosiy-toq);
    outline-offset: 2px;
    box-shadow: 0 0 0 2px var(--rang-fon);
  }
</style>
<nav aria-label="Asosiy menyu">
  <ul>
    <li><a href="#bosh">Bosh sahifa</a></li>
    <li>
      <details name="ichki-menyu">
        <summary>Menyu</summary>
        <ul>
          <li><a href="#issiq-taomlar">Issiq taomlar</a></li>
          <li><a href="#salatlar">Salatlar</a></li>
          <li><a href="#ichimliklar">Ichimliklar</a></li>
        </ul>
      </details>
    </li>
    <li><a href="#aloqa">Aloqa</a></li>
  </ul>
</nav>
<p>Sahifa matni: menyu ochilganda bu qator joyidan siljimaydi.</p>

Nimaga qarang: "Menyu ▾" ni bosing — ostida uchta havolali quti ochiladi, strelka tepaga buriladi. Quti sahifa matni ustida turadi, pastdagi paragraf joyidan qimirlamaydi. Yana bosing — yopiladi. Klaviaturada: Tab bilan "Menyu" ga boring, Enter yoki Space — ochiladi, keyingi Tab — ichki havolalar.

  • position: absolute + inset-block-start: 100% — quti summary ning ostida, details ga nisbatan (position). Sahifa oqimidan chiqqani uchun matnni surmaydi. z-index: 20 — «Bahor»dagi --qatlam-menyu.
  • Marker — list-style: none va ::-webkit-details-marker ikkalasi: birinchisi standart, ikkinchisi eski Safari uchun (Ro'yxatlar stili). O'rniga ::after dagi "▾" — muqobil matni bo'sh (/ ""), chunki ochiq-yopiqligini ekran o'quvchiga summary ning o'zi aytadi.
  • cursor: pointer — summary bosiladigan ekanini sichqonchada ko'rsatadi. cursor Baseline emas (telefonda kursor yo'q) — zaxira kerak emas.
  • name="ichki-menyu" — bir xil nomli details lardan faqat bittasi ochiq turadi (details va summary). Navbar'da ikkita ichki menyu bo'lsa, ikkinchisi ochilganda birinchisi o'zi yopiladi.

Chegaralari: details tashqariga bosganda va Esc da yopilmaydi. Mehmon havolani bosib boshqa sahifaga o'tsa — muammo yo'q, yangi sahifada menyu yopiq. Lekin langar havolalar (#salatlar) sahifani almashtirmaydi va menyu ochiq qoladi. Shunday joylarda popover yaxshiroq: ichki menyu ham popover bo'lishi mumkin, uni tugma yoniga Anchor positioning bog'laydi. To'liq dropdown komponentini Tooltip, dropdown va toast darsida quramiz.

Diqqat: Faqat :hover bilan ochiladigan ichki menyu yozmang (Kirish va chiqish animatsiyalari darsidagi ogohlantirish). Telefonda hover yo'q, klaviatura va ekran o'quvchi uni ocholmaydi. Hover — faqat qo'shimcha; asosiy yo'l — bosish.

Tekshirib ko'ring: Ichki menyu qutisiga position: absolute o'rniga hech narsa yozilmasa, "Menyu ▾" ochilganda pastdagi paragraf nima bo'ladi?

Javob

Paragraf pastga suriladi. position: absolute siz ro'yxat sahifa oqimida qoladi va o'z balandligicha joy egallaydi. absolute uni oqimdan chiqaradi — quti matn ustida suzadi, boshqa narsalar joyidan qimirlamaydi.

6. Telefonda pastki panel

Ilovalarga o'xshash saytlarda asosiy havolalar ekranning pastida — bosh barmoq yetadigan joyda (UI/UX asoslari darsidagi Fitts qonuni). CSS tomoni:

html
<style>
  :root {
    --rang-fon: #fffaf0;
    --rang-matn: #1f2a24;
    --rang-asosiy: #2f6b3a;
    --panel: 3.5rem;
  }
  body {
    margin: 0;
    padding-block-end:
      calc(var(--panel) + env(safe-area-inset-bottom, 0px));
    font-family: system-ui, sans-serif;
    background: var(--rang-fon);
    color: var(--rang-matn);
  }
  main { padding: 1rem; }
  .pastki-panel ul {
    position: fixed;
    inset-inline: 0;
    inset-block-end: 0;
    z-index: 10;
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    margin: 0;
    padding: 0 0 env(safe-area-inset-bottom, 0px);
    list-style: none;
    border-block-start: 1px solid #c9d6cf;
    background: var(--rang-fon);
  }
  .pastki-panel a {
    display: grid;
    justify-items: center;
    align-content: center;
    min-block-size: var(--panel);
    font-size: 0.75rem;
    color: inherit;
    text-decoration: none;
  }
  .pastki-panel [aria-current="page"] {
    color: var(--rang-asosiy);
    font-weight: bold;
  }
  .sprite { display: none; }
  .ikonka {
    inline-size: 1.5rem;
    block-size: 1.5rem;
    fill: currentColor;
  }
  @media (width >= 40rem) {
    .pastki-panel { display: none; }
    body { padding-block-end: 0; }
  }
</style>
<main>
  <h1>Choyxona «Bahor»</h1>
  <p>Telefonda asosiy havolalar pastda turadi.</p>
</main>
<svg class="sprite">
  <symbol id="i-uy" viewBox="0 0 24 24" fill="none"
    stroke="currentColor" stroke-width="2">
    <path d="M4 11l8-7 8 7v9h-5v-6H9v6H4z" />
  </symbol>
  <symbol id="i-menyu" viewBox="0 0 24 24" fill="none"
    stroke="currentColor" stroke-width="2">
    <path d="M5 6h14M5 12h14M5 18h14" />
  </symbol>
  <symbol id="i-taqvim" viewBox="0 0 24 24" fill="none"
    stroke="currentColor" stroke-width="2">
    <rect x="4" y="5" width="16" height="15" rx="2" />
    <path d="M4 10h16M9 3v4M15 3v4" />
  </symbol>
</svg>
<nav class="pastki-panel" aria-label="Tezkor havolalar">
  <ul>
    <li><a href="#bosh" aria-current="page">
      <svg class="ikonka" aria-hidden="true">
        <use href="#i-uy"/></svg>Bosh sahifa</a></li>
    <li><a href="#menyu">
      <svg class="ikonka" aria-hidden="true">
        <use href="#i-menyu"/></svg>Menyu</a></li>
    <li><a href="#bron">
      <svg class="ikonka" aria-hidden="true">
        <use href="#i-taqvim"/></svg>Bron</a></li>
  </ul>
</nav>

Nimaga qarang: telefon enida (360) ekranning pastida uchta teng katak: uy, ro'yxat va taqvim belgilari, ostida yozuvlari. "Bosh sahifa" yashil va qalin. Kompyuter enida panel yo'q.

  • position: fixed + inset-block-end: 0 — ekran pastiga mixlangan (position: fixed va sticky).
  • body ning pastki hoshiyasi panel balandligiga teng — aks holda sahifaning oxirgi qatori panel ostida qolib ketadi.
  • env(safe-area-inset-bottom) — iPhone'ning pastidagi "uy chizig'i" uchun joy (Mobil qurilma tuzoqlari). U faqat <meta name="viewport" content="..., viewport-fit=cover"> bo'lganda noldan katta bo'ladi; boshqa qurilmalarda — 0px zaxirasi. Safe area o'zgaruvchilari Baseline, 2020-yildan.
  • Belgi + so'z — faqat belgi emas. Uy belgisi hamma uchun tushunarli, taqvim esa "bron" ekanini aytmaydi.
  • pastki-panel — namoyish class'i. Bu naqsh «Bahor»ga qo'shilmaydi: to'rt havolali oddiy sayt uchun tepadagi menyu yetarli. Pastki panel — ko'p ishlatiladigan ilovasimon saytlarniki (do'kon, bank, taksi).

7. «Bahor»ning komponentlar.css iga

HTML'da ikki qo'shimcha: tugma va nav ga id + popover («Popover menyu» bo'limidagi kabi). CSS:

css
/* === Header va navbar (Navbar va mobil menyu darsi) === */
body > header {
  position: sticky;
  inset-block-start: 0;
  z-index: var(--qatlam-yopishqoq);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--masofa-xs) var(--masofa-m);
  padding: var(--masofa-xs) var(--masofa-m);
  border-block-end: 1px solid
    color-mix(in oklch, var(--rang-asosiy) 25%, var(--rang-fon));
  background: var(--rang-fon);
}

@supports (backdrop-filter: blur(1px)) {
  body > header {
    background: color-mix(in oklch, var(--rang-fon) 80%, transparent);
    backdrop-filter: blur(8px);
  }
}

nav[aria-label="Asosiy menyu"] a {
  display: block;
  padding: var(--masofa-s) var(--masofa-m);
  border-radius: var(--burchak-m);
  color: inherit;
  text-decoration: none;
}

nav[aria-label="Asosiy menyu"] [aria-current="page"] {
  color: var(--rang-asosiy);
  font-weight: bold;
  text-decoration: underline 2px;
  text-underline-offset: 0.3em;
}

/* Telefon: yon panel */
#asosiy-menyu {
  inset: 0 0 0 auto;
  inline-size: min(18rem, 85%);
  block-size: 100%;
  margin: 0;
  padding: var(--masofa-m);
  border: 0;
  background: var(--rang-yuza);
  color: var(--rang-matn);
  box-shadow: var(--soya-3);
}

/* Ro'yxatning brauzer margin'i va chekinishi — nolga */
#asosiy-menyu ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

#asosiy-menyu::backdrop {
  background: color-mix(in oklch, var(--rang-matn) 40%, transparent);
}

@media (prefers-reduced-motion: no-preference) {
  #asosiy-menyu {
    translate: 100% 0;
    transition:
      translate 0.25s ease-out,
      display 0.25s allow-discrete,
      overlay 0.25s allow-discrete;
  }

  #asosiy-menyu:popover-open {
    translate: 0 0;
  }

  @starting-style {
    #asosiy-menyu:popover-open {
      translate: 100% 0;
    }
  }
}

/* Kompyuter: oddiy qator */
@media (width >= 40rem) {
  body > header [popovertarget="asosiy-menyu"] {
    display: none;
  }

  #asosiy-menyu {
    display: block;
    position: static;
    inline-size: auto;
    block-size: auto;
    padding: 0;
    background: none;
    box-shadow: none;
    translate: none;
  }

  #asosiy-menyu ul {
    display: flex;
    gap: var(--masofa-2xs);
  }

  #asosiy-menyu a {
    padding: var(--masofa-xs) var(--masofa-s);
  }
}

asos.css ga — sarlavhalar header ostida qolmasin:

css
html {
  scroll-padding-block-start: 5rem;
}
  • Tugmaning o'zi — Tugmalar tizimi dagi class="tugma ikkinchi", belgisi — sprite'dagi i-menyu va .ikonka (SVG va ikonka tizimi); bu yerda faqat keng ekranda yashirish qoidasi. Fokus halqasi — asos.css dagi umumiy ikki rangli qoida (CSS'da accessibility).
  • #asosiy-menyu ul da margin: 0 — natijalardagi nav ul qoidasining o'rni. Busiz brauzerning 16 piksellik tepa va pastki margin'i qoladi: Chrome'da o'lchadik, 1280 pikselda header 36 piksel balandroq chiqdi.
  • body > header — faqat sahifa header'i. article ichidagi header (blog maqolasida bor) yopishqoq bo'lib qolmasin.
  • --rang-yuza va --soya-3 — panel "eng baland" qatlamda (Dizayn tokenlari), qorong'i rejimda o'zi moslashadi.
  • Qorong'i rejimda shaffof fon ham to'g'ri: --rang-fon qorong'i yashil, 80% i ham qorong'i.

8. Ko'p uchraydigan xatolar

8.1 Faqat belgili gamburger

"" belgisini hamma ham menyu deb tanimaydi, ayniqsa katta yoshdagilar. Tuzatish: belgi + "Menyu" so'zi. Joy yetmasa — kamida aria-label="Menyu".

8.2 Keng ekranda panel "qochib ketdi"

Kompyuter qoidasida telefondagi translate yoki position bekor qilinmagan. Tuzatish: keng ekran bloki popover'ning hamma o'zgartirilgan xususiyatini qaytarsin: position: static, translate: none, o'lcham, fon, soya.

8.3 Langar sarlavhasi header ostida

Yopishqoq header bor, scroll-padding yo'q. Tuzatish: html { scroll-padding-block-start: ... } — header balandligi va biroz zaxira.

8.4 Checkbox hiylasi

Ekran o'quvchi "belgilash katakchasi" deydi, Esc ishlamaydi. Tuzatish: popover yoki details.

8.5 Juda shaffof header

background: transparent + backdrop-filter — ostidan yorqin rasm o'tganda matn o'qilmay qoladi. Tuzatish: fon kamida 75–85% qoplamali, backdrop-filter yo'q bo'lsa — to'liq.

9. Mashqlar

Mashqlarni kurs/mashqlar/06/ papkasida bajaring.

1-mashq (oson): joriy sahifa belgisi

Navbar'da joriy sahifa havolasi ostida chiziq o'rniga 3 piksellik yashil "tasma" bo'lsin — havola eni bo'ylab, matndan 4 piksel pastda. Rangni ajratmaydigan odam ham farqni ko'rsin.

Ishora: box-shadow: inset 0 -3px yoki ::after + position: absolute (Pseudo-elementlar). Havolada padding bo'lsa, tasma padding'ning pastida chiziladi.

Yechim
html
<style>
  body { font-family: system-ui, sans-serif; background: #fffaf0; }
  nav ul {
    display: flex;
    gap: 0.25rem;
    margin: 0;
    padding: 0;
    list-style: none;
  }
  nav a {
    display: block;
    padding: 0.5rem 0.75rem 0.25rem;
    color: #1f2a24;
    text-decoration: none;
  }
  nav [aria-current="page"] {
    color: #2f6b3a;
    font-weight: bold;
    box-shadow: inset 0 -3px #2f6b3a;
  }
</style>
<nav aria-label="Asosiy menyu">
  <ul>
    <li><a href="#bosh">Bosh sahifa</a></li>
    <li><a href="#menyu" aria-current="page">Menyu</a></li>
    <li><a href="#aloqa">Aloqa</a></li>
  </ul>
</nav>

"Menyu" yashil, qalin, ostida havola eni bo'ylab tasma. box-shadow: inset 0 -3px — ichki soya faqat pastdan, xiralashtirishsiz: to'g'ri chiziq. padding-bottom (0.25rem = 4 piksel) matn va tasma orasidagi masofa. Ichki soya havola o'lchamini o'zgartirmaydi — boshqa havolalar bilan bir qatorda turadi.

2-mashq (o'rta): menyu tepadan tushsin

«Popover menyu: telefonda yon panel, kompyuterda qator» bo'limidagi menyuni o'zgartiring: telefonda panel o'ngdan emas, tepadan tushsin va butun enni egallasin (balandligi — kontentiga qarab). Harakat kamaytirilganda — shaffoflik bilan paydo bo'lsin.

Ishora: inset: 0 0 auto 0 (tepa, o'ng, past, chap). Boshlang'ich holat — translate: 0 -100%. Reduced motion uchun alohida opacity o'tishi — Top layer darsidagi portfolio qadami.

Yechim

Telefon qismidagi #asosiy-menyu qoidalari o'rniga:

css
#asosiy-menyu {
  inset: 0 0 auto 0;
  inline-size: 100%;
  margin: 0;
  padding: 1rem;
  border: 0;
  background: var(--rang-fon);
  box-shadow: 0 8px 24px #1f2a2440;
  opacity: 0;
  transition:
    opacity 0.2s,
    display 0.2s allow-discrete,
    overlay 0.2s allow-discrete;
}

#asosiy-menyu:popover-open {
  opacity: 1;
}

@starting-style {
  #asosiy-menyu:popover-open {
    opacity: 0;
  }
}

@media (prefers-reduced-motion: no-preference) {
  #asosiy-menyu {
    translate: 0 -100%;
    transition:
      opacity 0.2s,
      translate 0.25s ease-out,
      display 0.25s allow-discrete,
      overlay 0.25s allow-discrete;
  }

  #asosiy-menyu:popover-open {
    translate: 0 0;
  }

  @starting-style {
    #asosiy-menyu:popover-open {
      translate: 0 -100%;
    }
  }
}

Kompyuter blokiga opacity: 1 ham qo'shing — aks holda yopiq popover'dan yasalgan qator shaffof bo'lib qoladi. Balandlik yozilmadi: brauzer stilidagi height: fit-content panelni kontentiga moslaydi.

3-mashq (qiyin): ikki ichki menyu

Navbar'da ikkita details ichki menyusi: "Menyu" (3 bo'lim) va "Biz haqimizda" (Tarix, Jamoa). Talablar:

  1. Bir vaqtda faqat bittasi ochiq bo'lsin.
  2. O'ng chetdagi "Biz haqimizda" qutisi ekrandan chiqib ketmasin — u o'z tugmasining o'ng chetiga tekislansin.
  3. Telefonda (40rem gacha) ichki menyu quti emas, oddiy chekinishli ro'yxat bo'lib ochilsin (sahifa oqimida).

Ishora: 1 — bir xil name. 2 — inset-inline-end: 0 va inset-inline-start: auto (Mantiqiy xususiyatlar). 3 — mobile-first: position: absolute faqat @media (width >= 40rem) ichida.

Yechim
html
<style>
  body { font-family: system-ui, sans-serif; background: #fffaf0; }
  nav > ul {
    display: flex;
    flex-wrap: wrap;
    justify-content: end;
    gap: 0.25rem;
    margin: 0;
    padding: 0;
    list-style: none;
  }
  nav a, nav summary {
    display: block;
    padding: 0.5rem 0.75rem;
    color: #1f2a24;
    text-decoration: none;
    cursor: pointer;
  }
  nav details ul {
    margin: 0;
    padding-inline-start: 1rem;
    list-style: none;
  }
  @media (width >= 40rem) {
    nav details { position: relative; }
    nav details ul {
      position: absolute;
      inset-block-start: 100%;
      inset-inline-start: 0;
      z-index: 20;
      min-inline-size: 11rem;
      padding: 0.25rem;
      border: 1px solid #c9d6cf;
      border-radius: 0.5rem;
      background: #fffaf0;
      box-shadow: 0 8px 24px #1f2a2433;
    }
    nav li:last-child details ul {
      inset-inline-start: auto;
      inset-inline-end: 0;
    }
  }
</style>
<nav aria-label="Asosiy menyu">
  <ul>
    <li><a href="#bosh">Bosh sahifa</a></li>
    <li>
      <details name="ichki-menyu" open>
        <summary>Menyu</summary>
        <ul>
          <li><a href="#issiq-taomlar">Issiq taomlar</a></li>
          <li><a href="#salatlar">Salatlar</a></li>
          <li><a href="#ichimliklar">Ichimliklar</a></li>
        </ul>
      </details>
    </li>
    <li>
      <details name="ichki-menyu">
        <summary>Biz haqimizda</summary>
        <ul>
          <li><a href="#tarix">Tarix</a></li>
          <li><a href="#jamoa">Jamoa</a></li>
        </ul>
      </details>
    </li>
  </ul>
</nav>

Kompyuterda (1280) havolalar o'ng chetda, "Menyu" ochiq — qutisi tugma ostida. "Biz haqimizda" ni bosing: "Menyu" o'zi yopiladi (bir xil name), yangi quti esa o'ng chetga tekislangan — ekrandan chiqmaydi. Telefonda (360) ochiq "Menyu" ostida chekinishli oddiy ro'yxat, u pastdagi narsalarni suradi — kichik ekranda suzuvchi qutidan ko'ra shu qulayroq.

4-mashq: Portfolio qadami — yopishqoq header va telefon menyusi

Portfolio header'i Intrinsic layout darsidan beri Cluster: logotip va menyu sig'sa bir qatorda, sig'masa ikki qatorda. Telefonda menyu ikki qatorni egallaydi.

  1. Header surilganda tepada qolsin: 80% li fon va xiralash (zaxirasi bilan). Langar havolalar (bosh sahifadagi "Yuqoriga", #asosiy) sarlavhani header ostida qoldirmasin.
  2. Telefonda (40rem gacha) menyu "Menyu" tugmasi ortiga yashirilsin — popover, o'ngdan chiqadigan panel. Kompyuterda hozirgidek qator.
  3. Skip link (.otish) header ustida ko'rinsin.
  4. Menyusi bor har sahifada HTML o'zgaradi (5 ta). 404.html da menyu yo'q — tegmang.

Ishora: header balandligini telefonda va kompyuterda DevTools bilan o'lchang. z-index lar — z-index darsidagi portfolio shkalasi: header — --qatlam-yopishqoq (10), skip link — --qatlam-otish (40). Tugma portfolio tugmalar tizimidan (Tugmalar tizimi) ikkinchi variantni olsin.

Yechim

Har sahifaning header'ida — tugma va nav ga ikki atribut:

html
<header>
  <p><a href="./">Aziz Karimov</a></p>
  <button type="button" popovertarget="asosiy-menyu">Menyu</button>
  <nav id="asosiy-menyu" aria-label="Asosiy menyu" popover>
    <ul>
      <!-- havolalar o'zgarmaydi -->
    </ul>
  </nav>
</header>

komponentlar.css ga:

css
/* Yopishqoq header (Navbar va mobil menyu darsi) */
body > header {
  position: sticky;
  inset-block-start: 0;
  z-index: var(--qatlam-yopishqoq);
  background-color: var(--rang-fon);
}

@supports (backdrop-filter: blur(1px)) {
  body > header {
    background-color:
      color-mix(in oklch, var(--rang-fon) 80%, transparent);
    backdrop-filter: blur(8px);
  }
}

/* Header ichidagi tugma — ikkinchi variant */
body > header button {
  --_fon: transparent;
  --_matn: var(--rang-asosiy);
  --_chegara: var(--rang-asosiy);
}

/* Telefon: menyu — o'ngdan chiqadigan panel */
#asosiy-menyu {
  inset: 0 0 0 auto;
  inline-size: min(18rem, 85%);
  block-size: 100%;
  margin: 0;
  padding: var(--masofa-m);
  border: 0;
  background-color: var(--rang-fon);
  color: var(--rang-matn);
  box-shadow: var(--soya-1);
}

#asosiy-menyu ul {
  flex-direction: column;
  margin-inline: 0;
}

#asosiy-menyu::backdrop {
  background-color:
    color-mix(in oklch, var(--rang-matn) 40%, transparent);
}

@media (width >= 40rem) {
  body > header button {
    display: none;
  }

  #asosiy-menyu {
    display: block;
    position: static;
    inline-size: auto;
    block-size: auto;
    padding: 0;
    background: none;
    box-shadow: none;
    opacity: 1;
  }

  #asosiy-menyu ul {
    flex-direction: row;
    margin-inline: -0.5rem;
  }
}

asos.css ga:

css
html {
  scroll-padding-block-start: 4rem;
}
  • #asosiy-menyu ul — mavjud nav[aria-label="Asosiy menyu"] ul qoidasidan (flex, margin-inline: -0.5rem) og'irroq. Telefonda ro'yxat ustunga aylanadi, kompyuterda avvalgi holati qaytadi.
  • Panel siljish animatsiyasisiz yozildi — portfolio'ning top layer uslubi (Top layer darsi) popover'ga allaqachon shaffoflik o'tishini beradi. Harakat kamaytirilgan rejim uchun alohida qoida kerak emas.
  • opacity: 1 kompyuter blokida shart. O'sha top layer uslubida yopiq popover opacity: 0. Busiz keng ekranda menyu joyida turadi, lekin ko'rinmaydi — Chrome'da shu holatni tekshirdik.
  • 3-talab: skip link position: absolute va z-index: var(--qatlam-otish) (40) bilan — u header'dan (10) yuqorida. Qo'shimcha kod kerak emas; tekshirish uchun sahifani ochib Tab bosing.
  • Tugma matni "Menyu" — portfolio'da ikonka ishlatilmagan, so'z yetadi.
  • 4rem — namunaviy yechimda telefondagi header balandligi (bir qator) va zaxira. Sizning header'ingiz balandroq bo'lsa, qiymatni moslang.

Tekshiring: 360 pikselda "Menyu" → panel, Esc → yopiladi, fokus tugmaga qaytadi. 1280 pikselda tugma yo'q, menyu qatorda. Bosh sahifada pastga suring va "Yuqoriga" ni bosing — "Salom" sarlavhasi header ostida qolmasin. So'ng npm run check (popover va popovertarget — standart atributlar, html-validate xato bermaydi).

10. Real ishda

  • Deyarli har sayt telefonda menyuni tugma ortiga yashiradi. Uzoq yillar buni jQuery va Bootstrap'ning JavaScript'i qilgan. Bugun katta saytlar popover'ga o'tmoqda: kod kamroq, accessibility'ni brauzer beradi.
  • Yopishqoq header — yangilik saytlari va do'konlarda deyarli majburiy. Yarim shaffof fon va xiralash — Apple dizayn tilidan kelgan va keng tarqalgan uslub.
  • Pastki panel — ilovasimon saytlarda (Uzum, bank saytlari, Yandex Go) va PWA'larda (PWA haqida keyinroq o'rganamiz).
  • Intervyuda so'raladi: "JavaScript'siz mobil menyu qanday qilinadi?", "Checkbox hiylasining muammosi nima?", "Yopishqoq header ostida langar sarlavhasi yo'qolsa nima qilasiz?", "aria-expanded ni kim qo'yadi?".

Xulosa

  • Navbar — flex: logotip va menyu, flex-wrap bilan; joriy sahifa aria-current orqali, rang + qalinlik + chiziq bilan.
  • Yopishqoq header: position: sticky, 80% li fon + backdrop-filter (zaxira bilan), html da scroll-padding-block-start.
  • Telefon menyusi — popover: popovertarget tugmasi, brauzer Esc, tashqariga bosish, aria-expanded va fokusni boshqaradi. Keng ekranda media query uni oddiy qatorga aylantiradi.
  • Checkbox hiylasini yozmang; details — kichik ichki menyular uchun; hover — faqat qo'shimcha.
  • Doim DOM'da turadigan yashirin panel inert yoki visibility: hidden talab qiladi; popover'da bu muammo yo'q.
  • Surganda yashirinadigan header va pastki panel holatini almashtirish — JavaScript ishi, CSS tomoni tayyor.

Keyingi dars: Forma komponentlari: input, checkbox, switch va xato holatlari — saytning eng "ishchi" qismi: bron formasining maydonlari, maxsus checkbox va o'chirgich, xato holati va uning matni.

Manbalar

  • MDN: "Popover API", "popovertarget", "position: sticky", "backdrop-filter", "scroll-padding", "aria-current", "inert", "details", "env()" — developer.mozilla.org
  • WAI-ARIA Authoring Practices: "Disclosure (Show/Hide) pattern" — w3.org/WAI/ARIA/apg
  • web-features (Baseline ma'lumotlari): "popover", "backdrop-filter", "sticky-positioning", "details-name", "safe-area-inset", "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 navbar va mobil menyu: yopishqoq header, popover va JavaScript'siz gamburger — IlmHamroh