Seriya: HTML Basics Dars 9

ARIA — Semantics, Name, State, Patterns

ARIA qachon kerak va qachon zarar ekanini o'rganing, accessible name va state'ni to'g'ri boshqarishni va ARIA'ning 3 ta oltin qoidasini tushunish. ARIA interaktivlik bermaydi—faqat screen reader'ga ma'lumot beradi.

9-dars

ARIA — Semantics, Name, State, Patterns

🎯 Maqsad: ARIA'ni "yopishtirish" emas, qachon kerak / qachon zarar ekanini bilish, va accessible name + state ni to'g'ri boshqarish.

0️⃣ ARIA'ning 3 ta oltin qoidasi

Qoida 1: Avval HTML (Native element bo'lsa ARIA ishlatma)

<!-- ✅ To'g'ri -->
<button>Save</button>

<!-- ❌ Noto'g'ri -->
<div role="button">Save</div>

Native HTML elementlar o'zida accessibility, keyboard qo'llab-quvvatlash va semantics'ga ega. ARIA faqat native elementlar mavjud bo'lmaganda ishlatilishi kerak.

Qoida 2: ARIA interaktivlik bermaydi

ARIA faqat screen reader'ga ma'lumot beradi. U quyidagilarni qilmaydi:

  • Tab fokus qo'shmaydi
  • Enter/Space behavior bermaydi
  • Click funksiyasini bermaydi
  • UI'ni "accessible" qilib qo'ymaydi

Keyboard behavior va interaktivlikni JavaScript bilan implement qilish kerak.

Qoida 3: ARIA state'lar JS bilan sync bo'lishi shart

Agar aria-expanded="true" qo'ysangiz, lekin UI panel yopiq ko'rsatsa, yolg'on UI yaratdingiz. Screen reader foydalanuvchilari chalkashadi.

// ✅ To'g'ri: State UI bilan sync
button.setAttribute('aria-expanded', isOpen ? 'true' : 'false');

// ❌ Noto'g'ri: State UI bilan mos kelmaydi
button.setAttribute('aria-expanded', 'true'); // Lekin panel yopiq!

1️⃣ ARIA nima qiladi, nima qilmaydi

ARIA qiladi:

  • Element "kim" ekanini aytadi (role)
  • Holatini aytadi (state)
  • Bog'lanishlarini aytadi (property)
  • Screen reader o'qiydigan nom/izohni boshqaradi

ARIA qilmaydi:

  • ❌ Tab fokus qo'shmaydi
  • ❌ Enter/Space behavior bermaydi
  • ❌ Click ishlatib bermaydi
  • ❌ UI'ni "accessible" qilib qo'ymaydi (faqat xabar beradi)

2️⃣ ARIA'ning tuzilishi: Role / State / Property

A) role — "bu nima?"

role screen reader'ga element nima ekanligini aytadi.

Keng tarqalgan role'lar:

  • role="navigation"
  • role="dialog"
  • role="tablist"
  • role="tab"
  • role="tabpanel"
  • role="menu"
  • role="menuitem"
  • role="listbox"
  • role="option"
  • role="switch"

Qoidasi: role faqat native HTML yo'q bo'lsa ishlatiladi.

<!-- ✅ To'g'ri: Custom tabs -->
<div role="tablist">
  <button role="tab">Tab 1</button>
  <button role="tab">Tab 2</button>
</div>
<div role="tabpanel">Content</div>

<!-- ❌ Noto'g'ri: Native button mavjud -->
<div role="button">Click me</div>
<!-- <button>Click me</button> bo'lishi kerak -->

B) state — "hozir holati qanday?"

State elementning hozirgi holatini tasvirlaydi.

Keng tarqalgan state'lar:

  • aria-expanded="true|false" (ochiq/yopiq)
  • aria-checked="true|false" (checkbox/switch)
  • aria-selected="true|false" (tabs/options)
  • aria-pressed="true|false" (toggle button)
  • aria-disabled="true" (o'chirilgan)
  • aria-hidden="true" (screen reader'dan yashirish)

Qoidasi: State har doim real UI bilan bir xil bo'lishi kerak (JS bilan sync).

<!-- ✅ To'g'ri: State UI bilan mos -->
<button aria-expanded="true" aria-controls="panel">
  Open Panel
</button>
<div id="panel">Content</div>

<script>
  button.addEventListener('click', () => {
    const isOpen = panel.classList.toggle('open');
    button.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
  });
</script>

C) property — "nimalar bilan bog'langan?"

Property bog'lanishlar va qo'shimcha ma'lumotlarni tasvirlaydi.

Keng tarqalgan property'lar:

  • aria-controls="id" (qaysi panelni boshqaradi)
  • aria-labelledby="id" (nomini qayerdan oladi)
  • aria-describedby="id" (izoh qayerdan)
  • aria-live="polite|assertive" (dynamic xabarlar)
  • aria-modal="true" (modal context)
  • aria-current="page" (nav'da current page)

3️⃣ Accessible Name (Eng muhim mavzu)

Screen reader elementni o'qiganda 1-chi savol: "nomi nima?"

Name berish tartibi (amaliy qoida)

  1. Visible text (masalan, button ichidagi "Save")
  2. aria-labelledby="id" (tashqaridagi matndan nom olish)
  3. aria-label="..." (so'nggi chora)

Qoidasi:

  • Ko'rinadigan label bor bo'lsaaria-labelledby
  • Visible label yo'q bo'lsa (faqat icon) → aria-label
<!-- ✅ To'g'ri: Ko'rinadigan label -->
<button aria-labelledby="save-label">
  <span id="save-label">Save</span>
</button>

<!-- ✅ To'g'ri: Faqat icon -->
<button aria-label="Save">
  <svg>...</svg>
</button>

<!-- ❌ Noto'g'ri: Accessible name yo'q -->
<button>
  <svg>...</svg>
</button>

aria-labelledby vs aria-describedby

  • aria-labelledby → nom ("bu nima?")
  • aria-describedby → izoh ("qo'shimcha info")
<button aria-labelledby="btn-name" aria-describedby="btn-desc">
  <span id="btn-name">Submit</span>
</button>
<span id="btn-desc">Bu form ma'lumotlaringizni yuboradi</span>

Screen reader: "Submit, button. Bu form ma'lumotlaringizni yuboradi"

4️⃣ Eng ko'p ishlatiladigan ARIA'lar (cheat-sheet)

Toggle / Dropdown / Filter panel

<button 
  aria-expanded="false" 
  aria-controls="panel"
  id="toggle-btn"
>
  Toggle Panel
</button>
<div id="panel" aria-labelledby="toggle-btn">
  Content
</div>

Toggle button (like/subscribe)

<button aria-pressed="false">
  Like
</button>

Tabs

<div role="tablist">
  <button 
    role="tab" 
    aria-selected="true"
    aria-controls="panel-1"
    tabindex="0"
  >
    Tab 1
  </button>
  <button 
    role="tab" 
    aria-selected="false"
    aria-controls="panel-2"
    tabindex="-1"
  >
    Tab 2
  </button>
</div>
<div role="tabpanel" id="panel-1" aria-labelledby="tab-1">
  Content 1
</div>
<div role="tabpanel" id="panel-2" aria-labelledby="tab-2">
  Content 2
</div>

(ko'pincha) tabindex="0|-1" bilan roving tabindex pattern ishlatiladi.

Listbox / Combobox (custom select)

<div role="combobox" aria-expanded="false" aria-controls="listbox">
  <input aria-autocomplete="list" aria-controls="listbox">
  <ul role="listbox" id="listbox">
    <li role="option" aria-selected="false">Option 1</li>
    <li role="option" aria-selected="true">Option 2</li>
  </ul>
</div>

Modal/dialog (custom bo'lsa)

<div role="dialog" aria-modal="true" aria-labelledby="dialog-title" aria-describedby="dialog-desc">
  <h2 id="dialog-title">Tasdiqlash</h2>
  <p id="dialog-desc">Ishonchingiz komilmi?</p>
  <button>OK</button>
</div>

Live feedback (toast, "Saved!")

<!-- Polite: qulay bo'lganda o'qiydi -->
<div role="status" aria-live="polite">
  Saqlandi!
</div>

<!-- Assertive: darhol o'qiydi -->
<div role="alert" aria-live="assertive">
  Xato: Noto'g'ri kirish
</div>

Navigation current

<nav>
  <a href="/home" aria-current="page">Home</a>
  <a href="/about">About</a>
</nav>

5️⃣ Live Regions — dynamic kontentni "gapirtirish"

Agar UI'da matn o'zi o'zgarib qolsa (AJAX, toast, validation), screen reader buni ko'rmay qolishi mumkin.

  • aria-live="polite" → tinch, keyinroq o'qiydi (status, "Saved")
  • aria-live="assertive" → darhol (critical error)

Qoida: keragidan ortiq assertive ishlatma — foydalanuvchini "bosib ketadi".

<!-- ✅ To'g'ri: Non-critical yangilanishlar uchun polite -->
<div role="status" aria-live="polite" id="status">
  <!-- JS orqali yangilanadi -->
</div>

<!-- ✅ To'g'ri: Critical xatolar uchun assertive -->
<div role="alert" aria-live="assertive" id="error">
  <!-- Critical xato -->
</div>

6️⃣ aria-hidden va "yashirish" (katta xatolar shu yerda)

  • aria-hidden="true" → faqat screen reader'dan yashiriladi
  • hidden / display:none → ham ko'rinmaydi, ham SR ko'rmaydi

Xato pattern: Modal ochilganda orqa fonni faqat vizual yashirib qo'yib, SR uchun ochiq qoldirish.

<!-- ❌ Noto'g'ri: Background hali ham SR uchun accessible -->
<div class="modal-backdrop" style="opacity: 0;">
  <!-- Screen reader hali ham bu yerga navigatsiya qila oladi -->
</div>

<!-- ✅ To'g'ri: Modal ochilganda SR'dan yashirish -->
<div class="modal-backdrop" aria-hidden="true">
  <!-- Screen reader'dan yashirilgan -->
</div>

7️⃣ Eng xavfli 10 ta xato (checklist)

  1. ❌ Native element bor joyda role ishlatish
  2. aria-expanded bor, lekin JS update qilmaydi
  3. aria-controls id noto'g'ri (mavjud emas)
  4. ❌ Icon button'da label yo'q (aria-label/aria-labelledby yo'q)
  5. aria-hidden="true" bosiladigan narsaga qo'yilgan
  6. role="button" qo'yib, keyboard behavior yozilmagan
  7. aria-disabled="true" qo'yib, real disabled emas (action baribir ishlaydi)
  8. aria-describedby bilan error text ulanganmadi
  9. aria-live hamma joyga qo'yilgan (shovqin)
  10. ❌ ARIA bilan "semanticsni" tuzataman deb, asl HTML'ni buzish

8️⃣ Minimal "qachon ARIA kerak?" qaror daraxti

Native HTML bormi?
├─ Ha → ARIA yo'q
└─ Yo'q → Davom et

Icon-only buttonmi?
├─ Ha → aria-label yoki aria-labelledby
└─ Yo'q → Davom et

Biror narsa ochilib-yopiladimi?
├─ Ha → aria-expanded + aria-controls (JS sync)
└─ Yo'q → Davom et

Custom widgetmi (tabs/combobox)?
├─ Ha → role + state + keyboard spec
└─ Yo'q → Ehtimol ARIA kerak emas

Umumiy xulosa

ARIA — bu accessibility uchun "plastir" emas, bu screen reader'lar uchun muloqot vositasi. 3 ta oltin qoida: avval HTML, ARIA interaktivlik bermaydi, va ARIA state'lar JS bilan sync bo'lishi kerak.