Keyboard navigatsiya — tabindex, focus boshqarish

~15 daq · HTML · Accessibility

Muammodan boshlaylik

20-darsdagi tajribani eslang: sichqonchasiz saytda harakat. Odatda uchraydigan muammolar:

  • Tab bosasiz — fokus qayerda ekanini ko'rmaysiz
  • Asosiy kontentga yetish uchun menyudagi 30 ta havoladan har safar o'tasiz
  • Modal oyna ochildi — Tab bosilsa fokus oyna orqasidagi sahifaga ketib qoladi
  • Modal yopildi — fokus sahifaning eng boshiga "uchib" ketdi
  • Ba'zi "tugmalar" ga umuman yetib bo'lmaydi

Klaviatura bilan ishlaydigan foydalanuvchilar: ekran o'quvchi foydalanuvchilari, harakat cheklovlari bor odamlar, va ko'plab dasturchilar — tezlik uchun. Bu darsda — ularning hammasi uchun saytni qulay qilish.


Asosiy klaviatura tugmalari

Tugma Amal
Tab Keyingi interaktiv elementga
Shift + Tab Oldingisiga
Enter Havolani ochish, tugmani bosish, formani yuborish
Space Tugmani bosish, checkbox ni belgilash, sahifani pastga
↑ ↓ ← → Radio guruh, select, tablar, menyu ichida harakat
Esc Modal, menyu, ochilgan ro'yxatni yopish
Home / End Ro'yxat yoki sahifa boshi / oxiri

Tabiiy fokus tartibi

Tab bilan avtomatik ravishda tanlanadigan elementlar:

  • <a href> (faqat href bilan!)
  • <button>
  • <input>, <select>, <textarea>
  • <summary> (<details> ichida)
  • contenteditable elementlar

Tartib — HTML dagi tartib (DOM tartibi), ekranda qanday ko'rinishidan qat'i nazar.

[!WARNING] CSS bilan vizual tartibni o'zgartirsangiz (flex-direction: row-reverse, order, Grid joylashuvi, position: absolute), Tab tartibi o'zgarmaydi — fokus ekranda u yoqdan bu yoqqa sakraydi. Mantiqiy tartibni HTML da to'g'ri yozing, CSS faqat ko'rinish uchun (CSS kursi, 15 va 19-darslar).


Fokus ko'rinsin

/* ❌ eng ko'p uchraydigan accessibility xatosi */
*:focus {
  outline: none;
}

Bu bilan klaviatura foydalanuvchisi qayerda ekanini ko'rmaydi — xuddi sichqoncha kursorini yashirgandek.

/* ✅ faqat klaviatura bilan ishlaganda */
:focus-visible {
  outline: 2px solid #2563eb;
  outline-offset: 2px;
}

/* sichqoncha bilan bosilganda — chiziqsiz */
:focus:not(:focus-visible) {
  outline: none;
}

:focus-visible — brauzer o'zi hal qiladi: klaviatura bilan kelinganda fokus ko'rsatiladi, sichqoncha bosilganda — yo'q. Dizaynerning "bosilganda ko'k ramka xunuk" degan e'tiroziga ham yechim.

Fokus belgisi yaxshi ko'rinsin: kontrast kamida 3 : 1, qalinligi kamida 2px, fon bilan qo'shilib ketmasin.


tabindex

<div tabindex="0">...</div>     <!-- tabiiy tartibga qo'shiladi -->
<div tabindex="-1">...</div>    <!-- Tab bilan emas, faqat JS bilan fokuslanadi -->
<div tabindex="3">...</div>     <!-- ❌ hech qachon -->
Qiymat Ma'nosi Qachon
0 Tab tartibiga HTML joylashuvi bo'yicha qo'shish Fokuslanadigan maxsus vidjet (ARIA bilan)
-1 Tab bilan yo'q, lekin element.focus() ishlaydi Modal sarlavhasi, xato xabari, "skip link" maqsadi
1+ Hammadan oldin, raqam tartibida Hech qachon — butun sahifa tartibini buzadi

[!WARNING] tabindex="0" ni <div> ga qo'shish uni tugmaga aylantirmaydi — faqat fokuslanadigan qiladi. Enter va Space ishlamaydi, ekran o'quvchi "tugma" demaydi. Agar element bosiladigan bo'lsa — <button> ishlating (21-dars, ARIA ning birinchi qoidasi).

Fokusdan chiqarish — inert

<main inert>...</main>
<dialog open>...</dialog>

inert atributi — element va uning barcha ichidagilarini fokusdan, bosishdan va ekran o'quvchidan chiqaradi. Modal ochilganda orqadagi sahifa uchun, yopiq yon panel uchun ideal.


Skip link — "asosiy kontentga o'tish"

Sahifaning eng birinchi havolasi:

<body>
  <a href="#asosiy" class="skip-link">Asosiy kontentga o'tish</a>

  <header>
    <nav>...30 ta havola...</nav>
  </header>

  <main id="asosiy" tabindex="-1">
    ...
  </main>
</body>
.skip-link {
  position: absolute;
  left: 1rem;
  top: -100px;
}

.skip-link:focus {
  top: 1rem;          /* Tab bosilganda ko'rinadi */
}

Birinchi Tab — "Asosiy kontentga o'tish" paydo bo'ladi, Enter — menyuni chetlab o'tadi. Darsning boshidagi 2-muammo hal. Ko'plab yirik saytlarda (GitHub, GOV.UK) bor — ularda Tab bosib ko'ring.


Fokusni boshqarish — JavaScript

Sahifa dinamik o'zgarganda fokusni o'zingiz boshqarishingiz kerak.

Modal oyna — dialog

<button id="ochish">Kirish</button>

<dialog id="modal" aria-labelledby="modal-sarlavha">
  <h2 id="modal-sarlavha">Tizimga kirish</h2>
  <form method="dialog">
    <label for="m-email">Email</label>
    <input id="m-email" type="email">
    <button>Yopish</button>
  </form>
</dialog>
ochish.addEventListener('click', () => modal.showModal());

showModal() bilan ochilgan <dialog> hammasini o'zi qiladi:

  • Fokus ichkaridagi birinchi elementga o'tadi
  • Orqadagi sahifa inert — Tab oynadan chiqmaydi (3-muammo)
  • Esc bilan yopiladi
  • Yopilganda fokus uni ochgan tugmaga qaytadi (4-muammo)

Ilgari bularning hammasi uchun o'nlab qator JavaScript kerak edi — bugun bitta teg.

SPA da sahifa almashganda

Sahifa yangilanmasdan kontent o'zgarsa (React, Vue, DevDocs kabi SPA), ekran o'quvchi buni sezmaydi va fokus eski joyda qoladi:

function sahifaAlmashdi() {
  const sarlavha = document.querySelector('main h1');
  sarlavha.setAttribute('tabindex', '-1');
  sarlavha.focus();                     // ekran o'quvchi yangi sarlavhani o'qiydi
}

Element o'chirilganda

Ro'yxatdan element o'chirilsa, fokus u bilan birga yo'qoladi va sahifaning boshiga ketadi. Fokusni keyingi elementga yoki ro'yxat sarlavhasiga o'tkazing:

function ochir(item) {
  const keyingi = item.nextElementSibling ?? item.previousElementSibling;
  item.remove();
  keyingi?.querySelector('button')?.focus();
}

Maxsus vidjetlar — roving tabindex

Tablar, menyular, asboblar paneli kabi guruhlar ichida strelkalar bilan harakatlanish kutiladi, Tab esa guruhdan chiqishi kerak:

<div role="tablist" aria-label="Kurslar">
  <button role="tab" aria-selected="true"  tabindex="0">HTML</button>
  <button role="tab" aria-selected="false" tabindex="-1">CSS</button>
  <button role="tab" aria-selected="false" tabindex="-1">JavaScript</button>
</div>
tablist.addEventListener('keydown', (e) => {
  const tabs = [...tablist.querySelectorAll('[role="tab"]')];
  const i = tabs.indexOf(document.activeElement);
  let keyingi;
  if (e.key === 'ArrowRight') keyingi = tabs[(i + 1) % tabs.length];
  if (e.key === 'ArrowLeft')  keyingi = tabs[(i - 1 + tabs.length) % tabs.length];
  if (!keyingi) return;

  tabs[i].tabIndex = -1;
  keyingi.tabIndex = 0;
  keyingi.focus();
});

Faqat bitta element tabindex="0" — guruhga Tab bilan bir marta kiriladi, ichida — strelkalar. To'liq namunalar — ARIA Authoring Practices Guide da (21-dars).


Tekshiruv ro'yxati

Har bir sahifada sichqonchasiz:

  • Barcha havolalar, tugmalar va maydonlarga Tab bilan yetib boriladi
  • Fokus har doim aniq ko'rinadi
  • Tab tartibi mantiqiy — ekrandagi tartibga mos
  • Hamma narsa Enter/Space bilan ishlaydi
  • Skip link bor va ishlaydi
  • Modal: fokus ichida qoladi, Esc yopadi, fokus qaytadi
  • Hech qayerda "tuzoq" yo'q — Tab bilan kirib, chiqib bo'lmaydigan joy
  • Yashirin elementlar (yopiq menyu) Tab bilan tanlanmaydi

Nima uchun shunday?

Nima uchun klaviatura navigatsiyasi accessibility ning eng muhim qismlaridan biri hisoblanadi?

Chunki deyarli barcha yordamchi texnologiyalar klaviatura orqali ishlaydi. Ekran o'quvchilar klaviatura buyruqlari bilan boshqariladi. Bitta tugmali qurilmalar (switch), og'iz bilan boshqariladigan tayoqchalar, ko'z harakatini kuzatuvchi tizimlar, ovozli boshqaruv — ularning hammasi brauzerga klaviatura hodisalari sifatida yetib keladi. Ya'ni sayt klaviatura bilan ishlasa, u o'nlab turli vositalar bilan ishlaydi. Klaviatura bilan ishlamasa — ularning hech biri bilan. Va eng yaxshi xabar: tabiiy HTML elementlari (<button>, <a href>, <input>, <dialog>) buni allaqachon bepul beradi — muammolar faqat biz ularni div lar bilan almashtirganda boshlanadi.


Xulosa

Eslab qoling:

  • Tab / Shift+Tab — harakat; Enter / Space — amal; strelkalar — guruh ichida; Esc — yopish
  • Fokus tartibi — HTML tartibi; CSS bilan vizual tartibni buzmang
  • outline: none — hech qachon; :focus-visible bilan chiroyli fokus
  • tabindex="0" — tartibga qo'shish; -1 — faqat JS; musbat — hech qachon
  • inert — butun blokni fokusdan chiqarish
  • Skip link — sahifaning birinchi havolasi
  • <dialog> + showModal() — fokus, Esc, inert va qaytarish bepul
  • SPA da sahifa almashganda va element o'chirilganda — fokusni o'zingiz boshqaring

Kurs yakunlandi

Tabriklaymiz — HTML kursini tugatdingiz! Endi siz sahifa tuzilishini, semantik teglarni, meta ma'lumotlarni, formalarni va accessibility asoslarini bilasiz.

Keyingi qadam — CSS kursi: sahifangizni chiroyli, moslashuvchan va jonli qilish.