Mundarija (45)
- Bu darsda
- 1. Nega bu kerak?
- 2. APG nima?
- 2.1 Retseptlar kitobi
- 2.2 Asosiy ogohlantirish: ARIA xatti-harakat bermaydi
- 3. Birinchi qadam: native element yetarlimi?
- 3.1 Qaror jadvali
- 3.2 Native akkordeon — ARIA'siz
- 4. Fokus guruh ichida qanday yuradi
- 4.1 Roving tabindex
- 4.2 aria-activedescendant
- 4.3 Ekran o'quvchi strelkalarni kimga beradi?
- 5. Tabs
- 5.1 Qachon tabs — va qachon emas
- 5.2 HTML va ARIA tuzilmasi
- 5.3 Klaviatura
- 5.4 JavaScript nima qiladi
- 6. Akkordeon va disclosure — ARIA varianti
- 6.1 Qachon details yetmaydi
- 6.2 Mobil menyu — bu disclosure
- 7. Menyu tugmasi (menu button)
- 7.1 "Menyu" so'zining ikki ma'nosi
- 7.2 Tuzilma
- 7.3 Klaviatura
- 7.4 Popover yordam beradimi?
- 8. Combobox
- 8.1 Avval native variantlar
- 8.2 Tuzilma (ARIA 1.2)
- 8.3 Klaviatura
- 8.4 html-validate nima deydi
- 9. Karusel va boshqa patternlar
- 10. Natijani tekshirish
- 11. Ko'p uchraydigan xatolar
- 11.1 Sayt navigatsiyasida role="menu"
- 11.2 Rol bor, klaviatura yo'q
- 11.3 Holat yangilanmaydi
- 11.4 aria-controls mavjud bo'lmagan id ga
- 11.5 Hamma tabda tabindex="0" yoki umuman button emas
- 12. Mashqlar
- 1-mashq (oson): Patternni tanlang
- 2-mashq (o'rta): To'rtinchi tab
- 3-mashq (qiyin): Buzilgan combobox
- 13. Real ishda
- Xulosa
- Manbalar
ARIA Authoring Practices (APG): tabs, akkordeon, menyu tugmasi va combobox
Qisqacha: APG (ARIA Authoring Practices Guide) — W3C'ning tabs, akkordeon, menyu tugmasi, combobox kabi murakkab vidjetlar uchun tayyor "retseptlar" to'plami. Har bir retseptda uch narsa bor: qaysi
rolevaaria-*atributlar qo'yiladi, klaviaturada qaysi tugma nima qiladi va namuna kod. Avval native element (details,dialog,select) yetarlimi — shuni tekshiring. ARIA faqat vidjetning "ismini" aytadi, xatti-harakatini esa JavaScript yozadi.
Bu darsda
- APG nima ekanini va undan qanday foydalanishni bilasiz.
- Vidjet uchun avval native element, keyin ARIA pattern tanlay olasiz.
- Tabs, akkordeon, menyu tugmasi va combobox'ning HTML/ARIA tuzilmasini yoza olasiz.
- Roving tabindex va
aria-activedescendantfarqini tushuntira olasiz. role="menu"ni sayt navigatsiyasiga qo'yish nega xato ekanini bilasiz.
Oldin bilishingiz kerak: ARIA asoslari, Klaviatura va fokus boshqaruvi, Jonli hududlar va dinamik kontent, details va summary.
1. Nega bu kerak?
O'tgan darsda sahifada paydo bo'lgan xabarni ekran o'quvchiga aytdirishni o'rgandik. Endi murakkabroq vazifa.
details va summary darsida «Bahor» menyusini akkordeon qilgan edik. Endi dizayner uni qayta chizib keldi. Tepada uchta yorliq: "Issiq taomlar", "Salatlar", "Ichimliklar". Bittasini bossangiz, pastda faqat o'sha bo'lim ko'rinadi. Yonida taom qidirish maydoni, yozishingiz bilan takliflar chiqadi.
Muammo: HTML'da <tabs> degan teg yo'q. Combobox tegi ham yo'q. Dasturchi bularni div va button lardan o'zi yig'adi. «Bahor»ning doimiy mehmoni Malika NVDA ekran o'quvchisi bilan ishlaydi. U bu yig'ilgan narsani qanday "ko'radi"? Qaysi tugmani bosishi kerak?
Har dasturchi buni o'zicha hal qilsa, har saytda boshqacha bo'ladi. Malika har yangi saytda qaytadan o'rganishga majbur. Yo'l belgilarini eslang: ular dunyoning ko'p davlatida bir xil. Haydovchi notanish shaharda ham "STOP" belgisini taniydi. APG — vidjetlar uchun shunday umumiy "yo'l belgilari".
2. APG nima?
2.1 Retseptlar kitobi
APG (ARIA Authoring Practices Guide) — W3C'ning accessibility bo'limi (WAI) chiqargan qo'llanma. Manzili: w3.org/WAI/ARIA/apg. Unda 30 ga yaqin pattern (andoza) bor. Pattern — tez-tez uchraydigan vidjetni to'g'ri qurishning kelishilgan usuli.
Har bir pattern sahifasi bir xil tuzilgan:
| Bo'lim | Nima yozilgan |
|---|---|
| About This Pattern | Vidjet nima va qachon ishlatiladi |
| Keyboard Interaction | Qaysi tugma nima qiladi |
| Roles, States, and Properties | Qaysi role va aria-* kerak |
| Examples | Ishlaydigan namuna (HTML + CSS + JS) |
Ekran o'quvchilar va brauzerlar aynan shu kelishuvga moslashgan. Siz patternga amal qilsangiz, Malika sizning tablaringizni boshqa saytdagi tablar kabi boshqaradi.
2.2 Asosiy ogohlantirish: ARIA xatti-harakat bermaydi
ARIA asoslari darsidagi fikrni eslang: ARIA faqat va'da beradi. role="tab" yozsangiz, ekran o'quvchi "tab" deb e'lon qiladi. Malika o'ng strelkani bosadi va keyingi tabga o'tishni kutadi. JavaScript yozilmagan bo'lsa, hech narsa bo'lmaydi.
Ya'ni yarim ish qilingan vidjet ARIA'siz vidjetdan ham yomonroq: u yolg'on va'da beradi. APG'ning kirish sahifasi ham shuni aytadi: "ARIA'siz yaxshi, yomon ARIA'dan ko'ra".
Bu darsda har patternning HTML va ARIA qismini yozamiz va klaviatura qoidalarini o'rganamiz. Tugmalarni "jonlantiradigan" JavaScript — keyinroq, Dinamik UI'da qulaylik darsida. CSS tomoni — Tabs va accordion darsida.
Tekshirib ko'ring: Dasturchi
divlargarole="tab"vaaria-selectedqo'ydi, lekin JavaScript yozmadi. Ekran o'quvchi foydalanuvchisi uchun natija qanday?
Javob
Yomon. Ekran o'quvchi "tab, 3 dan 1" deb e'lon qiladi — foydalanuvchi strelkalar ishlaydi deb o'ylaydi. Strelkalar esa hech narsa qilmaydi, tanlangan tab ham o'zgarmaydi. Rol va'da berdi, lekin uni bajaradigan kod yo'q.
3. Birinchi qadam: native element yetarlimi?
3.1 Qaror jadvali
ARIA'ning birinchi qoidasi: mos HTML element bo'lsa — o'shani ishlating. Native elementda klaviatura, fokus va ekran o'quvchi bilan ishlash tayyor, bepul. Ko'p APG patternlarining HTML'da tayyor muqobili bor:
| Vidjet | Native muqobil | ARIA kerakmi? |
|---|---|---|
| Disclosure (ochiladigan blok) | details + summary |
Deyarli hech qachon |
| Akkordeon (bittasi ochiq) | details name="..." |
Kamdan-kam |
| Modal oyna | dialog |
Yo'q |
| Tanlash ro'yxati | select |
Yo'q |
| Takliflar bilan maydon | input + datalist |
Ba'zan |
| O'chirgich (switch) | input type="checkbox" |
Yo'q |
| Tabs | yo'q | Ha |
| Menyu tugmasi | popover qisman |
Ha |
| Karusel | yo'q | Ha |
details ni details va summary, dialog ni dialog, datalist ni tanlash maydonlari darsida o'rgandik.
3.2 Native akkordeon — ARIA'siz
details va summary darsidagi «Bahor» menyusini eslang. Uchta details bir xil name="menyu" bilan — va bir vaqtda faqat bittasi ochiq. Bu APG'ning akkordeon patternining aynan o'zi.
Farqi — unda bitta ham aria- atributi va bitta ham qator JavaScript yo'q. Klaviatura (Tab, Enter, Space), "ochiq/yopiq" holati, ekran o'quvchi e'loni — hammasini brauzer o'zi beradi. APG patternini qo'lda yig'sangiz, shu ishlarning hammasini o'zingiz yozasiz.
Demak, dizayner tablarni chizgan bo'lsa ham, avval so'raymiz: "akkordeon ham yaraydimi?". Yaraydigan bo'lsa — native qoladi. Bizning holatda buyurtmachi aynan tablarni xohladi. Shuning uchun davom etamiz.
Maslahat: html-validate'da
prefer-native-elementdegan qoida bor.role="button"yokirole="listbox"ko'rsa, "nativebutton/selectni ishlating" deb xato beradi. Bu — ARIA'ning birinchi qoidasi, vositaga aylantirilgan.
Tekshirib ko'ring: Mijoz "Batafsil" tugmasini bosganda taom tarkibi ochilishini xohlaydi. Qaysi pattern va qaysi HTML?
Javob
Bu disclosure (ochiladigan blok) patterni. Eng yaxshi yechim — details va summary: summary ichida "Tarkibi", details ichida tarkib ro'yxati. ARIA ham, JavaScript ham kerak emas.
4. Fokus guruh ichida qanday yuradi
Murakkab vidjetlarda fokus ikki xil usulda boshqariladi. Patternlarni o'qishdan oldin ikkalasini tanib oling.
4.1 Roving tabindex
APG'ning umumiy qoidasi: vidjet — bitta Tab to'xtashi. Tab guruhga bir marta kiradi, guruh ichida esa strelkalar yuradi. O'nta tabdan o'tish uchun Tab ni o'n marta bosish kerak bo'lmasin.
Buning usulini Klaviatura va fokus darsida filtr tugmalari misolida ko'rgan edik — roving tabindex (ko'chib yuruvchi tabindex):
- faol elementda
tabindex="0"—Tabshunga tushadi; - qolganlarida
tabindex="-1"—Tabularni o'tkazib yuboradi; - strelka bosilganda JavaScript
0ni keyingi elementga ko'chiradi va fokusni unga beradi.
Estafeta tayoqchasiga o'xshaydi: jamoada to'rt yuguruvchi bor, lekin tayoqcha bittasining qo'lida. O'sha darsda "to'liq pattern rollar bilan keyinroq" degan edik — mana, o'sha payt keldi.
4.2 aria-activedescendant
Combobox'da boshqa muammo bor. Malika maydonga "osh" deb yozyapti, pastda takliflar chiqdi. U strelka bilan takliflar bo'ylab yuradi — lekin yozishni davom ettirishi ham kerak. Fokus maydondan ketib qolsa, yozib bo'lmaydi.
Yechim — aria-activedescendant ("faol avlod"). Haqiqiy fokus maydonda qoladi. Atribut esa ro'yxatdagi qaysi band "hozir tanlangan"ini id orqali ko'rsatadi:
<input id="taom-qidir" type="text" role="combobox"
aria-activedescendant="taklif-2" ...>Ekran o'quvchi taklif-2 elementini xuddi fokus unda turgandek o'qiydi.
| Roving tabindex | aria-activedescendant |
|
|---|---|---|
| Haqiqiy fokus | Band o'zida | Konteyner yoki maydonda |
| Qayerda | Tabs, menyu, toolbar | Combobox, listbox |
| JS nima qiladi | tabindex ni ko'chiradi |
id ni almashtiradi |
4.3 Ekran o'quvchi strelkalarni kimga beradi?
Bir mayda, lekin muhim detal. NVDA kabi ekran o'quvchilar oddiy sahifada strelkalarni o'zi ishlatadi — matnni qatorma-qator o'qish uchun. Sahifa strelka bosilganini bilmaydi ham.
Fokus role="tablist", menu yoki listbox ichiga tushganda, ekran o'quvchi "bu vidjet, strelkalarni unga beraman" deb fokus rejimiga o'tadi. Ya'ni to'g'ri rol — sizning JavaScript'ingiz strelkani umuman "eshitishi" uchun ham kerak.
5. Tabs
5.1 Qachon tabs — va qachon emas
Tabs — bir joyda bir nechta panel, bir vaqtda faqat bittasi ko'rinadi. Panellar qisqa va teng huquqli bo'lganda mos keladi: menyu bo'limlari, "Tavsif / Tarkib / Sharhlar".
Tabga o'xshagan, lekin alohida sahifalarga olib boradigan yorliqlar esa tabs emas. Ular — navigatsiya: nav ichidagi havolalar va faol sahifada aria-current="page". Buni ko'p sahifali sayt darsida qilgan edik. Havola bosilsa URL o'zgaradi, tab bosilsa — o'zgarmaydi. Mana shu farq.
5.2 HTML va ARIA tuzilmasi
«Bahor» menyusining uchta bo'limi:
<div role="tablist" aria-label="Menyu bo'limlari">
<button type="button" role="tab" id="tab-issiq"
aria-selected="true"
aria-controls="panel-issiq">Issiq taomlar</button>
<button type="button" role="tab" id="tab-salat"
aria-selected="false" tabindex="-1"
aria-controls="panel-salat">Salatlar</button>
<button type="button" role="tab" id="tab-ichimlik"
aria-selected="false" tabindex="-1"
aria-controls="panel-ichimlik">Ichimliklar</button>
</div>
<div role="tabpanel" id="panel-issiq"
aria-labelledby="tab-issiq" tabindex="0">
<ul>
<li>Osh — 35 000</li>
<li>Lag'mon — 28 000</li>
</ul>
</div>
<div role="tabpanel" id="panel-salat"
aria-labelledby="tab-salat" tabindex="0" hidden>
<ul>
<li>Achchiq-chuchuk — 12 000</li>
<li>Vinegret — 15 000</li>
</ul>
</div>
<div role="tabpanel" id="panel-ichimlik"
aria-labelledby="tab-ichimlik" tabindex="0" hidden>
<ul>
<li>Ko'k choy (choynak) — 5 000</li>
<li>Kompot (1 litr) — 8 000</li>
</ul>
</div>Qatorma-qator:
role="tablist"— "bu tablar guruhi".aria-labelguruhga nom beradi: ekran o'quvchi "Menyu bo'limlari, tab ro'yxati" deydi.button+role="tab"— negadivemas?buttonfokus oladi vaEnter/Spaceni o'zi tushunadi. Yarim ish tayyor.aria-selected="true"— hozir tanlangan tab. Qolganlarida"false".tabindex="-1"— tanlanmagan tablarda. Bu — roving tabindex:Tabfaqat tanlangan tabga tushadi.aria-controls— "bu tab qaysi panelni boshqaradi", panelningidsi.role="tabpanel"+aria-labelledby— panelning nomi uning tabidan olinadi: "Issiq taomlar, tab paneli".tabindex="0"panelda — panel ichida havola yoki tugma bo'lmasa,Tabpanelning o'ziga tushsin. Aks holda Malika tabdan keyin to'g'ridan-to'g'ri sahifaning keyingi qismiga "sakrab" ketadi.hidden— ko'rinmaydigan panellar. Tab almashganda JavaScript uni olib tashlaydi.
Ekran o'quvchi ikkinchi tabda taxminan shunday deydi: "Salatlar, tab, tanlanmagan, 3 dan 2". Tartib raqamini ("3 dan 2") brauzer DOM'dan o'zi hisoblaydi.
5.3 Klaviatura
| Tugma | Nima bo'ladi |
|---|---|
Tab |
Tanlangan tabga kiradi; keyingi Tab — panelga |
→ / ← |
Keyingi / oldingi tab (oxiridan boshiga aylanadi) |
Home / End |
Birinchi / oxirgi tab |
Enter / Space |
Tabni faollashtiradi (qo'lda rejimda) |
APG ikki rejimni tasvirlaydi. Avtomatik rejimda strelka bosilishi bilan panel ham almashadi. Qo'lda rejimda strelka faqat fokusni ko'chiradi, panel Enter dan keyin almashadi. Panel tez chiqsa — avtomatik, har tab serverdan yuklansa — qo'lda. Tablar vertikal joylashsa, aria-orientation="vertical" qo'yiladi va ↑/↓ ishlaydi.
5.4 JavaScript nima qiladi
Kod keyinroq, lekin vazifalar ro'yxati hozirdan aniq. Tab almashganda JavaScript:
- yangi tabda
aria-selected="true", eskisida"false"qiladi; tabindexni ko'chiradi: yangisida0, eskisida-1;- yangi panelning
hiddenini olib tashlaydi, eskisiga qo'yadi; - strelka bosilganda fokusni yangi tabga beradi.
Uchta atribut va bitta fokus. Ro'yxatning birortasi unutilsa, vidjet "yolg'on" gapira boshlaydi.
Tekshirib ko'ring: Nega tanlanmagan tablarda
tabindex="-1"turibdi? Olib tashlasak nima bo'ladi?
Javob
Olib tashlasak, har bir tab alohida Tab to'xtashi bo'ladi: Malika vidjetdan o'tish uchun Tab ni uch marta bosadi. APG qoidasi — vidjet bitta to'xtash, ichida strelkalar. tabindex="-1" tablarni Tab tartibidan chiqaradi, lekin JavaScript ularga fokusni baribir bera oladi.
6. Akkordeon va disclosure — ARIA varianti
6.1 Qachon details yetmaydi
90% holatda details yetadi. ARIA varianti kerak bo'ladigan holatlar kam: masalan, dizayn tizimi hamma bo'limlar birdaniga ochilishini boshqarishi yoki tugma sarlavha ichida turishi shart bo'lsa.
APG akkordeoni shunday tuziladi:
<h3>
<button type="button" aria-expanded="false"
aria-controls="tarkib-osh" id="tugma-osh">
Osh tarkibi
</button>
</h3>
<section id="tarkib-osh" aria-labelledby="tugma-osh" hidden>
<p>Guruch, sabzi, mol go'shti, zig'ir yog'i.</p>
</section>buttonsarlavha ichida. Ekran o'quvchi foydalanuvchilari sahifani sarlavhalar bo'yicha aylanadi. Tugma sarlavhada tursa, har bo'lim sarlavhalar ro'yxatida ko'rinadi.aria-expanded— ochiq ("true") yoki yopiq ("false"). JavaScript unihiddenbilan birga almashtiradi.section+aria-labelledby— APG panelgarole="region"berishni taklif qiladi. Nomlisectionesa shu rolni o'zi oladi —article,sectionyokidivdarsida ko'rgandik. Yana native element g'alaba qildi:div role="region"yozsangiz, html-validate "nativesectionni ishlating" deydi. Bo'limlar oltitadan ko'p bo'lsa, hudud (region) qilmang — ular hududlar ro'yxatini to'ldirib yuboradi.
Klaviatura: Enter va Space — ochish/yopish, Tab — keyingi tugma. Bu tugmaning o'z xatti-harakati — ARIA'siz ham ishlaydi.
6.2 Mobil menyu — bu disclosure
Telefonda «Bahor» saytining menyusi ☰ tugmasi ortida yashiringan. Tugma bosilsa — havolalar ro'yxati ochiladi. Bu disclosure:
<nav aria-label="Asosiy">
<button type="button" aria-expanded="false"
aria-controls="asosiy-menyu">Menyu</button>
<ul id="asosiy-menyu" hidden>
<li><a href="/">Bosh sahifa</a></li>
<li><a href="/menyu.html">Taomlar</a></li>
<li><a href="/bron.html">Stol band qilish</a></li>
</ul>
</nav>Oddiy ro'yxat, oddiy havolalar, bitta aria-expanded. Qolgan hamma narsani Tab va Enter o'zi qiladi.
7. Menyu tugmasi (menu button)
7.1 "Menyu" so'zining ikki ma'nosi
Diqqat: ARIA'dagi
role="menu"— sayt menyusi emas! U kompyuter dasturlaridagi menyu: "Fayl → Saqlash, Chop etish". Ya'ni amallar ro'yxati.role="menu"qo'yilgan joyda ekran o'quvchi strelkalar bilan boshqaruvni kutadi vaTabishlamaydi deb hisoblaydi. Sayt navigatsiyasiga qo'ysangiz, Malika havolalarga yetib bora olmay qoladi.
Qoida oddiy: havolalar ro'yxati — nav, amallar ro'yxati — menu.
7.2 Tuzilma
«Bahor» admin panelida har buyurtma yonida "Amallar" tugmasi bor. U ochadigan ro'yxatda uchta amal: takrorlash, chekni yuklab olish, bekor qilish. Bu — haqiqiy menyu:
<button type="button" id="amal-tugma"
aria-haspopup="true" aria-expanded="false"
aria-controls="amal-menyu">Amallar</button>
<ul role="menu" id="amal-menyu"
aria-labelledby="amal-tugma" hidden>
<li role="menuitem" tabindex="-1">Takrorlash</li>
<li role="menuitem" tabindex="-1">Chekni yuklab olish</li>
<li role="menuitem" tabindex="-1">Bekor qilish</li>
</ul>aria-haspopup="true"— "bu tugma menyu ochadi"."menu"qiymati ham xuddi shu ma'noni beradi. Ekran o'quvchi "Amallar, menyu tugmasi" deydi.aria-expanded— menyu ochiqmi.role="menu"varole="menuitem"— ro'yxat va uning bandlari.lining o'z ma'nosi ("ro'yxat bandi") rol bilan almashtirildi.tabindex="-1"— bandlarga faqat JavaScript fokus beradi.
7.3 Klaviatura
| Tugma | Qayerda | Nima bo'ladi |
|---|---|---|
Enter, Space, ↓ |
Tugmada | Menyuni ochadi, birinchi bandga fokus |
↑ |
Tugmada | Menyuni ochadi, oxirgi bandga fokus |
↓ / ↑ |
Menyuda | Keyingi / oldingi band |
Home / End |
Menyuda | Birinchi / oxirgi band |
Esc |
Menyuda | Yopadi, fokus tugmaga qaytadi |
| Harf | Menyuda | Shu harf bilan boshlanadigan band |
Oxirgi qator — "typeahead" (yozib qidirish): B bosilsa "Bekor qilish" ga o'tadi. Esc dan keyin fokusni tugmaga qaytarish — Klaviatura va fokus darsidagi "fokusni qaytarish" qoidasining o'zi.
7.4 Popover yordam beradimi?
Popover API ochish, yopish va Esc bilan yopishni JavaScript'siz beradi. Bu menyuning yarmi. Lekin strelkalar, typeahead va rollarni popover bermaydi. Shuning uchun real hayotda popover + ARIA + kichik JavaScript birga ishlaydi.
Tekshirib ko'ring: Sayt sarlavhasida "Biz haqimizda", "Menyu", "Aloqa" havolalari bor. Dasturchi ularni
role="menu"ichiga soldi. Nima deysiz?
Javob
Xato. Bu amallar emas, havolalar — demak, nav ichidagi oddiy ro'yxat. role="menu" ekran o'quvchini "strelkalar bilan boshqariladigan dastur menyusi" deb aldaydi va JavaScript yozilmagan bo'lsa, foydalanuvchi havolalarga yetib bora olmaydi.
8. Combobox
8.1 Avval native variantlar
Combobox — matn maydoni va unga ulangan ochiladigan takliflar ro'yxati. Kundalik misol — Yandex Go'da manzil yozish: "Chil" deysiz, "Chilonzor" chiqadi.
Native variantlarni eslang:
select— faqat tanlash, yozish yo'q.input+datalist— yozish va takliflar. Lekin ro'yxat ko'rinishini boshqarib bo'lmaydi va u har brauzerda boshqacha.- Customizable select — ko'rinish boshqariladi, lekin yozib qidirish yo'q.
Ro'yxatda narx, rasm ko'rsatish yoki serverdan qidirish kerak bo'lsa — ARIA combobox.
8.2 Tuzilma (ARIA 1.2)
Malika "osh" deb yozdi, ikkita taklif chiqdi, u ↓ ni ikki marta bosdi:
<label for="taom-qidir">Taom qidirish</label>
<input id="taom-qidir" type="text" role="combobox"
aria-autocomplete="list" aria-expanded="true"
aria-controls="taom-takliflar"
aria-activedescendant="taklif-2">
<!-- [html-validate-disable-next prefer-native-element] -->
<ul id="taom-takliflar" role="listbox" aria-label="Taomlar">
<li id="taklif-1" role="option"
aria-selected="false">Osh — 35 000 so'm</li>
<li id="taklif-2" role="option"
aria-selected="true">Oshqovoq somsa — 7 000 so'm</li>
</ul>
<p role="status">2 ta taom topildi</p>role="combobox"— to'g'ridan-to'g'riinputda.label— o'zgarmagan, oddiy label.aria-autocomplete="list"— "yozganingizga qarab takliflar ro'yxati chiqadi". Boshqa qiymatlar:none(ro'yxat yozuvga bog'liq emas),inline(maydonning o'zida davomi yoziladi),both(ikkalasi).aria-expanded— ro'yxat ochiqmi.aria-controls— ro'yxatningidsi.aria-activedescendant— hozir belgilangan taklif. Fokus esa maydonda qoladi.role="listbox"varole="option"— takliflar ro'yxati va uning bandlari.aria-selected="true"— belgilangan band.role="status"— natijalar soni. Uni jonli hududlar darsidan bilasiz: ekran o'quvchi "2 ta taom topildi" deb o'zi aytadi.
Maslahat: Eski kodda boshqa tuzilmani uchratasiz:
role="combobox"maydonni o'rab turgandivga qo'yilgan. Bu — ARIA 1.1 dagi eski pattern. Yangi kodda rol maydonning o'zida bo'ladi.
8.3 Klaviatura
| Tugma | Nima bo'ladi |
|---|---|
| Harf yozish | Maydonga yoziladi, ro'yxat yangilanadi |
↓ / ↑ |
Keyingi / oldingi taklif (fokus maydonda qoladi) |
Alt + ↓ |
Ro'yxatni ochadi, taklifni belgilamaydi |
Enter |
Belgilangan taklif maydonga yoziladi, ro'yxat yopiladi |
Esc |
Ro'yxatni yopadi; ikkinchi Esc — maydonni tozalaydi |
8.4 html-validate nima deydi
Yuqoridagi koddagi <!-- [html-validate-disable-next ...] --> izohiga e'tibor bering. Usiz html-validate shunday yozadi:
6:25 error Prefer to use the native <select> element prefer-native-elementTarjimasi: "native select elementini ishlatgan ma'qul". Qoida to'g'ri gapiryapti — oddiy holatda select yaxshiroq. Bizda esa yozib qidirish kerak, select bunga yaramaydi. Bunday ongli istisnoda qoidani faqat keyingi qator uchun o'chirasiz va sababini izohda yozasiz. Butun loyihada o'chirib qo'yish esa xato bo'lardi.
Tekshirib ko'ring: Nega combobox'da roving tabindex emas,
aria-activedescendantishlatiladi?
Javob
Chunki foydalanuvchi takliflar bo'ylab yurib turib, yozishni ham davom ettiradi. Roving tabindex haqiqiy fokusni ro'yxat bandiga ko'chirardi — maydonga yozib bo'lmay qolardi. aria-activedescendant bilan fokus maydonda qoladi, ekran o'quvchi esa belgilangan taklifni o'qiydi.
9. Karusel va boshqa patternlar
Karusel — bir-birini almashtiradigan slaydlar ("Bugungi taklif", "Juma kuni osh"). U eng muammoli vidjetlardan biri:
- avtomatik aylansa, 5 soniyadan uzoq harakat uchun to'xtatish tugmasi majburiy (WCAG talabi);
- fokus yoki sichqoncha ustiga kelganda aylanish to'xtashi kerak;
- ko'pchilik foydalanuvchi ikkinchi slaydgacha ham yetib bormaydi.
Tuzilma g'oyasi: umumiy konteynerda aria-roledescription="karusel" va aria-label. Har slaydda role="group", aria-roledescription="slayd" va aria-label="3 dan 1". aria-roledescription — rolning o'qiladigan nomini almashtiradi. Uni faqat shunday joylarda ishlating: boshqa hamma joyda u ekran o'quvchi uchun tanish rol nomini buzadi.
APG'da yana tooltip, slider, treeview, grid, toolbar, feed patternlari bor. Ularning hammasini yod olish shart emas. Qoida: yangi vidjet yasashdan oldin APG'dan uning sahifasini ochib o'qing.
10. Natijani tekshirish
Yozgan tuzilmangizni ikki usulda tekshiring:
- DevTools → Elements → Accessibility paneli. Tabni tanlang: Role —
tab, Name — "Salatlar", holatlar orasidaselected: false. Bu panelni Accessibility daraxti darsida o'rgangan edik. - html-validate —
no-missing-referencesqoidasi bilan. Uaria-controlsvaaria-labelledbydagi mavjud bo'lmaganidlarni topadi (sozlamasi pastda, xatolar bo'limida).
Haqiqiy ekran o'quvchi bilan tekshirish — Accessibility'ni tekshirish darsida.
11. Ko'p uchraydigan xatolar
11.1 Sayt navigatsiyasida role="menu"
Eng keng tarqalgan xato — yuqorida ko'rdik. Tuzatish: nav + ul + havolalar. Ochiladigan bo'lsa — disclosure (button aria-expanded).
11.2 Rol bor, klaviatura yo'q
role="tab" qo'yilgan, JavaScript esa faqat sichqoncha bosishini tinglaydi. Tuzatish: APG'ning Keyboard Interaction jadvalini to'liq bajaring. Bajara olmasangiz — rollarni ham qo'ymang, oddiy tugmalar qoldiring.
11.3 Holat yangilanmaydi
Panel almashdi, lekin aria-selected birinchi tabda "true" bo'lib qoldi. Ko'rgan odam farqni sezmaydi, ekran o'quvchi esa noto'g'ri tabni "tanlangan" deydi. Tuzatish: har o'zgarishda holat atributlari ham yangilanadi ("JavaScript nima qiladi" ro'yxati).
11.4 aria-controls mavjud bo'lmagan id ga
Nomda xato (panel-isiq) — aloqa uziladi. Tavsiya etilgan to'plam buni tekshirmaydi, shuning uchun .htmlvalidate.json ga qoidani qo'shing:
{
"extends": ["html-validate:recommended"],
"rules": {
"no-missing-references": "error"
}
}Shunda xato aniq ko'rinadi:
4:26 error Element references missing id "panel-isiq" no-missing-referencesTarjimasi: "element mavjud bo'lmagan panel-isiq id'siga murojaat qilyapti". 4:26 — 4-qator, 26-belgi: aynan aria-controls qiymati turgan joy.
11.5 Hamma tabda tabindex="0" yoki umuman button emas
div role="tab" + tabindex yo'q — klaviatura bilan tabga umuman yetib bo'lmaydi. Hammasida tabindex="0" — vidjet besh-oltita Tab to'xtashiga aylanadi. Tuzatish: button + roving tabindex.
12. Mashqlar
1-mashq (oson): Patternni tanlang
Har vaziyat uchun eng yaxshi yechimni yozing: native element (qaysi) yoki APG pattern (qaysi).
- Taom kartasida "Tarkibini ko'rsatish" tugmasi.
- Profil sahifasida "Ma'lumotlar / Buyurtmalar / Sozlamalar" yorliqlari, bittasi ko'rinadi, URL o'zgarmaydi.
- Sayt tepasidagi "Bosh sahifa, Menyu, Aloqa" havolalari.
- Buyurtma yonidagi
⋮tugmasi: "Tahrirlash", "Nusxa olish", "O'chirish". - Viloyatni tanlash — 14 ta variant, yozib qidirish shart emas.
Yechim
- Disclosure →
details+summary. - Tabs →
tablist,tab,tabpanel(ARIA kerak). - Navigatsiya →
nav+ ro'yxat + havolalar. Menyu emas! - Menyu tugmasi →
button aria-haspopup+role="menu"— bu haqiqiy amallar ro'yxati. select— native element yetarli.
Beshtadan faqat ikkitasida ARIA kerak bo'ldi. Real loyihalarda nisbat taxminan shunday.
2-mashq (o'rta): To'rtinchi tab
«Bahor» menyusiga "Shirinliklar" bo'limi qo'shildi. To'rtinchi tab va paneli uchun HTML yozing. Tab tanlanmagan. Tabning id si tab-shirin, panelniki panel-shirin. Panelda "Chak-chak — 15 000".
Ishora: tanlanmagan tabda ikki atribut bor — aria-selected="false" va tabindex ning qiymati . Panel esa hidden.
Yechim
<button type="button" role="tab" id="tab-shirin"
aria-selected="false" tabindex="-1"
aria-controls="panel-shirin">Shirinliklar</button>Bu tugma tablist ichiga, oxirgi tabdan keyin qo'yiladi. Panel — boshqa panellar yoniga:
<div role="tabpanel" id="panel-shirin"
aria-labelledby="tab-shirin" tabindex="0" hidden>
<ul>
<li>Chak-chak — 15 000</li>
</ul>
</div>Tab va panel bir-biriga ikki tomonlama bog'langan: tab aria-controls bilan panelni, panel aria-labelledby bilan tabni ko'rsatadi. Ekran o'quvchi endi "4 dan 4" deydi — sonni brauzer o'zi yangiladi.
3-mashq (qiyin): Buzilgan combobox
Stajyor filial tanlash maydonini yozdi. Unda beshta xato bor. Toping va tuzatilgan variantni yozing.
<div role="combobox">
<input id="filial" type="text"
aria-controls="filiallar">
</div>
<ul id="filial-royxat" role="menu">
<li role="menuitem">Chilonzor</li>
<li role="menuitem">Yunusobod</li>
</ul>Eslatma: yorliq, role joyi, ro'yxat roli, aria-controls va holat atributiga qarang.
Yechim
labelyo'q — maydonning nomi yo'q.role="combobox"o'rab turgandivda — bu eski ARIA 1.1 usuli. Rolinputning o'zida bo'ladi.aria-controls="filiallar", ro'yxatningidsi esafilial-royxat— aloqa uzilgan.- Ro'yxat
role="menu"— takliflar amallar emas.listboxvaoptionbo'lishi kerak. aria-expandedyo'q — ekran o'quvchi ro'yxat ochiq-yopiqligini bilmaydi.
<label for="filial">Filial</label>
<input id="filial" type="text" role="combobox"
aria-autocomplete="list" aria-expanded="false"
aria-controls="filial-royxat">
<!-- [html-validate-disable-next prefer-native-element] -->
<ul id="filial-royxat" role="listbox" aria-label="Filiallar"
hidden>
<li id="filial-1" role="option"
aria-selected="false">Chilonzor</li>
<li id="filial-2" role="option"
aria-selected="false">Yunusobod</li>
</ul>Yana bir savol bering: filiallar faqat ikkita bo'lsa, combobox umuman kerakmi? Ikki variant uchun ikki radio tugma yoki select ancha sodda va ishonchli.
13. Real ishda
- Headless kutubxonalar. Radix, React Aria, Headless UI kabi kutubxonalar APG patternlarini tayyor holda beradi: rollar, holatlar, klaviatura — hammasi ichida. Ularni UI kutubxonalar xaritasi va Radix Primitives darslarida ko'ramiz. Kutubxonani tanlashda birinchi savol: "APG'ga amal qiladimi?"
- Testlar rol bo'yicha. React Testing Library elementni
getByRole("tab", { name: "Salatlar" })kabi topadi. To'g'ri rollar — ham accessibility, ham ishonchli testlar. Buni RTL darsida ko'rasiz. - Kod review. Tajribali dasturchi
role="menu"ni ko'rsa, darhol "bu haqiqiy menyumi yoki navigatsiya?" deb so'raydi. - Intervyu. "Tabs'ni accessible qilib qanday yasaysiz?" — frontend intervyularida uchraydi. Yaxshi javob: rollar,
aria-selected, roving tabindex, strelkalar, APG'ga havola.
Xulosa
- APG — tabs, menyu, combobox kabi vidjetlar uchun rol, holat va klaviatura qoidalari yozilgan W3C qo'llanmasi.
- Avval native element:
details,details name,dialog,select,datalist. ARIA — faqat ular yetmaganda. - Vidjet — bitta
Tabto'xtashi; ichida strelkalar. Usullari: roving tabindex yokiaria-activedescendant. role="menu"— amallar uchun, sayt navigatsiyasi uchun emas.- ARIA faqat va'da beradi: holatlar (
aria-selected,aria-expanded) va klaviaturani JavaScript bajaradi.
Keyingi dars: Kontent accessibility'si — kod emas, matnning o'zi: oddiy til, sarlavhalar, havola matni, rang va harakat.
Manbalar
- W3C WAI: "ARIA Authoring Practices Guide (APG)" — Patterns, "Read Me First" — w3.org/WAI/ARIA/apg
- W3C: "WAI-ARIA 1.2" — w3.org/TR/wai-aria-1.2
- MDN: "ARIA: tab role", "ARIA: combobox role" — developer.mozilla.org
- html-validate: "prefer-native-element", "no-missing-references" — html-validate.org
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!