Erişilebilir Menü Sistemleri Oluşturma

Yayınlanan: 2022-03-10
Hızlı özet ↬ Web'de birçok farklı menü türü vardır. Kapsayıcı deneyimler yaratmak, doğru işaretleme ve davranışla doğru yerlerde doğru menü kalıplarını kullanma meselesidir.

Editörün Notu : Bu makale orijinal olarak Inclusive Components'ta yayınlanmıştır. Benzer kapsayıcı bileşen makaleleri hakkında daha fazla bilgi edinmek isterseniz, Twitter'da @inclusicomps'u takip edin veya RSS beslemesine abone olun. Patreon'da kapsayıcı-components.design'ı destekleyerek, onu mevcut sağlam arayüz bileşenlerinin en kapsamlı veritabanı haline getirmeye yardımcı olabilirsiniz.

Sınıflandırma zordur. Örneğin yengeçleri alın. Münzevi yengeçler, porselen yengeçler ve at nalı yengeçleri - taksonomik olarak konuşursak - gerçek yengeçler değildir. Ancak bu, "yengeç" son ekini kullanmamıza engel değil. Gerçek olmayan yengeçler, zamanla ve karsinizasyon adı verilen bir süreç sayesinde gerçek yengeçlere daha yakından benzeyecek şekilde geliştiğinde daha da kafa karıştırıcı hale gelir. Geçmişte münzevi yengeç olduğuna inanılan kral yengeçler için durum böyledir. Kabuklarının boyutunu hayal edin!

Tasarımda, genellikle farklı şeylere aynı adı vererek aynı hatayı yaparız. Benzer görünüyorlar , ancak görünüşler aldatıcı olabilir. Bunun bileşen kitaplığınızın netliği üzerinde talihsiz bir etkisi olabilir. Dahil etme açısından, aynı zamanda anlamsal ve davranışsal olarak uygun olmayan bir bileşeni yeniden tasarlamanıza da yol açabilir. Kullanıcılar bir şey bekleyecek ve başka bir şey alacak.

"Açılır menü" terimi klasik bir örnektir. Bir <select> öğesindeki <option> s kümesi ve bir gezinme alt menüsünü oluşturan JavaScript tarafından açıklanan bağlantılar listesi dahil olmak üzere arabirimlerde "açılır" birçok şey vardır. Aynı isim; oldukça farklı şeyler. (Bazıları bunlara "açılanlar" derler elbette ama buna girmeyelim.)

Bir dizi seçenek oluşturan açılır menülere genellikle "menüler" denir ve ben burada bunlardan bahsetmek istiyorum. Gerçek bir menü tasarlayacağız, ancak yol boyunca gerçekten doğru olmayan menüler hakkında söylenecek çok şey var.

Atlamadan sonra daha fazlası! Aşağıdan okumaya devam edin ↓

Bir sınavla başlayalım. Resimdeki gezinti çubuğundan aşağı sarkan bağlantı kutusu bir menü mü?

Bir gezinme çubuğu, altında sırasıyla köpek kostümleri, waffle ütüleri ve büyülü küreler için üç bağlantıdan oluşan bir dizi asılı olan bir mağaza bağlantısı içerir.
Bir gezinme çubuğu, altında sırasıyla köpek kostümleri, waffle ütüleri ve büyülü küreler için üç bağlantıdan oluşan bir dizi asılı olan bir mağaza bağlantısı içerir. (Büyük önizleme)

Cevap hayır, gerçek bir menü değil.

Gezinme şemalarının bağlantı listelerinden oluşması uzun süredir devam eden bir gelenektir. Neredeyse uzun süredir devam eden bir kural, alt navigasyonun iç içe bağlantı listeleri olarak sağlanması gerektiğini belirtir. Yukarıda gösterilen bileşen için CSS'yi kaldıracak olsaydım, mavi renkli ve Times New Roman dışında aşağıdakine benzer bir şey görmem gerekirdi.

Anlamsal olarak konuşursak, iç içe bağlantı listeleri bu bağlamda doğrudur. Navigasyon sistemleri aslında içerik tablolarıdır ve içerik tabloları bu şekilde yapılandırılır. Bizi gerçekten "menü" olarak düşündüren tek şey, iç içe geçmiş listelerin stili ve üzerine gelindiğinde veya odaklanıldığında ortaya çıkma biçimleridir.

İşte bazılarının yanlış gittiği ve WAI-ARIA semantiğini eklemeye başladığı nokta: aria-haspopup="true" , role="menu" , role="menuitem" vb. Bunlar için bir yer var, üzerinde duracağımız gibi, ama burada değil . İşte bunun iki nedeni:

  1. ARIA menüleri gezinme için değil, uygulama davranışı için tasarlanmıştır. Bir masaüstü uygulaması için menü sistemini hayal edin.
  2. Üst düzey bağlantı, bağlantı olarak kullanılabilir olmalıdır, yani bir menü düğmesi gibi davranmaz.

(2) ile ilgili olarak: Alt menüleri olan bir navigasyon bölgesinden geçerken, "üst seviye" bağlantısının üzerine gelindiğinde veya odaklanıldığında her bir alt menünün görünmesi beklenir (resimde "Mağaza"). Bu hem alt menüyü ortaya çıkarır hem de kendi bağlantılarını odak sırasına yerleştirir. Gerektiğinde alt menülerin görünümünü sürdürmek için odak ve bulanıklık olaylarını yakalayan JavaScript'ten biraz yardım alarak, klavyeyi kullanan biri sırayla her katmanın her bir bağlantısında sekme yapabilmelidir.

aria-haspopup="true" özelliğini alan menü düğmeleri bu şekilde davranmaz. Tıklandığında etkinleştirilirler ve gizli bir menüyü ortaya çıkarmaktan başka bir amaçları yoktur.

e-kitap indirimleri bieten wir
Solda: aşağıyı gösteren bir ok simgesi ve aria-genişletilmiş = yanlış durumu ile 'menü' etiketli bir menü düğmesi. Sağ: Aynı menü düğmesi, ancak menü açık. Bu düğme aria-genişletilmiş = gerçek durumundadır. (Büyük önizleme)

Resimdeki gibi o menünün açık mı kapalı mı olduğu aria-expanded ile bildirilmelidir. Bu durumu odakta değil, yalnızca tıklamada değiştirmelisiniz. Kullanıcılar genellikle sadece bir odak olayında açık bir durum değişikliği beklemezler. Navigasyon sistemimizde durum gerçekten değişmez; bu sadece bir stil hilesi. Davranışsal olarak, bu tür bir göster/gizle hilesi yokmuş gibi gezinmede Sekme yapabiliriz.

Gezinme Alt Menüleriyle İlgili Sorun

Gezinme alt menüleri (veya bazılarına "açılır menüler") bir fare veya klavye ile iyi çalışır, ancak dokunma söz konusu olduğunda o kadar sıcak değildirler. Örneğimizde ilk kez üst düzey "Dükkan" bağlantısına bastığınızda hem alt menüyü açmasını hem de bağlantıyı takip etmesini söylüyorsunuz.

Burada iki olası çözüm vardır:

  1. Tam WAI-ARIA menü semantiği ve davranışında üst düzey bağlantıların ( e.preventDefault() ) ve komut dosyasının varsayılan davranışını önleyin.
  2. Her üst düzey hedef sayfada, alt menüye alternatif olarak bir içindekiler tablosu olduğundan emin olun.

(1) yetersiz çünkü daha önce de belirttiğim gibi, bu tür anlambilim ve davranışlar, bağlantıların konu kontrolleri olduğu bu bağlamda beklenmiyor. Artı, kullanıcılar, eğer varsa, artık üst düzey bir sayfaya gidemezler.

Sidenote: Hangi cihazlar dokunmatik cihazlardır?

“Bu harika bir çözüm değil, ancak sadece dokunmatik arayüzler için ekleyeceğim” diye düşünmek cazip geliyor. Sorun şudur: Bir cihazda dokunmatik ekran olup olmadığı nasıl anlaşılır?

"Küçük ekranı" kesinlikle "dokunma etkin" ile eşitlememelisiniz. Müzeler için dokunmatik ekran yapan insanlarla aynı ofiste çalışmış biri olarak, sizi temin ederim ki etraftaki en büyük ekranlardan bazıları dokunmatik ekranlardır. Çift klavye ve dokunmatik girişli dizüstü bilgisayarlar da giderek daha üretken hale geliyor.

Aynı şekilde, küçük cihazların tamamı olmasa da çoğu dokunmatik cihazlardır. Kapsayıcı tasarımda varsayımlarda bulunmayı göze alamazsınız.

Çözünürlük (2), tüm girdilerin kullanıcıları için bir "yedek" sağladığı için daha kapsayıcı ve sağlamdır. Ancak buradaki geri dönüş terimi etrafındaki korkutucu alıntılar oldukça kasıtlı çünkü aslında sayfa içi içerik tablolarının gezinme sağlamanın üstün bir yolu olduğunu düşünüyorum.

Ödüllü Devlet Dijital Hizmetleri ekibi aynı fikirde görünüyor. Bunları Wikipedia'da da görmüş olabilirsiniz.

Gov.uk içerik tabloları, liste stilleri olarak kısa çizgilerle minimaldir. Wikipedia, numaralandırılmış öğeler içeren kenarlıklı gri bir kutu sağlar. Her ikisi de etiketli içeriklerdir.
Gov.uk içerik tabloları, liste stilleri olarak kısa çizgilerle minimaldir. Wikipedia, numaralandırılmış öğeler içeren kenarlıklı gri bir kutu sağlar. Her ikisi de etiketli içeriklerdir.

İçindekiler

İçerik tabloları, ilgili sayfalar veya sayfa bölümleri için gezinmedir ve bir <nav> öğesi, bir liste ve bir grup etiketleme mekanizması kullanarak ana site gezinme bölgelerine anlamsal olarak benzer olmalıdır.

 <nav aria-labelledby="sections-heading"> <h2>Products</h2> <ul> <li><a href="/products/dog-costumes">Dog costumes</a></li> <li><a href="/products/waffle-irons">Waffle irons</a></li> <li><a href="/products/magical-orbs">Magical orbs</a></li> </ul> </nav> <!-- each section, in order, here -->

notlar

  • Bu örnekte, açılır alt menüde olduğu gibi her bölümün kendi sayfası olduğunu hayal ediyoruz.
  • Bu "Mağaza" sayfalarının her birinin aynı yapıya sahip olması ve bu "Ürünler" içindekiler tablosunun aynı yerde bulunması önemlidir. Tutarlılık anlayışı destekler.
  • Liste, öğeleri gruplandırır ve ekran okuyucunun sentetik sesi gibi yardımcı teknoloji çıktılarında numaralandırır.
  • <nav> , aria-labelledby kullanılarak başlık tarafından özyinelemeli olarak etiketlenir. Bu, "ürün navigasyonunun", bölgeye Tab ile girildiğinde çoğu ekran okuyucuda duyurulacağı anlamına gelir. Bu aynı zamanda, "ürünlerde gezinme"nin, kullanıcıların doğrudan bölgelere gidebileceği ekran okuyucu eleman arayüzlerinde maddeleştirileceği anlamına gelir.

Hepsi bir sayfada

Tüm bölümleri kaydırmak için çok uzun ve zahmetli hale gelmeden tek bir sayfaya sığdırabilirseniz, daha da iyisi. Sadece her bölümün karma tanımlayıcısına bağlantı verin. Örneğin, href="#waffle-irons" şunu işaret etmelidir: .

 <nav aria-labelledby="sections-heading"> <h2>Products</h2> <ul> <li><a href="#dog-costumes">Dog costumes</a></li> <li><a href="#waffle-irons">Waffle irons</a></li> <li><a href="#magical-orbs">Magical orbs</a></li> </ul> </nav> <!-- dog costumes section here --> <section tabindex="-1"> <h2>Waffle Irons</h2> </section> <!-- magical orbs section here -->

( Not: Bazı tarayıcılar, odağı bağlantılı sayfa parçalarına göndermede yetersizdir. Hedef parçaya tabindex="-1" yerleştirmek bunu düzeltir.)

Bir sitenin çok fazla içeriğe sahip olduğu durumlarda, içerik tablolarının “menüler”in liberal kullanımıyla ifade edilen dikkatli bir şekilde oluşturulmuş bir bilgi mimarisi, güvencesiz ve hantal bir açılır sisteme sonsuz derecede tercih edilir. Duyarlı hale getirmek daha kolay ve bunu yapmak için daha az kod gerektirir, aynı zamanda işleri daha net hale getirir: açılır sistemlerin yapıyı gizlediği yerde, içerik tabloları onu çıplak bırakır.

Devlet Dijital Servisi'nin gov.uk sitesi de dahil olmak üzere bazı siteler, yalnızca içerik tabloları olan dizin (veya “konu”) sayfaları içerir. Popüler statik site oluşturucu Hugo'nun varsayılan olarak bu tür sayfaları oluşturması çok güçlü bir kavramdır.

İki ayrı sayfa dalı ile en üstte konu açılış sayfası bulunan aile ağacı stili diyagramı. Tek tek sayfa dallarının her biri, birden çok sayfa bölümü dallarına sahiptir
İki ayrı sayfa dalı ile en üstte konu açılış sayfası bulunan aile ağacı stili diyagramı. Bireysel sayfa dallarının her biri, birden çok sayfa bölümü dalına sahiptir (Büyük önizleme)

Bilgi mimarisi, içermenin büyük bir parçasıdır. Kötü organize edilmiş bir site teknik olarak istediğiniz kadar uyumlu olabilir, ancak yine de birçok kullanıcıyı, özellikle de bilişsel bozuklukları olan veya zaman sıkıntısı çekenleri yabancılaştıracaktır.

Gezinme Menüsü Düğmeleri

Sahte navigasyonla ilgili menüler konusuna girmişken, navigasyon menü butonlarından bahsetmemek yanlış olur. Bunların üç satırlı "hamburger" veya "navicon" simgesiyle gösterildiğini neredeyse kesin olarak görmüşsünüzdür.

Kısıtlanmış bir bilgi mimarisi ve yalnızca bir gezinme bağlantısı katmanıyla bile, küçük ekranlardaki alan birinci sınıftır. Gezinmeyi bir düğmenin arkasına gizlemek, görünüm alanında ana içerik için daha fazla yer olduğu anlamına gelir.

Gezinme düğmesi, şimdiye kadar incelediğimiz gerçek bir menü düğmesine en yakın şeydir. Tıklamada bir menünün kullanılabilirliğini değiştirme amacına sahip olduğundan, şunları yapmalıdır:

  1. Kendini bir bağlantı değil, bir düğme olarak tanımlayın;
  2. İlgili menünün genişletilmiş veya daraltılmış durumunu tanımlayın (ki bu, katı terimlerle yalnızca bir bağlantı listesidir).

Aşamalı geliştirme

Ama kendimizin önüne geçmeyelim. Aşamalı geliştirme konusunda dikkatli olmalıyız ve bunun JavaScript olmadan nasıl çalışacağını düşünmeliyiz.

Geliştirilmemiş bir HTML belgesinde butonlarla yapabileceğiniz pek bir şey yoktur (gönder butonları dışında ama bu bizim burada elde etmek istediğimiz şeyle yakından alakalı bile değil). Bunun yerine, belki de bizi navigasyona götüren bir bağlantıyla başlamalıyız?

 <a href="#navigation">navigation</a> <!-- some content here perhaps --> <nav> <ul> <li><a href="/">Home</a></li> <li><a href="/about">About</a></li> <li><a href="/shop">Shop</a></li> <li><a href="/content">Content</a></li> </ul> </nav>

Bağlantı ve gezinme arasında çok fazla içerik olmadıkça bağlantıya sahip olmanın pek bir anlamı yoktur. Sitede gezinme hemen hemen her zaman kaynak sıranın üst kısmında görünmesi gerektiğinden, buna gerek yoktur. Yani, gerçekten, JavaScript'in olmadığı bir navigasyon menüsü sadece biraz navigasyon olmalı.

 <nav> <ul> <li><a href="/">Home</a></li> <li><a href="/about">About</a></li> <li><a href="/shop">Shop</a></li> <li><a href="/content">Content</a></li> </ul> </nav>

Bunu, başlangıç ​​durumunda düğmeyi ekleyerek ve gezinmeyi gizleyerek ( hidden özniteliği kullanarak) geliştirebilirsiniz:

 <nav> <button aria-expanded="false">Menu</button> <ul hidden> <li><a href="/">Home</a></li> <li><a href="/about">About</a></li> <li><a href="/shop">Shop</a></li> <li><a href="/contact">Contact</a></li> </ul> </nav>

Bazı eski tarayıcılar - hangilerini biliyorsunuz - hidden özelliğini desteklemez, bu nedenle aşağıdakileri CSS'nize koymayı unutmayın. Bu sorunu çözer çünkü display: none , menüyü yardımcı teknolojilerden gizleme ve odak sırasındaki bağlantıları kaldırma konusunda aynı etkiye sahip değildir.

 [hidden] { display: none; }

Eski yazılımı desteklemek için elinden gelenin en iyisini yapmak, elbette, kapsayıcı bir tasarım eylemidir. Bazıları yükseltme yapamıyor veya istemiyor.

Yerleştirme

Birçok insanın yanlış yaptığı yer, düğmeyi bölgenin dışına yerleştirmek. Bu, kısayol kullanarak <nav> 'a geçen ekran okuyucu kullanıcılarının onu boş bulacağı anlamına gelir, bu da pek yardımcı olmaz. Liste ekran okuyuculardan gizlendiğinde, sadece şununla karşılaşırlar:

 <nav> </nav>

Durumu şu şekilde değiştirebiliriz:

 var navButton = document.querySelector('nav button'); navButton.addEventListener('click', function() { let expanded = this.getAttribute('aria-expanded') === 'true' || false; this.setAttribute('aria-expanded', !expanded); let menu = this.nextElementSibling; menu.hidden = !menu.hidden; });

arya kontrolleri

Aria-controls Is Poop'ta yazdığım gibi, ekran okuyucu kullanıcılarının bir kontrol öğesinden kontrol edilen bir öğeye gitmesine yardımcı olmayı amaçlayan aria-controls özniteliği yalnızca JAWS ekran okuyucusunda desteklenir. Yani basitçe ona güvenemezsiniz.

Kullanıcıları öğeler arasında yönlendirmek için iyi bir yöntem olmadan, bunun yerine aşağıdakilerden birinin doğru olduğundan emin olmalısınız:

  1. Genişletilmiş listenin ilk bağlantısı, düğmeden sonra odak sırasında yer alır (önceki kod örneğinde olduğu gibi).
  2. İlk bağlantı, listeyi ortaya çıkarmaya programlı olarak odaklanmıştır.

Bu durumda, tavsiye ederim (1). Odağı düğmeye geri taşıma ve bunu hangi olay(lar)a yapma konusunda endişelenmenize gerek olmadığı için bu çok daha kolaydır. Ayrıca, şu anda kullanıcıları odaklarının farklı bir yere taşınacağı konusunda uyaracak hiçbir şey yok. Birazdan tartışacağımız gerçek menülerde, bu aria-haspopup="true" .

aria-controls kullanmak, ekran okuyuculardaki okumayı daha ayrıntılı hale getirmesi dışında pek zarar vermez. Ancak, bazı JAWS kullanıcıları bunu bekleyebilir. Şifre olarak listenin id kullanarak nasıl uygulanacağı aşağıda açıklanmıştır:

 <nav> <button aria-expanded="false" aria-controls="menu-list">Menu</button> <ul hidden> <li><a href="/">Home</a></li> <li><a href="/about">About</a></li> <li><a href="/shop">Shop</a></li> <li><a href="/contact">Contact</a></li> </ul> </nav>

Menü ve menü öğesi rolleri

Gerçek bir menü (WAI-ARIA anlamında), menu rolünü (kap için) ve tipik olarak menuitem alt öğelerini (diğer alt roller geçerli olabilir) kullanarak kendisini bu şekilde tanımlamalıdır. Bu ebeveyn ve çocuk rolleri, yardımcı teknolojilere bilgi sağlamak için birlikte çalışır. Menü semantiğine sahip olmak için bir listenin nasıl genişletilebileceği aşağıda açıklanmıştır:

 <ul role="menu"> <li role="menuitem">Item 1</li> <li role="menuitem">Item 2</li> <li role="menuitem">Item 3</li> </ul>

Navigasyon menümüz bir şekilde “gerçek” bir menü gibi davranmaya başladığına göre, bunların olmaması gerekir mi?

Kısa cevap: hayır. Uzun cevap şudur: hayır, çünkü liste menuitem bağlantılar içerir ve menü öğesi öğelerinin etkileşimli torunları olması amaçlanmamıştır. Yani bir menüdeki kontrollerdir .

Elbette, role="presentation" veya role="none" (bunlar eşdeğerdir) kullanarak <li> lerin liste semantiğini bastırabilir ve menuitem rolünü her bağlantıya yerleştirebiliriz. Ancak bu, örtük bağlantı rolünü bastırır. Başka bir deyişle, izlenecek örnek "Ana sayfa, bağlantı" veya "Ana sayfa, menü öğesi, bağlantı" değil , "Ana sayfa, menü öğesi" olarak duyurulacaktır. ARIA rolleri, HTML rollerini geçersiz kılar.

 <!-- will be read as "Home, menu item" --> <li role="presentation"> <a href="/" role="menuitem">Home</a> </li>

Kullanıcının bir bağlantı kullandığını ve bağlantı davranışı bekleyebileceğini bilmesini istiyoruz, bu yüzden bu iyi değil. Dediğim gibi, gerçek menüler (JavaScript odaklı) uygulama davranışı içindir.

Geriye, tam olarak gerçek bir menü olmayan ancak en azından kullanıcılara aria-expanded durum sayesinde bağlantı listesinin açık olup olmadığını söyleyen bir tür karma bileşen kaldı. Bu, navigasyon menüleri için tamamen tatmin edici bir modeldir.

Sidenote: <select> öğesi

En başından beri duyarlı tasarımla ilgilendiyseniz, gezinmenin dar görünümler için bir <select> öğesinde toplandığı bir kalıbı hatırlayabilirsiniz.

Görünüm penceresinin üst kısmında seçili "ev" öğesini gösteren seçkin öğeye sahip ahize
Görünüm penceresinin üst kısmında seçili "ev" öğesini gösteren seçkin öğeye sahip el cihazı.

Tartıştığımız onay kutusu tabanlı geçiş düğmelerinde olduğu gibi, ek komut dosyası oluşturmadan bir şekilde amaçlandığı gibi davranan yerel bir öğe kullanmak, verimlilik ve özellikle mobilde performans için iyi bir seçimdir. Ve <select> öğeleri, yakında oluşturacağımız düğmeyle tetiklenen menüye benzer semantiklere sahip bir tür menülerdir.

Ancak, onay kutusu geçiş düğmesinde olduğu gibi, yalnızca bir seçim yapmakla değil, girdi girmekle ilişkili bir öğe kullanıyoruz. Bu, birçok kullanıcı için kafa karışıklığına neden olabilir - özellikle bu kalıp, seçili <option> öğesinin bir bağlantı gibi davranmasını sağlamak için JavaScript kullandığından. Bunun ortaya çıkardığı beklenmedik bağlam değişikliği, WCAG'ın 3.2.2 Girişte (Düzey A) kriterine göre bir başarısızlık olarak kabul edilir.

Gerçek Menüler

Artık sahte menüler ve yarı menüler hakkında tartıştığımıza göre, gerçek bir menü düğmesiyle açılıp kapatılan gerçek bir menü oluşturma zamanı geldi. Bundan sonra buton ve menüyü birlikte sadece “menü butonu” olarak anacağım.

Fakat menü butonumuz hangi açılardan doğru olacak? Bu, söz konusu uygulamada seçenekleri seçmeye yönelik bir menü bileşeni olacak ve bu tür bir araç için geleneksel olarak kabul edilecek tüm beklenen semantikleri ve karşılık gelen davranışları uygulayacak.

Daha önce de belirtildiği gibi, bu kurallar masaüstü uygulama tasarımından gelir. ARIA özniteliği ve JavaScript tarafından yönetilen odak yönetimi, bunları tam olarak taklit etmek için gereklidir. ARIA'nın amacının bir kısmı, web geliştiricilerinin yerel dünyada oluşturulmuş kullanılabilirlik kurallarını bozmadan zengin web deneyimleri oluşturmalarına yardımcı olmaktır.

Bu örnekte, uygulamamızın bir tür oyun veya bilgi yarışması olduğunu hayal edeceğiz. Menü düğmemiz, kullanıcının bir zorluk seviyesi seçmesine izin verecektir. Tüm semantikler yerindeyken, menü şöyle görünür:

 <button aria-haspopup="true" aria-expanded="false"> Difficulty <span aria-hidden="true">&#x25be;</span> </button> <div role="menu"> <button role="menuitem">Easy</button> <button role="menuitem">Medium</button> <button role="menuitem">Incredibly Hard</button> </div>

notlar

  • aria-haspopup özelliği, düğmenin bir menü oluşturduğunu gösterir. Basıldığında, kullanıcının "açılır" menüye taşınacağı konusunda uyarı görevi görür (odak davranışını birazdan ele alacağız). Değeri değişmez - her zaman true kalır.
  • Düğmenin içindeki <span> , siyah aşağı bakan küçük üçgen için unicode noktasını içerir. Bu kural, aria-haspopup görsel olmayan bir şekilde ne yaptığını görsel olarak gösterir - düğmeye basmak, altındaki bir şeyi ortaya çıkaracaktır. aria-hidden="true" özelliği, ekran okuyucuların "aşağıya bakan üçgen" veya benzerlerini duyurmasını engeller. aria-haspopup sayesinde, görsel olmayan bağlamda buna gerek yoktur.
  • aria-haspopup özelliği, aria-expanded ile tamamlanır. Bu, kullanıcıya true ve false değerler arasında geçiş yaparak menünün açık (genişletilmiş) veya kapalı (daraltılmış) durumda olup olmadığını söyler.
  • Menünün kendisi (uygun şekilde adlandırılmış) menu rolünü üstlenir. menuitem rolü ile torunları alır. menu öğesinin doğrudan çocukları olmaları gerekmez, ancak bu durumda - basitlik için.

Klavye ve Odak Davranışı

Etkileşimli kontroller klavyesini erişilebilir kılmak söz konusu olduğunda, yapabileceğiniz en iyi şey doğru öğeleri kullanmaktır. Burada <button> öğelerini kullandığımız için, HTMLButtonElement arabiriminde belirtildiği gibi, Enter ve Space tuş vuruşlarında tıklama olaylarının tetikleneceğinden emin olabiliriz. Ayrıca butonla ilişkili disabled özelliğini kullanarak menü öğelerini devre dışı bırakabileceğimiz anlamına gelir.

Yine de menü düğmesi klavye etkileşimi için çok daha fazlası var. WAI-ARIA Yazma Uygulamaları 1.1'e dayalı olarak uygulayacağımız tüm odak ve klavye davranışının bir özeti:

Menü düğmesinde Enter , Space veya Menüyü açar
bir menü öğesinde Odağı sonraki menü öğesine veya sonuncusundaysanız ilk menü öğesine taşır
bir menü öğesinde Odağı önceki menü öğesine veya ilk menüdeyseniz son menü öğesine taşır
menü düğmesinde Açıksa menüyü kapatır
Bir menü öğesinde Esc Menüyü kapatır ve menü düğmesine odaklanır

Ok tuşlarını kullanarak menü öğeleri arasında odağı hareket ettirmenin avantajı, sekmenin menüden çıkmak için korunmasıdır. Pratikte bu, kullanıcıların menüden çıkmak için her menü öğesinde gezinmeleri gerekmediği anlamına gelir - özellikle çok sayıda menü öğesinin olduğu yerlerde kullanılabilirlik açısından büyük bir gelişme.

tabindex="-1" uygulaması, menü öğelerini Tab tarafından odaklanamaz hale getirir, ancak ok tuşlarındaki tuş vuruşlarını yakalayarak öğeleri programlı olarak odaklama yeteneğini korur.

 <button aria-haspopup="true" aria-expanded="false"> Difficulty <span aria-hidden="true">&#x25be;</span> </button> <div role="menu"> <button role="menuitem" tabindex="-1">Easy</button> <button role="menuitem" tabindex="-1">Medium</button> <button role="menuitem" tabindex="-1">Incredibly Hard</button> </div>

açık yöntem

Sağlam bir API tasarımının parçası olarak, çeşitli olayları işlemek için yöntemler oluşturabiliriz.

Örneğin, open yönteminin aria-expanded değeri "true" olarak değiştirmesi, menünün gizli özelliğini false olarak değiştirmesi ve menüde devre dışı bırakılmamış ilk menuitem öğesine odaklanması gerekir:

 MenuButton.prototype.open = function () { this.button.setAttribute('aria-expanded', true); this.menu.hidden = false; this.menu.querySelector(':not(\[disabled])').focus(); return this; }

Kullanıcının odaklanmış bir menü düğmesi örneğinde aşağı tuşuna bastığı yerde bu yöntemi uygulayabiliriz:

 this.button.addEventListener('keydown', function (e) { if (e.keyCode === 40) { this.open(); } }.bind(this));

Ek olarak, bu komut dosyasını kullanan bir geliştirici artık menüyü programlı olarak açabilecektir:

 exampleMenuButton = new MenuButton(document.querySelector('\[aria-haspopup]')); exampleMenuButton.open();

Sidenote: Onay kutusu hack'i

Mümkün olduğunca, gerekmedikçe JavaScript kullanmamak daha iyidir. HTML ve CSS'nin üzerine üçüncü bir teknolojiyi dahil etmek, sistemik karmaşıklık ve kırılganlıkta mutlaka bir artıştır. Ancak, tüm bileşenler, karışımda JavaScript olmadan tatmin edici bir şekilde oluşturulamaz.

Menü düğmeleri söz konusu olduğunda, onları "JavaScript olmadan çalıştırma" hevesi, onay kutusu hack denen bir şeye yol açtı. Burası, CSS kullanarak bir menü öğesinin görünürlüğünü değiştirmek için gizli bir onay kutusunun işaretli (veya işaretlenmemiş) durumunun kullanıldığı yerdir.

 /* menu closed */ [type="checkbox"] + [role="menu"] { display: none; } /* menu open */ [type="checkbox"]:checked + [role="menu"] { display: block; }

Ekran okuyucu kullanıcıları için, onay kutusu rolü ve işaretli durum bu bağlamda anlamsızdır. Bu, onay role="button" eklenerek kısmen aşılabilir.

 <input type="checkbox" role="button" aria-haspopup="true">

Ne yazık ki, bu, örtük kontrol edilen durum iletişimini bastırır ve bizi JavaScript içermeyen durum geri bildiriminden mahrum bırakır (bu bağlamda "kontrol edilmiş" olsa da zayıf).

Ancak aria-expanded taklit etmek mümkündür . Sadece etiketimize aşağıdaki gibi iki açıklık sağlamamız gerekiyor.

 <input type="checkbox" role="button" aria-haspopup="true" class="vh"> <label for="toggle" data-opens-menu> Difficulty <span class="vh expanded-text">expanded&lt;/span> <span class="vh collapsed-text">collapsed</span> <span aria-hidden="true">&#x25be;</span> </label>

Bunların her ikisi de görsel visually-hidden olarak gizlenir, ancak içinde bulunduğumuz duruma bağlı olarak yalnızca biri ekran okuyuculara da gizlenir. Yani, yalnızca birinde display: none vardır ve bu, mevcut (ancak iletilmemiş) kontrol edilen durum tarafından belirlenir:

 /* class to hide spans visually */ .vh { position: absolute !important; clip: rect(1px, 1px, 1px, 1px); padding: 0 !important; border: 0 !important; height: 1px !important; width: 1px !important; overflow: hidden; } /* reveal the correct state wording to screen readers based on state */ [type="checkbox"]:checked + label .expanded-text { display: inline; } [type="checkbox"]:checked + label .collapsed-text { display: none; } [type="checkbox"]:not(:checked) + label .expanded-text { display: none; } [type="checkbox"]:not(:checked) + label .collapsed-text { display: inline; }

Bu akıllıca ve hepsi, ancak tartıştığımız beklenen odaklanma davranışları JavaScript olmadan uygulanamayacağından menü düğmemiz hala eksik.

Bu davranışlar gelenekseldir ve beklenir, bu da düğmeyi daha kullanışlı hale getirir. Ancak, JavaScript olmadan gerçekten bir menü düğmesi uygulamanız gerekiyorsa, bu, alabileceğiniz en yakın şeydir. Daha önce ele aldığım kısa gezinme menü düğmesinin JavaScript'e bağlı olmayan menü içeriği (yani bağlantılar) sunduğu göz önüne alındığında, bu yaklaşım uygun bir seçenek olabilir.

Eğlenmek için, JavaScript içermeyen bir gezinme menü düğmesi uygulayan bir codePen burada.

CodePen'de Heydon (@heydon) tarafından yazılan Kalem Gezinti menü düğmesi örneğine bakın.

( Not: Menüyü yalnızca Boşluk açar.)

"Seç" olayı

Dinleyicileri ayarlayabilmemiz için bazı yöntemleri yürütmek olaylar yaymalıdır. Örneğin, bir kullanıcı bir menü öğesini tıkladığında bir choose olayı yayınlayabiliriz. Bunu, olayın detail özelliğine bir argüman iletmemize izin veren CustomEvent kullanarak ayarlayabiliriz. Bu durumda, argüman (“seçim”), seçilen menü öğesinin DOM düğümü olacaktır.

 MenuButton.prototype.choose = function (choice) { // Define the 'choose' event var chooseEvent = new CustomEvent('choose', { detail: { choice: choice } }); // Dispatch the event this.button.dispatchEvent(chooseEvent); return this; }

Bu mekanizma ile yapabileceğimiz her türlü şey var. Belki de menuFeedback id kurulmuş bir canlı bölgemiz var:

 <div role="alert"></div>

Artık bir dinleyici kurabilir ve canlı bölgeyi event içinde saklanan bilgilerle doldurabiliriz:

 exampleMenuButton.addEventListener('choose', function (e) { // Get the node's text content (label) var choiceLabel = e.details.choice.textContent; // Get the live region node var liveRegion = document.getElementById('menuFeedback'); // Populate the live region liveRegion.textContent = 'Your difficulty level is ${choiceLabel}'; });
Kullanıcı bir seçeneği belirlediğinde menü kapanır ve odak menü düğmesine döner. Menü kapatıldıktan sonra kullanıcıların tetikleyici öğeye döndürülmesi önemlidir.
Kullanıcı bir seçeneği belirlediğinde menü kapanır ve odak menü düğmesine döner. Menü kapatıldıktan sonra kullanıcıların tetikleyici öğeye döndürülmesi önemlidir. (Büyük önizleme)

Bir menü öğesi seçildiğinde, ekran okuyucu kullanıcısı "[menü öğesinin etiketini] seçtiniz" ifadesini duyar. Canlı bir bölge (burada role=“alert” özniteliği ile tanımlanır), bu içerik değiştiğinde içeriğini ekran okuyucularında duyurur. Canlı bölge zorunlu değildir, ancak kullanıcının bir menü seçimi yapmasına yanıt olarak arayüzde neler olabileceğinin bir örneğidir.

Kalıcı Seçenekler

Tüm menü öğeleri kalıcı ayarları seçmek için değildir. Birçoğu, basıldığında arayüzde bir şeyin olmasını sağlayan standart düğmeler gibi davranır. Bununla birlikte, zorluk menü düğmemiz söz konusu olduğunda, mevcut zorluk ayarının hangisi olduğunu - en son seçileni - belirtmek istiyoruz.

aria-checked="true" niteliği, menuitem yerine menuitemradio rolünü alan öğeler için çalışır. İkinci öğe işaretliyken ( set ) gelişmiş işaretleme şöyle görünür:

 <button aria-haspopup="true" aria-expanded="false"> Difficulty <span aria-hidden="true">&#x25be;</span> </button> <div role="menu"> <button role="menuitemradio" tabindex="-1">Easy</button> <button role="menuitemradio" aria-checked="true" tabindex="-1">Medium</button> <button role="menuitemradio" tabindex="-1">Incredibly Hard</button> </div>

Birçok platformdaki yerel menüler, onay işaretlerini kullanarak seçilen öğeleri gösterir. Bunu biraz fazladan CSS kullanarak sorunsuz bir şekilde yapabiliriz:

 [role="menuitem"] [aria-checked="true"]::before { content: '\2713\0020'; }

Ekran okuyucu çalışırken menüde gezinirken, bu işaretli öğeye odaklanmak, "onay işareti, Orta menü öğesi, işaretlendi" gibi bir duyuru isteyecektir.

İşaretli bir menuitemradio ile bir menüyü açma davranışı biraz farklıdır. Menüdeki ilk (etkin) öğeye odaklanmak yerine, bunun yerine işaretli öğeye odaklanılır.

Menü düğmesi, açılmamış menü ile başlar. İkinci (Orta) zorluk ayarının açılmasına odaklanılır. Aria tarafından kontrol edilen özniteliğin varlığına dayalı olarak bir onay işareti ile önek eklenir.
Menü düğmesi, açılmamış menü ile başlar. İkinci (Orta) zorluk ayarının açılmasına odaklanılır. Aria tarafından kontrol edilen özniteliğin varlığına dayalı olarak bir onay işareti ile önek eklenir. (Büyük önizleme)

Bu davranışın faydası nedir? Kullanıcıya (herhangi bir kullanıcıya) önceden seçmiş olduğu seçenek hatırlatılır. Çok sayıda artan seçenekli menülerde (örneğin, bir dizi yakınlaştırma düzeyi), klavyeyle çalışan kişiler, ayarlamalarını yapmak için en uygun konuma yerleştirilir.

Menü Düğmesini Ekran Okuyucuyla Kullanma

Bu videoda, Voiceover ekran okuyucu ve Chrome ile menü düğmesini kullanmanın nasıl bir şey olduğunu göstereceğim. Örnek, menuitemradio , aria-checked ve tartışılan odak davranışına sahip öğeleri kullanır. Popüler ekran okuyucu yazılımı yelpazesinde benzer deneyimler beklenebilir.

Github'da Kapsayıcı Menü Düğmesi

Kitty Giraudel ve ben, tanımladığım API özellikleri ve daha fazlasıyla bir menü düğmesi bileşeni oluşturmak için birlikte çalıştık. Bu özelliklerin çoğu için Hugo'ya teşekkür etmelisiniz, çünkü bunlar bir 11y-diyalog üzerinde yaptıkları çalışmaya dayalıdır - erişilebilir bir modal diyalog. Github ve NPM'de mevcuttur.

 npm i inclusive-menu-button --save

Ayrıca Kitty, zevkiniz için bir React sürümü yarattı.

kontrol listesi

  • Navigasyon menü sistemlerinde ARIA menü semantiğini kullanmayın.
  • İçeriğin yoğun olduğu sitelerde, iç içe açılan açılır menülerle desteklenen gezinme menülerinde yapıyı gizlemeyin.
  • Düğmeyle etkinleştirilen bir gezinme menüsünün açık/kapalı durumunu belirtmek için aria-expanded kullanın.
  • Açılan/kapanan düğmeden sonra söz konusu gezinme menüsünün odak sırasında olduğundan emin olun.
  • JavaScript içermeyen çözümlerin peşindeyken kullanılabilirlikten asla ödün vermeyin. Bu kibir.