Mundarija (32)
- Bu darsda
- 1. Nega bu kerak?
- 2. Tooltip: kichik izoh
- 2.1 Birinchi urinish: :hover va :focus-visible
- 2.2 WCAG: sichqoncha bilan chiqadigan kontent
- 2.3 To'g'ri yo'l: popover="hint" va interestfor
- 2.4 Brauzerlar va zaxira
- 2.5 Strelka: tooltip qaysi tugmaniki?
- 3. Dropdown: tugma ostidagi menyu
- 3.1 Havolalar ro'yxati
- 3.2 Uch tanlov
- 3.3 nav va role="menu" farqi
- 4. Toast: "tayyor!" degan xabar
- 4.1 Toast nima va qayerda turadi
- 4.2 Tugma bilan ochiladigan toast
- 4.3 Bir nechta toast: stack
- 4.4 JavaScript nima qiladi
- 5. Kutubxonalar: qachon kerak
- 6. Ko'p uchraydigan xatolar
- 6.1 Tooltip ichida havola yoki tugma
- 6.2 Faqat :hover
- 6.3 Popover strelkasi ko'rinmaydi
- 6.4 Toast ekran o'rtasida
- 6.5 Jonli hudud JavaScript bilan birga qo'shildi
- 7. Mashqlar
- 1-mashq (oson): Menyu chap chetda
- 2-mashq (o'rta): Tooltip'ga strelka
- 3-mashq (qiyin): Stajyorning bildirishnomasi
- 4-mashq: Portfolio qadami — Telegram izohiga strelka
- 8. Real ishda
- Xulosa
- Manbalar
CSS tooltip, dropdown va toast: popover va anchor positioning bilan suzuvchi UI
Qisqacha: Tooltip, dropdown va toast — sahifa ustida "suzib" turadigan kichik elementlar. Endi ular uchun JavaScript kutubxonasi shart emas:
popoveratributi ochish-yopishni,Escva tashqariga bosishni beradi, anchor positioning esa elementni tugma yoniga qo'yadi. Tooltip —popover="hint"+interestfor, dropdown —popover+position-area: bottom span-right, toast — ekran burchagidagirole="status"hududi. Faqat toast'ning vaqt bilan yopilishi va yangi xabar qo'shilishi JavaScript ishi.
Bu darsda
- Tooltip'ni uch usulda qurasiz va nega faqat
:hoverbilan qurilgani WCAG'dan o'tmasligini tushuntira olasiz. - Tooltip'ga strelka qo'shasiz va u joy yetmaganda boshqa tomonga "aylanishini" ta'minlaysiz.
- Tugma ostida ochiladigan havolalar menyusini (dropdown) klaviatura bilan ishlaydigan qilib yozasiz.
- Toast bildirishnomaning joyi, ranglari, kirish-chiqish animatsiyasi va stack'ini CSS'da quramiz.
- Qaysi qismi Baseline, qaysi biri faqat Chrome'da ekanini va zaxira yo'lini bilasiz; Floating UI va Sonner qachon kerakligini ayta olasiz.
Oldin bilishingiz kerak: Anchor positioning, Top layer: dialog va popover'ni stillash, Micro-interaktsiyalar, Popover API, Jonli hududlar.
1. Nega bu kerak?
«Bahor» saytida uch xil "suzuvchi" narsa bor:
- menyuda "Bron narxi: 0 so'm" yonidagi "?" — ustiga kelsangiz, kichik izoh chiqadi;
- sarlavhadagi "Yana ▾" tugmasi — bosilsa, qo'shimcha havolalar ro'yxati ochiladi;
- bron yuborilgach, ekran burchagida "Bron qabul qilindi" degan xabar paydo bo'ladi.
Uchalasi ham sahifa ustida turadi va bir-biriga o'xshaydi. Lekin xulqi har xil. Buni choyxonadagi uch holatga o'xshatish mumkin. Tooltip — ofitsiant Otabekning qulog'ingizga pichirlab aytgan gapi: so'ramasangiz ham, yaqinlashsangiz eshitasiz. Dropdown — so'rab olgan menyungiz: o'zingiz ochasiz, o'zingiz yopasiz. Toast — oshxonadan "tayyor!" degan ovoz: sizdan hech narsa kutmaydi, bir necha soniyada tinadi.
| Komponent | Qachon ochiladi | Qachon yopiladi | Fokus ichiga kiradimi |
|---|---|---|---|
| Tooltip | Sichqoncha yoki fokus kelganda | Ketganda, Esc |
Yo'q |
| Dropdown | Tugma bosilganda | Tashqariga bosish, Esc, tanlash |
Ha |
| Toast | Biror amaldan keyin | O'zi yoki "×" bilan | Yo'q |
Ko'p yillar bularning hammasini JavaScript kutubxonalari qilgan: tugma koordinatasini o'lchash, ekrandan chiqib ketsa boshqa tomonga o'tkazish, Esc ni tinglash. Anchor positioning va Popover API bu ishning katta qismini brauzerga berdi. Bugun uchala komponentni yig'amiz.
2. Tooltip: kichik izoh
2.1 Birinchi urinish: :hover va :focus-visible
Tooltip (maslahat oynasi) — element ustiga sichqoncha yoki fokus kelganda chiqadigan qisqa izoh. Unda faqat matn bo'ladi: havola ham, tugma ham yo'q.
Eng oddiy yo'l — hech qanday yangi HTML imkoniyatisiz, faqat CSS:
<style>
body { font-family: system-ui, sans-serif; padding-top: 48px; }
.savol { anchor-name: --savol; }
.izoh {
position: absolute;
position-anchor: --savol;
position-area: top;
margin: 0 0 8px;
padding: 4px 8px;
border-radius: 6px;
background: #1f2a24;
color: #fffaf0;
font-size: 14px;
visibility: hidden;
opacity: 0;
transition: opacity 0.15s, visibility 0.15s;
}
.savol:hover + .izoh,
.savol:focus-visible + .izoh {
visibility: visible;
opacity: 1;
}
</style>
<p>Bron narxi: 0 so'm
<button type="button" class="savol"
aria-describedby="bron-izoh">?</button>
<span class="izoh" id="bron-izoh">To'lov faqat choyxonada</span>
</p>Nimaga qarang: sahifa ochilganda izoh ko'rinmaydi. Sichqonchani "?" ustiga olib boring yoki Tab bilan fokuslang — qora izoh tugma tepasida paydo bo'ladi. Ekran o'quvchi esa aria-describedby tufayli tugmani "savol belgisi, To'lov faqat choyxonada" deb o'qiydi (ARIA asoslari). visibility va opacity — Transition darsidagi "ko'rinmas, lekin joyida" naqshi.
Ko'rinishi yaxshi. Lekin Chrome'da tekshirdik va ikki muammo topdik:
- Izoh ustiga o'tib bo'lmaydi. Sichqonchani tugmadan izohga sursangiz, u 8 piksellik bo'shliqda
:hoverni yo'qotadi va izoh yashirinadi. Ekranni kattalashtirib ishlatadigan odam izohni o'qiy olmaydi: kattalashtirilgan ekranda izohning yarmi ko'rinmaydi, uni ko'rish uchun sichqonchani surish kerak. Escyopmaydi. Fokus tugmada turibdi, izoh boshqa matnni yopib qo'ydi — undan qutulishning yo'li yo'q.
2.2 WCAG: sichqoncha bilan chiqadigan kontent
Bu ikki muammo WCAG'ning 1.4.13 "Content on Hover or Focus" mezonida yozilgan (AA daraja). Sichqoncha yoki fokus bilan chiqadigan kontent uch shartga javob berishi kerak:
- Yopsa bo'ladi (dismissible) — sichqonchani yoki fokusni surmasdan, masalan
Escbilan yopiladi. - Ustiga o'tsa bo'ladi (hoverable) — sichqoncha izohning o'ziga o'tganda u yo'qolmaydi.
- Turib turadi (persistent) — foydalanuvchi o'zi ketmaguncha yoki yopmaguncha yo'qolmaydi.
Bizning CSS tooltip'imiz birinchi ikkitasidan o'tmaydi. CSS'ning o'zi Esc tugmasini "eshitmaydi" — buning uchun brauzerning o'z mexanizmi kerak.
Tekshirib ko'ring: Dizayner "tooltip 3 soniyadan keyin o'zi yo'qolsin" dedi. Qaysi shart buziladi?
Javob
"Turib turadi" (persistent) sharti. Sekin o'qiydigan odam 3 soniyada matnni tugatmasligi mumkin. Tooltip foydalanuvchi sichqonchani yoki fokusni olib ketmaguncha yoki Esc bosmaguncha turishi kerak.
2.3 To'g'ri yo'l: popover="hint" va interestfor
Popover API va Invoker commands darslarida ikki yangi atributni ko'rgan edik:
popover="hint"— "maslahat" turi. Boshqa ochiq menyularni yopmaydi,Escva tashqariga bosish bilan yopiladi.interestfor— "qiziqish bildirilganda och": sichqoncha ustiga kelganda yoki fokus tushganda. Tugma bosilishini kutmaydi.
Endi ularni anchor positioning bilan birlashtiramiz:
<style>
body { font-family: system-ui, sans-serif; padding-top: 48px; }
button[interestfor="bron-izoh"] {
anchor-name: --bron-izoh;
}
#bron-izoh {
position-anchor: --bron-izoh;
position-area: top;
position-try-fallbacks: flip-block;
margin: 0 0 8px;
padding: 4px 8px;
border: 0;
border-radius: 6px;
background: #1f2a24;
color: #fffaf0;
font-size: 14px;
opacity: 0;
transition:
opacity 0.15s,
display 0.15s allow-discrete,
overlay 0.15s allow-discrete;
}
#bron-izoh:popover-open { opacity: 1; }
@starting-style {
#bron-izoh:popover-open { opacity: 0; }
}
</style>
<p>Bron narxi: 0 so'm
<button type="button" interestfor="bron-izoh"
popovertarget="bron-izoh"
aria-describedby="bron-izoh">?</button>
</p>
<p id="bron-izoh" popover="hint">To'lov faqat choyxonada</p>Nimaga qarang: "?" ustida yarim soniya tursangiz, izoh asta paydo bo'ladi. Endi sichqonchani izohning o'ziga olib o'ting — u yo'qolmaydi. Esc bosing — yopiladi. Chrome 154 da o'lchadik: izoh sichqoncha kelgandan 0,3–0,6 soniya orasida ochildi, sichqoncha ketgach esa 0,2–0,4 soniyada yopildi. Klaviatura bilan Tab bosganda ham ochildi, Esc yopdi.
Kodni o'qiymiz:
- Popover o'zi top layer'da.
position: absoluteyozish shart emas (Anchor positioning). Ochilish animatsiyasi — Top layer darsidagi andoza:@starting-style,allow-discrete,overlay. Faqat shaffoflik o'zgaradi — bu harakat emas,prefers-reduced-motionbloki kerak emas (Harakat etikasi). - Ikki atribut — ikki yo'l.
interestfor— sichqoncha va fokus uchun.popovertarget— bosish uchun. Chrome'da ikkalasi birga ishladi: hover bilan ochilgan izoh ustiga bosilsa yopildi, qayta bosilsa ochildi. aria-describedbyni o'zingiz yozing. Chrome'ning accessibility daraxtida tekshirdik:interestforning o'zi tugmaga tavsif bermadi.aria-describedbyqo'shilgach, tugma "To'lov faqat choyxonada" tavsifini oldi.
Kutish vaqtini interest-delay xususiyati sozlaydi: interest-delay: 0.2s; — ochilish ham, yopilish ham 0,2 soniya. Ikki qiymat yozsangiz — birinchisi ochilish, ikkinchisi yopilish uchun. Sukut bo'yicha qiymat — normal, ya'ni brauzer tanlagan vaqt (yuqorida o'lchagan yarim soniya atrofida). Kichik kechikish kerak: sahifa bo'ylab sichqoncha yurganda har tugma ustida izoh "chaqnab" ketmasin.
2.4 Brauzerlar va zaxira
Baseline ma'lumoti bo'yicha:
| Imkoniyat | Holat |
|---|---|
popover (auto, manual) |
Baseline, 2025-yil yanvardan (yangi) |
popover="hint" |
Baseline emas: Chrome/Edge 151, Firefox 153; Safari'da yo'q |
interestfor, interest-delay |
Baseline emas: faqat Chrome/Edge 142 dan |
| Anchor positioning (asosiy qism) | Baseline, 2026-yil yanvardan (yangi) |
@starting-style, allow-discrete |
Baseline, 2024-yil avgustdan (yangi) |
overlay |
Baseline emas: faqat Chrome/Edge 117 dan |
Endi yuqoridagi kod boshqa brauzerlarda qanday ishlashini ko'raylik:
- Firefox
interestforni tanimaydi: sichqoncha kelganda hech narsa bo'lmaydi. Lekinpopovertargetbor — "?" bosilsa, izoh ochiladi vaEscyopadi. - Safari
hintni tanimaydi va popover'nimanualdeb tushunadi (Top layer). Bosish ochadi, qayta bosish yopadi.Escva tashqariga bosish yopmaydi — noqulay, lekin ma'lumot yo'qolmaydi.
"Yangi" Baseline — eski telefon va brauzerlarda yo'q. Animatsiyasi bo'lmasa, izoh shunchaki darhol chiqadi. Shuning uchun ikki atributni birga yozish tavsiya: interestfor — yangi brauzerlar uchun qulaylik, popovertarget — hamma uchun asosiy yo'l.
Diqqat: Telefonda "sichqoncha olib kelish" yo'q. Tooltip'ga faqat qo'shimcha izoh yozing — muhim ma'lumot (narx, shart, xato sababi) sahifaning o'zida ochiq tursin. Invoker commands darsidagi qoidaning o'zi.
2.5 Strelka: tooltip qaysi tugmaniki?
Ko'p dizaynlarda tooltip ostida kichik uchburchak bo'ladi — u izoh qaysi tugmaga tegishliligini ko'rsatadi. Uchburchak — ::after (Pseudo-elementlar): eni nol, faqat bitta tomonida rangli border. Qiyin joyi boshqa: tooltip joy yetmay pastga "aylansa" (flip-block), strelka hamon pastga qarab qoladi.
Yechim — container-type: anchored. U bog'langan elementni "konteyner" qiladi va ichidagi qoidalar qaysi zaxira joy tanlanganini so'ray oladi: @container anchored(fallback: flip-block) { ... } — "agar flip-block tanlangan bo'lsa". Container queries darsidagi g'oya, faqat o'lcham o'rniga — joylashuv.
<style>
body { font-family: system-ui, sans-serif; margin: 0; }
.satr {
display: flex;
justify-content: space-around;
align-items: start;
height: 150px;
padding-top: 4px;
}
.satr button { font: inherit; }
.past { margin-top: 90px; }
.t1 { anchor-name: --t1; }
.t2 { anchor-name: --t2; }
.izoh {
position: absolute;
position-area: top;
position-try-fallbacks: flip-block;
container-type: anchored;
margin: 0 0 10px;
padding: 4px 8px;
border-radius: 6px;
background: #1f2a24;
color: #fffaf0;
font-size: 14px;
}
.i1 { position-anchor: --t1; }
.i2 { position-anchor: --t2; }
.izoh::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
translate: -50% 0;
border: 6px solid transparent;
border-top-color: #1f2a24;
}
@container anchored(fallback: flip-block) {
.izoh::after {
top: auto;
bottom: 100%;
border-top-color: transparent;
border-bottom-color: #1f2a24;
}
}
</style>
<div class="satr">
<button type="button" class="t1">Tepada</button>
<button type="button" class="t2 past">Pastroqda</button>
</div>
<p class="izoh i1">Joy yo'q — pastga o'tdim</p>
<p class="izoh i2">Joy bor — tepada turibman</p>Nimaga qarang: ikki izohning CSS'i bir xil — position-area: top. "Pastroqda" izohi tugma tepasida, strelkasi pastga qaragan. "Tepada" tugmasi ustida esa joy yo'q: izoh pastga o'tdi va strelkasi tepaga, tugmaga qarab qoldi. Izohlar bu yerda doim ko'rinadi — shunda ikkala holatni bir vaqtda ko'rasiz.
Strelka ichida ikki tanish narsa bor. top: 100% — izohning pastki chetidan tashqariga (position). translate: -50% 0 — o'z enining yarmicha chapga, ya'ni aniq o'rtaga (2D transformlar).
Brauzer holati: container-type: anchored va @container anchored() — Baseline emas, faqat Chrome/Edge 143 dan. Firefox va Safari'da strelka doim pastga qaraydi — izoh pastga aylanganda strelka noto'g'ri tomonga ko'rsatadi. Buni oldini olish uchun strelkani butunlay @supports ichiga oling:
/* Strelka faqat u to'g'ri aylanadigan brauzerda */
@supports (container-type: anchored) {
#bron-izoh {
container-type: anchored;
overflow: visible;
}
#bron-izoh::after {
content: "";
/* ... yuqoridagi strelka qoidalari ... */
}
}Boshqa brauzerda tooltip strelkasiz chiqadi — chiroyi kamroq, lekin to'g'ri. overflow: visible ga e'tibor bering: brauzer popover'ga overflow: auto beradi va chetdan tashqaridagi strelka kesilib qoladi. Chrome'da tekshirdik: overflow ni qaytarib olsak, strelka yo'qoladi.
Tekshirib ko'ring: Tooltip matni uzun, strelka esa izoh o'rtasida emas, chap chetga yaqin chiqdi.
position-area: topyozilgan. Nimani tekshirasiz?
Javob
Izoh tugma o'rtasiga tekislanganmi. Odatda position-area: top izohni tugma o'rtasiga qo'yadi. Lekin izoh ekran chetiga yaqin bo'lsa, brauzer uni ichkariga suradi — shunda izoh o'rtasi tugma o'rtasiga to'g'ri kelmaydi va left: 50% dagi strelka tugmaga emas, izoh o'rtasiga qaraydi. Chetdagi tugmalar uchun position-area: top span-right (yoki span-left) tanlash va strelkani chetga yaqinroq qo'yish mumkin.
3. Dropdown: tugma ostidagi menyu
3.1 Havolalar ro'yxati
Dropdown (ochiladigan menyu) — tugma bosilganda uning ostida ochiladigan ro'yxat. Navbar va mobil menyu darsida uning sodda turini — details dagi ichki menyuni — qurgan edik: u tashqariga bosish va Esc bilan yopilmaydi. Endi to'liq dropdown: popover (top layer, yopilishni brauzer boshqaradi) va anchor positioning (joyni brauzer tanlaydi). Misol — «Bahor» sarlavhasining ixcham varianti: logotip yonida faqat "Yana ▾" tugmasi, "Aloqa", "Stol band qilish" va "Blog" havolalari uning ortida.
<style>
body { font-family: system-ui, sans-serif; margin: 0; }
header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 16px;
background: #2f6b3a;
color: #fffaf0;
}
header p { margin: 0; font-weight: bold; }
button[popovertarget="yana"] {
anchor-name: --yana;
padding: 6px 12px;
font: inherit;
}
#yana {
position-anchor: --yana;
position-area: bottom span-left;
position-try-fallbacks: flip-block, flip-inline;
min-width: anchor-size(width);
margin: 4px 0 0;
padding: 4px;
list-style: none;
border: 1px solid #c9d6cf;
border-radius: 8px;
background: #fffaf0;
box-shadow: 0 8px 24px #1f2a2433;
opacity: 0;
translate: 0 -4px;
transition:
opacity 0.15s, translate 0.15s,
display 0.15s allow-discrete,
overlay 0.15s allow-discrete;
}
#yana:popover-open { opacity: 1; translate: 0 0; }
@starting-style {
#yana:popover-open { opacity: 0; translate: 0 -4px; }
}
@media (prefers-reduced-motion: reduce) {
#yana, #yana:popover-open { translate: none; }
}
#yana a {
display: block;
padding: 8px 12px;
border-radius: 4px;
color: #1f2a24;
text-decoration: none;
}
#yana a:hover,
#yana a:focus-visible { background: #e8f1ec; }
:focus-visible {
outline: 3px solid #1a5d1a;
outline-offset: 2px;
box-shadow: 0 0 0 2px #fffaf0;
}
</style>
<header>
<p>Choyxona «Bahor»</p>
<nav aria-label="Qo'shimcha menyu">
<button type="button" popovertarget="yana">Yana ▾</button>
<ul id="yana" popover>
<li><a href="aloqa/">Aloqa</a></li>
<li><a href="bron/">Stol band qilish</a></li>
<li><a href="blog/">Blog</a></li>
</ul>
</nav>
</header>Nimaga qarang: "Yana ▾" ni bosing — ro'yxat tugma ostida, 4 piksel tushib, asta ochiladi. Tugma o'ng chetda turibdi, shuning uchun ro'yxat chapga qarab ochildi (bottom span-left) va ekrandan chiqmadi. Tashqariga bosing yoki Esc — yopiladi.
Chrome'da klaviatura bilan tekshirdik:
Tab→ "Yana ▾" →Enter: menyu ochildi, tugma accessibility daraxtida "expanded" holatini oldi.aria-expandedni o'zimiz yozmadik —popovertargetuni o'zi beradi.- Keyingi
Tab: fokus "Aloqa" ga o'tdi, keyin "Stol band qilish". Popover HTML'da boshqa joyda tursa ham,Tabtartibida u tugmadan keyin keladi. - Fokus menyu ichida turganda
Esc: menyu yopildi va fokus "Yana ▾" ga qaytdi. Bu Klaviatura va fokus darsidagi "fokusni qaytarish" qoidasi — brauzer o'zi bajardi.
3.2 Uch tanlov
bottom span-left— tugma o'ng chetda bo'lgani uchun. Chap chetdagi tugmagabottom span-right. Zaxira ro'yxatidagiflip-inline— sahifa tuzilishi o'zgarib, tugma boshqa chetga ko'chsa ham menyu sig'sin.min-width: anchor-size(width)— menyu tugmadan tor bo'lmaydi, uzun havola uchun esa kengaya oladi (Anchor positioning darsidagi 2-mashq).- Havolalarga
display: blockvapadding— bosish maydoni butun qator: barmoq bilan tegish oson (UI/UX asoslari darsidagi bosish maydoni). - Fokus — och fon va «Bahor»ning ikki rangli halqasi:
outline+ fon rangidagibox-shadow(CSS'da accessibility). Saytda bu umumiy:focus-visibleqoidasiasos.cssda turadi; natijada ko'rinsin deb takrorladik.
3.3 nav va role="menu" farqi
Bu ro'yxatda havolalar bor — demak, u navigatsiya, nav ichida turadi. ARIA patternlari darsidagi qoidani eslang: role="menu" — amallar ro'yxati uchun ("Takrorlash", "Bekor qilish"), va u strelkalar bilan boshqarishni talab qiladi. Strelkalarni, Home/End ni va harf bilan qidirishni CSS ham, popover ham bermaydi — bu JavaScript ishi. Tilni 08-qismda, sahifa elementlarini boshqarishni esa 09-qismda (Dinamik UI'da qulaylik) o'rganamiz. Hozircha qoida: havolalar menyusi — nav + popover, role yozilmaydi. Mobil menyuni to'liq Navbar va mobil menyu darsida qurdik.
Diqqat: "Sichqoncha kelganda ochiladigan" menyu (
:hoverdropdown) yozmang. Telefonda hover yo'q, klaviatura foydalanuvchisi uni ocholmaydi, sichqoncha esa ro'yxatga o'tayotganda uni tasodifan yopib qo'yadi. Menyu — bosish bilan.
Tekshirib ko'ring: Nima uchun dropdown uchun
popover="hint"emas, oddiypopover(auto) tanlandi?
Javob
Menyu — foydalanuvchi o'zi ochadigan va ichiga kiradigan narsa. Oddiy (auto) popover boshqa shunday popover ochilganda o'zi yopiladi: bir vaqtda ikkita menyu ochiq qolmaydi. Maslahat turi (hint) esa faqat qisqa izoh uchun — u boshqa menyularni yopmaydi va Safari'da manual bo'lib, Esc ga ham javob bermaydi.
4. Toast: "tayyor!" degan xabar
4.1 Toast nima va qayerda turadi
Toast bildirishnoma (toast notification) — biror amaldan keyin ekran chetida qisqa vaqtga chiqadigan xabar. Nomi tosterdan sakrab chiqadigan non bo'lagidan olingan: pastdan "chiqadi", biroz turadi, yo'qoladi.
Toast uchun amaliy qoidalar:
- Joyi doim bir xil. Kompyuterda — pastki o'ng burchak, telefonda — pastda, butun en bo'ylab. Foydalanuvchi xabarni qayerdan izlashni bilsin.
- Muhim tugmani yopmasin. Telefonda "Yuborish" yoki pastki menyu ustiga chiqmasin.
- Faqat "bo'ldi" xabari. Javob talab qiladigan savol ("O'chirilsinmi?") — toast emas, modal oyna.
- Ma'nosi rangsiz ham tushunarli. Belgi va so'z bilan: " Bron qabul qilindi" (Rang nazariyasi darsidagi WCAG 1.4.1).
- Ekran o'quvchiga eshitiladi. Toast hududi —
role="status"(Jonli hududlar).
4.2 Tugma bilan ochiladigan toast
JavaScript'siz ham toast'ni ko'rsata olamiz: popover="manual" — o'zi yopilmaydigan popover. Ochuvchi tugmada popovertargetaction="show", yopuvchi "×" da — "hide":
<style>
:root {
--rang-fon: #fffaf0;
--rang-matn: #1f2a24;
--rang-muvaffaqiyat: oklch(52% 0.13 150);
}
body { font-family: system-ui, sans-serif; }
#bron-toast {
inset: auto 16px 16px auto;
max-width: min(100% - 32px, 22rem);
margin: 0;
padding: 12px 12px 12px 16px;
border: 0;
border-inline-start: 4px solid var(--rang-muvaffaqiyat);
border-radius: 8px;
background: var(--rang-fon);
color: var(--rang-matn);
box-shadow: 0 8px 24px #1f2a2433;
opacity: 0;
translate: 0 16px;
transition:
opacity 0.25s, translate 0.25s,
display 0.25s allow-discrete,
overlay 0.25s allow-discrete;
}
#bron-toast:popover-open {
display: flex;
gap: 12px;
align-items: start;
opacity: 1;
translate: 0 0;
}
@starting-style {
#bron-toast:popover-open { opacity: 0; translate: 0 16px; }
}
@media (prefers-reduced-motion: reduce) {
#bron-toast, #bron-toast:popover-open { translate: none; }
}
#bron-toast p { margin: 0; }
#bron-toast strong { color: var(--rang-muvaffaqiyat); }
#bron-toast button {
min-width: 24px;
min-height: 24px;
border: 0;
background: none;
font-size: 18px;
line-height: 1;
}
</style>
<button type="button" popovertarget="bron-toast"
popovertargetaction="show">Stolni band qilish</button>
<div id="bron-toast" popover="manual" role="status">
<p><strong>✔ Bron qabul qilindi.</strong>
Stol 19:00 ga tayyor.</p>
<button type="button" popovertarget="bron-toast"
popovertargetaction="hide"
aria-label="Xabarni yopish">×</button>
</div>Nimaga qarang: "Stolni band qilish" ni bosing — pastki o'ng burchakda xabar 16 piksel pastdan ko'tarilib, asta paydo bo'ladi. Uning chap chetida yashil chiziq, matn boshida "" va yashil so'z bor. Sahifaning boshqa joyiga bossangiz ham yopilmaydi — manual popover shunday. "×" bosilsa — pastga tushib so'nadi.
inset: auto 16px 16px auto— popover'ning standartinset: 0vamargin: autoi uni ekran o'rtasiga qo'yardi (Anchor positioning darsidagi tuzoq). Bu yerda langar yo'q: toast ekran burchagiga bog'lanadi. Tartib — tepa, o'ng, past, chap (CSS nima darsidagi soat mili).display: flexfaqat:popover-openda — Top layer darsidagidisplaytuzog'i. Yopiq popover'gadisplayyozsangiz, u yopiq holatda ham ko'rinib qoladi.--rang-muvaffaqiyat— «Bahor»ning semantik holat rangi (Rang nazariyasi): qaymoq fonda 5.0:1.- "×" tugmasi 24×24 — WCAG 2.5.8 minimal bosish maydoni (O'lchamlar).
aria-label— belgi o'qilmasligi uchun: ekran o'quvchi "ko'paytirish" emas, "Xabarni yopish" deydi.
Diqqat:
role="status"ekran o'quvchiga faqat hududning ichidagi matn o'zgarganda xabar beradi (Jonli hududlar). Yopiq popover'ni ko'rsatish — matn o'zgarishi emas, va brauzerlar buni bir xil e'lon qilmaydi. Haqiqiy loyihada JavaScript bo'sh hududga matnni yozadi — shunda e'lon ishonchli bo'ladi. Bu darsda biz toast'ning ko'rinishini quramiz.
4.3 Bir nechta toast: stack
Foydalanuvchi ketma-ket uch amal qildi — uchta xabar. Ular ustma-ust tushmasligi kerak. Sanoatdagi odatiy tuzilma: ekran burchagida bitta hudud, uning ichida xabarlar ro'yxati. Har yangi xabar ro'yxat oxiriga qo'shiladi. Bunday ustma-ust taxlangan to'plam stack deb ataladi — xuddi stol ustidagi likopchalar taxlami.
<style>
:root {
--rang-fon: #fffaf0;
--rang-matn: #1f2a24;
--rang-muvaffaqiyat: oklch(52% 0.13 150);
--rang-xato: oklch(52% 0.19 27);
--rang-malumot: oklch(52% 0.13 250);
}
body { font-family: system-ui, sans-serif; }
.toastlar {
position: fixed;
inset: auto 8px 8px 8px;
display: flex;
flex-direction: column;
gap: 8px;
margin: 0;
padding: 0;
list-style: none;
}
@media (min-width: 40rem) {
.toastlar { inset: auto 16px 16px auto; width: 22rem; }
}
.toastlar li {
padding: 10px 14px;
border-inline-start: 4px solid var(--_rang);
border-radius: 8px;
background: var(--rang-fon);
color: var(--rang-matn);
box-shadow: 0 4px 12px #1f2a2426;
transition: opacity 0.3s, translate 0.3s;
}
@starting-style {
.toastlar li { opacity: 0; translate: 0 16px; }
}
@media (prefers-reduced-motion: reduce) {
.toastlar li { translate: none; }
}
.toastlar strong { color: var(--_rang); }
.ok { --_rang: var(--rang-muvaffaqiyat); }
.xato { --_rang: var(--rang-xato); }
.info { --_rang: var(--rang-malumot); }
</style>
<p>Sahifaning asosiy matni shu yerda.</p>
<section aria-label="Bildirishnomalar">
<ol class="toastlar" role="status">
<li class="info"><strong>ℹ Eslatma.</strong>
Bron 2 soat oldin qilinadi.</li>
<li class="xato"><strong>✖ Telefon noto'g'ri.</strong>
Namuna: +998 90 000 00 00</li>
<li class="ok"><strong>✔ Bron qabul qilindi.</strong>
Stol 19:00 ga tayyor.</li>
</ol>
</section>Nimaga qarang: uchta xabar bir-birining ostida, 8 piksel oraliq bilan. Eng yangisi ("Bron qabul qilindi") pastda — burchakka eng yaqin. Telefon enida (360) xabarlar butun en bo'ylab, pastda. 768 va 1280 da esa pastki o'ng burchakda, 22rem enli ustun. Sahifa ochilganda har xabar pastdan ko'tarilib chiqadi — @starting-style sahifa yuklanganda ham ishlaydi (Kirish va chiqish animatsiyalari).
Tuzilma:
section aria-label— hududga nom. Ekran o'quvchi foydalanuvchisi uni hududlar ro'yxatida topadi.ol+role="status"— tartibli ro'yxat (yangi xabar — oxirida) va jonli hudud. Hudud sahifada doim turadi, bo'sh bo'lsa ham. JavaScript faqat ichigaliqo'shadi — shunda e'lon ishonchli.position: fixed— sahifa aylantirilganda ham burchakda qoladi (position: fixed).- Ichki
--_rang— bitta qoida, uch xil rang (CSS o'zgaruvchilari 2).
Bu hudud top layer'da emas. Ochiq modal oyna uni to'sib qo'yadi. Kutubxonalar bunga ham yo'l topadi — masalan, hududning o'zini popover="manual" qilib, JavaScript bilan ochib qo'yish. Hozircha bilish kifoya: toast va modal bir vaqtda kerak bo'lsa, qatlamlarni o'ylang.
Tekshirib ko'ring: Stajyor bo'sh
ol role="status"ni sahifadan olib tashladi: "xabar kelganda JavaScript hudud va xabarni birga qo'shadi". Nima buziladi?
Javob
Ekran o'quvchi xabarni eshittirmaydi. Jonli hudud faqat oldindan bor hudud ichidagi o'zgarishni kuzatadi. Hudud xabar bilan bir vaqtda paydo bo'lsa, brauzer uni "yangi hudud" deb qabul qiladi, "o'zgarish" deb emas — Malika jim qoladi.
4.4 JavaScript nima qiladi
CSS toast'ning joyini, ko'rinishini va harakatini beradi. Qolgan ishlar — JavaScript'da:
- amal tugagach, hududga yangi
liqo'shish; - 5–6 soniyadan keyin uni olib tashlash (chiqish animatsiyasi tugagach);
- sichqoncha xabar ustida yoki fokus ichida bo'lsa — vaqtni to'xtatib turish;
- juda ko'p xabar yig'ilsa, eskilarini yopish.
Uchinchi band — WCAG 2.2.1 "Timing Adjustable" mezonining ruhi: foydalanuvchi o'qib ulgurishi kerak. Muhim havola yoki "Bekor qilish" tugmasini faqat 5 soniyalik toast ichiga qo'ymang — u sahifada ham bo'lsin.
5. Kutubxonalar: qachon kerak
Floating UI (@floating-ui/dom paketi, hozir 1.8 versiya) — tooltip va menyularni JavaScript bilan joylaydigan kutubxona (Anchor positioning darsida tanishgan edik). Sonner (hozir 2.0) va react-hot-toast 2.6-bob — React uchun toast kutubxonalari; ularni React qismida uchratasiz, hozir bilish shart emas. Bunday kutubxonalar npm orqali o'rnatiladi — dasturchilar kodini tarqatadigan umumiy ombor; npm'ni keyingi qismlarda to'liq o'rganamiz. Versiyalar dars yozilgan kuni shu ombordan tekshirilgan.
| Vaziyat | Tanlov |
|---|---|
| Oddiy sayt, tooltip va menyu | popover + anchor positioning (bu dars) |
| Eski brauzerlar juda muhim | Floating UI |
| React ilova, ko'p toast, "bekor qilish", surib yopish | Sonner yoki shunga o'xshash |
| Toast'ning ko'rinishi | Baribir sizning CSS'ingiz — kutubxona uni o'zgartirishga ruxsat beradi |
Sonner ichida ham siz quradigan narsa turibdi: section hudud, ol ro'yxat, jonli hudud atributlari. Kutubxona vaqt, surib yopish, "stack" ni sichqoncha kelganda yoyib ko'rsatish kabi xulqni qo'shadi. Asosni bilgan dasturchi kutubxonani ham tez tushunadi, uning xatosini ham topadi.
6. Ko'p uchraydigan xatolar
6.1 Tooltip ichida havola yoki tugma
Tooltip'ga "Batafsil" havolasini qo'ydingiz — sichqoncha unga yetib borguncha izoh yopiladi, klaviatura esa umuman kira olmaydi. Tuzatish: bosiladigan narsa bo'lsa — bu tooltip emas, popover (bosish bilan ochiladigan panel, dropdown kabi).
6.2 Faqat :hover
:focus-visible unutilgan: klaviatura foydalanuvchisi izohni hech qachon ko'rmaydi. Esc ham ishlamaydi. Tuzatish: popover + interestfor + popovertarget.
6.3 Popover strelkasi ko'rinmaydi
::after bor, lekin ko'rinmaydi. Popover'ning standart overflow: auto i chetdan chiqqan qismni kesadi. Tuzatish: overflow: visible.
6.4 Toast ekran o'rtasida
popover="manual" toast o'rtada ochildi. Popover'ning standart inset: 0 va margin: auto i qolgan. Tuzatish: inset ni to'rt qiymat bilan qayta yozing va margin: 0.
6.5 Jonli hudud JavaScript bilan birga qo'shildi
Hudud va xabar bir vaqtda sahifaga qo'shildi — ekran o'quvchi jim qoldi. Tuzatish: hudud HTML'da oldindan, bo'sh holda tursin; JavaScript faqat ichini to'ldirsin (Jonli hududlar).
7. Mashqlar
Mashqlarni kurs/mashqlar/06/ papkasida bajaring: har mashqqa alohida papka, ichida index.html va asosiy.css.
1-mashq (oson): Menyu chap chetda
«Bahor» sarlavhasi o'zgardi: "Yana ▾" tugmasi endi chap chetda, logotipdan oldin. Dropdown natijasidagi CSS'da bitta qiymatni almashtiring, shunda menyu ekrandan chiqmasin va tugmaning chap cheti bilan tekis ochilsin.
Ishora: position-area ning ikkinchi so'zi (Anchor positioning darsidagi span-* qiymatlari).
Yechim
#yana {
position-area: bottom span-right;
}span-right — o'rta ustundan (tugmadan) boshlab o'ngga. Menyuning chap cheti tugmaning chap cheti bilan bir chiziqda. flip-inline zaxirasi qolaveradi: tugma yana o'ngga ko'chsa, menyu o'zi chapga ochiladi.
2-mashq (o'rta): Tooltip'ga strelka
«Tooltip: to'g'ri yo'l» natijasidagi #bron-izoh ga strelka qo'shing:
- Strelka izoh ostida, o'rtada, 6 piksellik uchburchak.
- Izoh pastga aylansa — strelka tepaga qarasin.
- Strelkani aylantira olmaydigan brauzerda strelka umuman chiqmasin.
Ishora: «Strelka» bo'limidagi natija va @supports bloki. Popover'da strelka kesilmasligi uchun bitta qo'shimcha xususiyat kerak.
Yechim
@supports (container-type: anchored) {
#bron-izoh {
container-type: anchored;
overflow: visible;
}
#bron-izoh::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
translate: -50% 0;
border: 6px solid transparent;
border-top-color: #1f2a24;
}
@container anchored(fallback: flip-block) {
#bron-izoh::after {
top: auto;
bottom: 100%;
border-top-color: transparent;
border-bottom-color: #1f2a24;
}
}
}overflow: visible— popover'ning standartoverflow: autoi strelkani kesmasin.@containerqoidasi@supportsichida — CSS nesting darsidagi kabi @-qoidalar bir-birining ichida yozilishi mumkin.- Firefox va Safari'da
@supportssharti yolg'on: izoh strelkasiz, lekin to'g'ri joyda.
3-mashq (qiyin): Stajyorning bildirishnomasi
Stajyor «Bahor» bron sahifasiga shunday toast yozdi:
<div class="toast" popover>Bron qabul qilindi</div>.toast {
display: flex;
bottom: 16px;
right: 16px;
background: #b4461a;
color: #fffaf0;
}Shikoyatlar:
- Toast sahifa ochilishi bilan ko'rinib turibdi va yopilmaydi.
- Ochilganda ekran o'rtasida chiqadi.
- Sahifaning istalgan joyiga bossangiz, yo'qolib qoladi.
- Malika (NVDA) xabarni eshitmaydi.
- Qizg'ish fon "xato bo'ldimi?" degan fikr uyg'otadi.
Har muammoning sababini toping va HTML hamda CSS'ni tuzating.
Ishora: «Tugma bilan ochiladigan toast» bo'limi; beshinchi muammo — Rang nazariyasi darsidagi «Urg'u va xato to'qnashuvi».
Yechim
display: flexyopiq holatga yozilgan — popover yopiq bo'lsa ham ko'rinadi (Top layer darsidagi tuzoq).inset: 0vamargin: autoqolgan —bottomvarightyozilgan, lekintopvalefthamon 0.popover(auto) — tashqariga bosish uni yopadi. Toast uchunmanual.- Jonli hudud yo'q —
role="status". - Urg'u rangi — narx va aksiya rangi. Muvaffaqiyat uchun semantik
--rang-muvaffaqiyat, belgi va so'z bilan.
<div id="bron-toast" popover="manual" role="status">
<p><strong>✔ Bron qabul qilindi.</strong></p>
</div>#bron-toast {
inset: auto 1rem 1rem auto;
margin: 0;
border: 0;
border-inline-start: 4px solid var(--rang-muvaffaqiyat);
background: var(--rang-fon);
color: var(--rang-matn);
}
#bron-toast:popover-open {
display: flex;
}class="toast" olib tashlandi: «Bahor»ning kanonik class ro'yxatida bunday nom yo'q, id selektori yetarli.
4-mashq: Portfolio qadami — Telegram izohiga strelka
Anchor positioning darsida portfolio'ning "Aloqa" sahifasiga #telegram-izoh popover'ini qo'shgan edik: "?" tepasida, sig'masa pastida. Endi uni haqiqiy tooltip'ga yaqinlashtiring:
- Chrome'da "?" ustiga sichqoncha kelganda ham ochilsin; bosish bilan ochilishi saqlansin.
- Izohning ostida (yoki tepasida — qaysi tomonda ochilsa) tugmaga qaragan strelka bo'lsin. Popover'ning chegarasi bor — strelka ham chegara bilan chizilsin.
- Strelkani aylantira olmaydigan brauzerda strelka chiqmasin.
- Chrome'da sahifani shunday aylantiringki, "?" ekran tepasiga yaqin tursin — izoh pastga o'tsa, strelka tepaga qarasinmi? So'ng
npm run check.
Ishora: chegarali strelka uchun uchburchak o'rniga 45° burilgan kvadrat qulay: background: inherit; border: inherit; va ikki tomonining chegarasini olib tashlash. rotate — 2D transformlar. Popover'ning umumiy qoidalari Top layer darsida yozilgan — ularni takrorlamang.
Yechim
aloqa/index.html dagi tugmaga bitta atribut:
<button type="button" popovertarget="telegram-izoh"
interestfor="telegram-izoh"
aria-label="Telegram'da javob vaqti">?</button>komponentlar.css dagi #telegram-izoh qoidasidan keyin:
/* --- Telegram izohiga strelka: faqat u aylana oladigan brauzerda
(Tooltip, dropdown va toast darsi) --- */
@supports (container-type: anchored) {
#telegram-izoh {
container-type: anchored;
overflow: visible;
margin-block: 0 0.75rem;
}
#telegram-izoh::after {
content: "";
position: absolute;
inset-block-start: 100%;
inset-inline-start: 50%;
inline-size: 0.625rem;
block-size: 0.625rem;
translate: -50% -50%;
rotate: 45deg;
background: inherit;
border: inherit;
border-block-start: 0;
border-inline-start: 0;
}
@container anchored(fallback: flip-block) {
#telegram-izoh::after {
inset-block-start: auto;
inset-block-end: 100%;
translate: -50% 50%;
border: inherit;
border-block-end: 0;
border-inline-end: 0;
}
}
}interestfor— Chrome'da hover bilan ochiladi; boshqa brauzerlarda atribut e'tiborsiz qoladi vapopovertargetishlayveradi. Popover turiautoqoldi: u Baseline,Eschamma brauzerda yopadi.- Kvadrat strelka. 10 pikselli kvadrat 45° burildi; ko'rinadigan pastki-o'ng ikki cheti "V" hosil qiladi.
backgroundvaborderpopover'dan meros — qorong'i rejimda ham rang to'g'ri. margin-block: 0 0.75rem— strelka uchun joy: 6 piksellik oraliq 12 ga oshdi.flip-blockpastga o'tkazganda umargin-topga aylanadi.- Mantiqiy xususiyatlar (
inset-block-start) — portfolio Mantiqiy xususiyatlar darsidan beri shunday yoziladi.
Chrome 154 da tekshirdik: sahifa pastroqda — izoh tepada, strelka pastga; "?" ekran tepasida — izoh pastda, strelka tepaga, chegarasi bilan. Tugmaning nomi aria-label dan olinadi — "Telegram'da javob vaqti". Izoh matnini alohida tavsif qilish shart emas: u popover ochilganda o'qiladi.
8. Real ishda
- Dizayn tizimlarida tooltip, dropdown va toast — alohida komponentlar, har biri o'z qoidalari bilan. Katta kompaniyalarning dizayn tizimi hujjatlarida har biri uchun alohida sahifa bo'ladi: qachon ishlatish, qachon ishlatmaslik.
- Intervyuda so'raladi: "Tooltip'ni qanday qilib accessible qilasiz?", "Toast ekran o'quvchiga qanday eshitiladi?", "Dropdown uchun
role="menu"kerakmi?". WCAG 1.4.13 ning uch sharti varole="status"— kuchli javob. - Kod ko'rib chiqishda eng ko'p topiladigan xato — faqat
:hoverbilan qurilgan tooltip vadivichidagi "menyu". Endi ularni ko'rganingizda nima deyishni bilasiz. - Kutubxona tanlovi — jamoada "Floating UI qo'shamizmi?" degan savolga Baseline jadvali va foydalanuvchilar brauzeri bilan javob berasiz (Brauzer mosligi).
Xulosa
- Tooltip — faqat matn, sichqoncha va fokus bilan; WCAG 1.4.13:
Escbilan yopiladi, ustiga o'tsa bo'ladi, o'zi yo'qolmaydi. popover="hint"+interestfor+popovertarget+aria-describedby— yangi brauzerda to'liq tooltip, eskisida bosish bilan ochiladigan izoh.- Strelka:
::after; aylanishi —container-type: anchoredva@container anchored(fallback: flip-block), faqat Chrome'da —@supportsichida. - Dropdown —
navichidagi popover,position-area: bottom span-left/right, zaxiraflip-block, flip-inline;aria-expanded,Tabtartibi vaEscdan keyin fokus qaytishini brauzer beradi. - Toast — ekran burchagidagi doimiy
role="status"hududi, yangi xabar ro'yxat oxirida; yashirish vaqti va qo'shish — JavaScript ishi.
Keyingi dars: Tabs va accordion — details name bilan akkordeonni oxirigacha bezaymiz va tablarning CSS tomonini quramiz.
Manbalar
- W3C: "Understanding Success Criterion 1.4.13: Content on Hover or Focus" — w3.org/WAI/WCAG22/Understanding
- MDN: "Using the Popover API", "popover", "interestfor", "container-type: anchored" — developer.mozilla.org
- WHATWG HTML: "The popover attribute" — html.spec.whatwg.org
- web-features: "popover", "popover-hint", "interest-invokers", "container-anchor-position-queries" — web-platform-dx.github.io/web-features-explorer
- WAI-ARIA APG: "Tooltip Pattern", "Disclosure (Show/Hide) Pattern" — w3.org/WAI/ARIA/apg
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!