Erişilebilirlik
Niçin Erişilebilirlik?
(a11y) olarak da anılan web erişilebilirliği, herkes tarafından kullanılabilir web sitelerinin tasarımı ve oluşturulmasıdır. Erişilebilirlik desteği, yardımcı teknolojinin web sayfalarını yorumlamasına izin vermek için gereklidir.
React, sıklıkla standart HTML tekniklerini kullanarak, tamamen erişilebilir web siteleri oluşturmayı destekler.
Standartlar ve Yönergeler
WCAG
Web İçeriği Erişilebilirlik Yönergeleri, erişilebilir web siteleri oluşturmak için yönergeler sağlar.
Aşağıdaki WCAG kontrol listeleri genel bir bakış sağlar:
WAI-ARIA
Web Erişilebilirlik Girişimi - Erişilebilir Zengin İnternet Uygulamaları belgesi, tamamen erişilebilir JavaScript widgetleri oluşturmak için teknikler içerir.
Tüm aria- *
HTML özelliklerinin, JSX’te tam olarak desteklendiğini unutmayın. React’teki çoğu DOM özellikleri ve nitelikleri camelCased iken, bu nitelikler düz HTML’de olduğu gibi hyphen-cased şeklinde olmalıdır (kebab-case, lisp-case, ve benzeri olarak da bilinir):
<input
type="text"
aria-label={labelText} aria-required="true" onChange={onchangeHandler}
value={inputValue}
name="name"
/>
Anlamsal HTML
Anlamsal HTML, bir web uygulamasında erişilebilirliğin temelidir. Web sitelerimizdeki bilginin anlamını pekiştirmek için, çeşitli HTML öğelerini kullanmak sıklıkla bize ücretsiz olarak erişilebilirlik sağlayacaktır.
Bazen, React kodumuzun çalışması için JSX’imize <div>
öğeleri eklediğimizde, HTML’in anlamsallığını bozarız, özellikle listeler (<ol>
, <ul>
ve <dl>
), ve HTML <table>
ile çalışırken.
Bu durumlarda, çoklu öğeleri gruplamak için React Fragmentleri kullanmayı tercih etmelisiniz.
Örneğin,
import React, { Fragment } from 'react';
function ListItem({ item }) {
return (
<Fragment> <dt>{item.term}</dt>
<dd>{item.description}</dd>
</Fragment> );
}
function Glossary(props) {
return (
<dl>
{props.items.map(item => (
<ListItem item={item} key={item.id} />
))}
</dl>
);
}
Başka herhangi bir öğe türünde yapacağınız gibi, bir öğe koleksiyonunu bir fragment dizisine (array’ine) eşleyebilirsiniz :
function Glossary(props) {
return (
<dl>
{props.items.map(item => (// Kolleksiyonları eşleştirirken, fragmentler de bir `anahtar` prop'a sahip olmalıdır.
<Fragment key={item.id}>
<dt>{item.term}</dt> <dd>{item.description}</dd>
</Fragment>
))} </dl>
);
}
Fragment etiketinde herhangi bir prop’a ihtiyacınız olmadığında, eğer araç gereçleriniz onu destekliyorsa kısa sözdizimi(syntax)‘ni kullanabilirsiniz:
function ListItem({ item }) {
return (
<> <dt>{item.term}</dt>
<dd>{item.description}</dd>
</> );
}
Daha fazla bilgi için, Fragmentler dokümantasyonu‘na bakınız.
Erişilebilir Formlar
Etiketlemek
<input>
ve <textarea>
gibi her HTML form kontrolunun (form control), erişilebilir halde etiketlenmiş olması gerekir. Ekran okuyucuları tarafndan da ortaya çıkan, açıklayıcı etiketler sağlamamız gerekir.
Aşağıdaki kaynaklar bize bunun nasıl yapılacağını gösterir:
- W3C bize öğelerin nasıl etiketleneceğini gösterir
- WebAIM bize öğelerin nasıl etiketleneceğini gösterir
- Paciello Group erişilebilir isimleri açıklar
Bu standart HTML uygulamaları doğrudan React’te kullanılabilmesine rağmen, for
niteliğinin JSX’de htmlFor
olarak yazıldığına dikkat edin:
<label htmlFor="namedInput">Name:</label><input id="namedInput" type="text" name="name"/>
Kullanıcı hatalarını bildirmek
Hata durumlarının tüm kullanıcılar tarafından anlaşılmış olması gerekir. Aşağıdaki link, hata metinlerinin de ekran okuyucuları tarafından nasıl algılandığını gösterir:
Odak Kontrolü
Web uygulamanızın yalnızca klavye ile tam olarak çalıştırılabildiğinden emin olun:
Klavye odağı ve odak ana hatları
Klavye odağı, klavyeden girişi kabul etmek için seçilen DOM’daki varolan öğeye başvurur. Bunu her yerde aşağıdaki resimde gösterilene benzer bir odak anahat olarak görürüz:
Eğer onu başka bir odak anahat uygulamasıyla değiştiriyorsanız, sadece bu anahattı kaldıran CSS’ini kullanın.
İstenilen içeriğe atlama mekanizmaları
Klavyede gezinmeye yardımcı olduğundan ve hızlandırdığından, kullanıcıların uygulamanızdaki geçmiş navigasyon bölümlerini atlamasına izin veren bir mekanizma sağlayın.
AtlamaLinkleri (Skiplinks) veya Navigasyon Linklerini Atlamak (Skip Navigation Links), klavye kullanıcıları, sadece sayfa ile etkileşimde bulundukları zaman görünür olan gizli navigasyon linkleridir. Bunların iç sayfa bağlantıları ve bazı stillerle uygulanması çok kolaydır:
Yardımcı teknoloji, kullanıcının bu bölümlere çabuk bir şekilde gezinmesine olanak tanıdığından, sayfa bölümlerini ayırmak için <main>
ve <aside>
gibi belirgin işaret (landmark) öğeleri ve rolleri de kullanın.
Erişilebilirliği geliştirmek için, bu öğelerin kullanımı hakkında daha fazlasını buradan okuyun
Programlayarak odağı yönetmek
React uygulamalarımız, çalışma süresinde, HTML DOM’u değiştirir, bazen klavye odağının kaybolmasına veya beklenmedik bir öğeye ayarlanmasına yol açar. Bunu düzeltmek amacıyla, klavye odağını programlı olarak doğru yönde itelemek gerekir. Örneğin, modal penceresi kapatıldıktan sonra, bir modal penceresi açan bir butona klavye odağını sıfırlatmak.
MDN Web Dokümanları buna bakar ve gezinilebilir-klavye JavaScript widgetleri‘ni nasıl inşa edebildiğimizi açıklar.
React’te odağı ayarlamak için DOM öğelerine Ref’ler‘i kullanabiliriz.
Bunu kullanarak, öncelikle, bir bileşen sınıfının JSX’indeki bir öğeye bir ref oluştururuz:
class CustomTextInput extends React.Component {
constructor(props) {
super(props);
// textInput DOM öğesini depolamak için bir ref oluşturun this.textInput = React.createRef(); }
render() {
// text input DOM'a bir referans depolamak için `ref` callback'i (geri çağrı) kullanın // bir instance alanındaki öğe (örneğin, this.textInput). return (
<input
type="text"
ref={this.textInput} />
);
}
}
Daha sonra, gerektiğinde bileşenimizde onu başka bir yere odaklayabiliriz:
focus() {
// Açık bir şekilde, işlenmemiş DOM API'ı kullanarak metin girişine odaklanın
// Not: DOM düğümünü almak için "current"e erişiyoruz
this.textInput.current.focus();
}
Bazen bir üst bileşenin, bir alt bileşendeki bir öğeye odağının ayarlanması gerekir. Bunu DOM ref’lerini üst bileşenler de ortaya çıkartarak, üst öğenin ref’ini alt öğenin DOM düğümüne ileten alt bileşen üzerindeki özel bir prop yoluyla yapabiliriz.
function CustomTextInput(props) {
return (
<div>
<input ref={props.inputRef} /> </div>
);
}
class Parent extends React.Component {
constructor(props) {
super(props);
this.inputElement = React.createRef(); }
render() {
return (
<CustomTextInput inputRef={this.inputElement} /> );
}
}
// Simdi gerektiğinde odağı ayarlayabilirsiniz.
this.inputElement.current.focus();
Bileşenleri genişletmek için bir HOC kullanırken, React’in forwardRef
fonksiyonu kullanılarak sarılmış bileşene ref’i iletmesi önerilir. Eğer üçüncü bir taraf HOC, ref iletmeyi uygulamazsa, yukarıdaki şablon yine de bir geri çekilme olarak kullanılabilir.
react-aria-modal, harika bir odak yönetimi örneğidir. Bu, tamamen erişilebilir bir modal penceresinin göreceli olarak nadir bir örneğidir.
Sadece ilk odağı iptal butonuna ayarlamak (klavye kullanıcısının başarılı eylemi yanlışlıkla etkinleştirmesini engeller) ve klavye odağını modal içinde hapsetmekle kalmaz, onu başlangıçta modalı tetikleyen öğeye geri odaklanarak sıfırlar.
Not:
Bu çok önemli bir erişilebilirlik özelliği iken, adilce kullanılması da gereken bir tekniktir. Nasıl yapılacağını tahmin etmek için değil, rahatsız edildiğinde klavye odak akışını onarmak için kullanın. kullanıcılar uygulamaları kullanmak ister.
Fare ve imleç olayları
Bir fare veya imleç olayı aracılığıyla açığa çıkan tüm fonksiyonların yalnızca klavye kullanılarak da erişilebildiğinden emin olun. Sadece imleç cihazına bağlı olarak, klavye kullanıcıları uygulamanızın kullanılamayacağı birçok duruma yönlendirilecektir.
Bunu göstermek için, tıklama olaylarının sebep olduğu bozuk erişilebilirliğin verimli bir örneğine bakalım. Bu, bir kullanıcının öğenin dışına tıklayarak, bir anda açılan pencereyi (popover) engellediği dış tıklama şablonudur.
Bu genellikle popover’ı kapatan window
nesnesine bir click
olayının bağlanarak uygulanmasıdır.
class OuterClickExample extends React.Component {
constructor(props) {
super(props);
this.state = { isOpen: false };
this.toggleContainer = React.createRef();
this.onClickHandler = this.onClickHandler.bind(this);
this.onClickOutsideHandler = this.onClickOutsideHandler.bind(this);
}
componentDidMount() { window.addEventListener('click', this.onClickOutsideHandler); }
componentWillUnmount() {
window.removeEventListener('click', this.onClickOutsideHandler);
}
onClickHandler() {
this.setState(currentState => ({
isOpen: !currentState.isOpen
}));
}
onClickOutsideHandler(event) { if (this.state.isOpen && !this.toggleContainer.current.contains(event.target)) { this.setState({ isOpen: false }); } }
render() {
return (
<div ref={this.toggleContainer}>
<button onClick={this.onClickHandler}>Select an option</button>
{this.state.isOpen && (
<ul>
<li>Option 1</li>
<li>Option 2</li>
<li>Option 3</li>
</ul>
)}
</div>
);
}
}
Bu fare gibi imleçli cihaz kullanan kullanıcılar için iyi çalışabilir. Ama bunun tek olarak klavye ile çalıştırılması, sonraki öğeye sekme yapıldığında bozuk fonksiyonelliğe yol açar, çünkü window
nesnesi asla click
olayını almaz. Bu, kullanıcıların uygulamanızı kullanmasını engelleyen belirsiz fonksiyonellige yol açabilir.
Bunun yerine onBlur
ve onFocus
gibi, aynı fonksiyonellik, uygun olay yöneticilerini kullanarak ulaşılabilir:
class BlurExample extends React.Component {
constructor(props) {
super(props);
this.state = { isOpen: false };
this.timeOutId = null;
this.onClickHandler = this.onClickHandler.bind(this);
this.onBlurHandler = this.onBlurHandler.bind(this);
this.onFocusHandler = this.onFocusHandler.bind(this);
}
onClickHandler() {
this.setState(currentState => ({
isOpen: !currentState.isOpen
}));
}
// Bir sonraki tıklamada, setTimeout kullanarak açılır pencereyi (popover) kapatıyoruz. // Bu gereklidir çünkü önce kontrol etmemiz gerekiyor, eğer // öğenin başka bir alt öğesine odaklanılmışsa, // bulanıklık olayı, yeni odak olayından önce tetiklendiği. onBlurHandler() { this.timeOutId = setTimeout(() => { this.setState({ isOpen: false }); }); }
// Bir alt öğeye odaklanılırsa, açılır pencereyi (popover) kapatmayın onFocusHandler() { clearTimeout(this.timeOutId); }
render() {
// React bulanıklığı köpürterek ve // olayları üst öğeye odaklayarak bize yardımcı olur return (
<div onBlur={this.onBlurHandler} onFocus={this.onFocusHandler}> <button onClick={this.onClickHandler}
aria-haspopup="true"
aria-expanded={this.state.isOpen}>
Select an option
</button>
{this.state.isOpen && (
<ul>
<li>Option 1</li>
<li>Option 2</li>
<li>Option 3</li>
</ul>
)}
</div>
);
}
}
Bu kod, işlevselliği hem imlece hem de klavye kullanıcılarına sunar. Ekran-okuyucu kullanıcılarını desteklemek için eklenen aria-*
prop’larına da dikkat edin. Basitlik adına, açılır pencere (popover) seçeneklerinin arrow key
etkileşimini etkinleştirmek için klavye olayları uygulanmamıştır.
Bu, sadece imleç ve fare olaylarına bağlı olan klavye kullanıcıları için, fonksiyonelliğin bozulduğu birçok duruma bir örnektir. Daima klavye ile test etmek, derhal klavyeye duyarlı olay yöneticilerini kullanarak düzeltilmiş olabilen sorunlu bölgeleri vurgular.
Daha Karmaşık Widgetler
Daha karmaşık bir kullanıcı deneyimi, daha az erişilebilir demek değildir. Erişilebilirlik en kolay şekilde mümkün olabildiğince HTML’ye yakın kodlama ile ulaşılabilir iken, en karmaşık widget bile erişilebilir şekilde kodlanmış olabilir.
Burada ARIA Durumları ve Özellikleri gibi ARIA Rolleri‘nin bilgisine gereksinim duyarız. Bunlar JSX’te tamamen desteklenmiş ve tamamen erişilebilir, yüksek dereceli fonksiyonel React bileşenleri inşa etmemize imkan veren HTML nitelikleriyle dolu araç kutularıdır.
Her çeşit widget öğesi türünün belirli bir tasarım deseni vardır ve hem kullanıcılar hem de kullanıcı ajansları gibi olanlar tarafından, belirli bir şekilde fonksiyon göstermesi beklenir:
- ARIA Yazarlık Pratikleri (APG) - Tasarım Desenleri ve Örnekler
- Heydon Pickering - ARIA Örnekleri
- Kapsayıcı Bileşenler
Düşünülmesi Gereken Diğer Hususlar
Dili ayarlamak
Ekran okuyucu yazılımı, doğru ses ayarlarını seçmek için bunu kullandığından, sayfa metinlerinin insan dilini belirtin:
Doküman başlığını ayarlamak
Dokümanın <title>
‘ını mevcut sayfa içeriğini doğru şekilde tanımlayarak ayarlayın, çünkü bu, kullanıcının mevcut sayfa içeriğinden emin olmasını sağlar:
Bunu React’te React Doküman Başlığı Bileşeni‘ni kullanarak ayarlayabiliriz.
Renk Kontrastı
Görme yetisi kısıtlı kullanıcılar tarafından, maksimum düzeyde okunabilmesi için web sitenizdeki tüm okunabilir metinlerin yeterli renk kontrastına sahip olduğundan emin olun:
- WCAG - Renk Kontrastı Gereksinimini Anlama
- Renk Kontrastı Hakkındaki Her Şey ve Onu Neden Yeniden Düşünmelisiniz
- A11yProjesi - Renk Kontrastı Nedir
Web sitenizdeki tüm durumlar için uygun renk kombinasyonlarını manuel olarak hesaplamak yorucu olabilir. Öyleyse, bunun yerine Colorable ile tüm erişilebilir bir renk paletini hesaplayın.
Aşağıda belirtilen hem aXe hem de WAVE araçları renk kontrast testlerini de içerir ve kontrast hatalarını rapor edecektir.
Kontrast testi becerilerinizi genişletmek istiyorsanız, bu araçları kullanabilirsiniz:
Geliştirme ve Test Etme Araçları
Erişilebilir web uygulamalarının oluşturulmasına yardımcı olmak için kullanabileceğimiz bir çok araç vardır.
Klavye
Şimdiye kadar en kolay ve aynı zamanda en önemli kontroller, tüm websitesinin sadece klavye ile ulaşalabilir ve kullanılabilir olduğunu test etmektir. Bunu şu şekilde yapın:
- Farenizin bağlantısını kesmek.
- Gözden geçirmek icin
Tab
veShift+Tab
kullanmak. - Öğeleri etkinleştirmek için
Enter
‘i kullanmak - Gerektiğinde, menüler ve aşağı doğru açılan (dropdown) menüler gibi, bazı öğelerle etkileşim kurmak için klavye ok tuşlarınızı kullanmak.
Geliştirme asistanı
Bazı erişilebilirlik özelliklerini doğrudan JSX kodumuzda kontrol edebiliriz. Genellikle, ARIA rolleri, durumları ve özellikleri için Intellisense kontrolleri, JSX uyumlu IDE (Integrated Development Environment)‘lerde zaten sağlanmıştır. Aşağıdaki araca da erişimimiz vardir:
eslint-plugin-jsx-a11y
ESLint için eslint-plugin-jsx-a11y eklentisi, JSX’inizdeki erişilebilirlik sorunları ile ilgili AST linting geri bildirimini sağlar. Bir çok IDE, bu bulguları doğrudan kod analizi ve kaynak kodu pencereleri ile birlikte kullanmanıza izin verir.
Create React App, bir kural alt kümesinin etkinleştirildiği bu eklentiye sahiptir. Daha da fazla erişilebilirlik kurallarını etkinleştirmek istiyorsanız, bu içerikle projenizin root (kök) dizininde bir .eslintrc
dosyası oluşturabilirsiniz:
{
"extends": ["react-app", "plugin:jsx-a11y/recommended"],
"plugins": ["jsx-a11y"]
}
Tarayıcıda erişilebilirliği test etme
Tarayıcınızda web sayfalarındaki erişilebilirlik denetimlerini çalıştırabilen bir dizi araçlar vardır. Onlar yalnızca HTML’nizin teknik erişilebilirliğini test edebildiği için, lütfen onları burada belirtilen diğer erişilebilirlik kontrolleriyle birlikte kullanın.
aXe, aXe-core ve react-axe
Deque Systemleri uygulamalarınızın otomatik ve uçtan-uça (end-to-end) erişilebilirlik testleri için aXe-core sunar. Bu modül Selenium için entegrasyonları içerir.
Erişilebilirlik Motoru veya aXe, aXe-core
üzerine inşa edilmiş bir erişilebilirlik denetçisi tarayıcı uzantısı.
Geliştirme ve hata ayıklama sırasında, bu erişilebilirlik bulgularını doğrudan konsola bildirmek için @axe-core/react modülünü de kullanabilirsiniz.
WebAIM WAVE
Web Erişilebilirlik Değerlendirme Aracı başka bir erişilebilirlik tarayıcı uzantısıdır.
Erişilebilirlik Denetçileri ve Erişilebilirlik Ağacı
Erişilebilirlik Ağacı, ekran okuyucuları gibi yardımcı teknolojilere maruz bırakılmış olması gereken, her DOM öğesi için erişilebilir nesneleri içeren DOM ağacının alt kümesidir.
Bazı tarayıcılarda, erişilebilirlik ağacındaki her öğe için erişilebilirlik bilgilerini kolayca görüntüleyebiliriz:
- Firefox’da Erişilebilirlik Denetçisini Kullanmak
- Chrome’da Erişilebilirlik Denetçisini Kullanmak
- OS X Safari’de Erişilebilirlik Denetçisini Kullanmak
Ekran Okuyucuları
Bir ekran okuyucuyla test etmek, erişilebilirlik testlerinizin bir parçasını oluşturmalıdır.
Tarayıcı / ekran okuyucu kombinasyonlarının önemli olduğunu lütfen unutmayın. Uygulamanızı, seçtiğiniz ekran okuyucuya en uygun tarayıcıda test etmeniz önerilir.
Yaygın Kullanılan Ekran Okuyucuları
Firefox İçindeki NVDA
Görsel Olmayan Masaüstü Erişimi veya NVDA(NonVisual Desktop Access) yaygın olarak kullanılan açık kaynaklı bir Windows ekran okuyucudur.
NVDA’yı en iyi şekilde nasıl kullanacağınız konusunda aşağıdaki kılavuzlara basvurun:
- WebAIM - Web Erişilebilirliğini Değerlendirmek için NVDA’yı Kullanmak
- Deque - NVDA Klavye Kısayolları
Safari içindeki VoiceOver
VoiceOver, Apple cihazlara entegre edilmiş bir ekran okuyucudur.
VoiceOver’ı nasıl etkinleştireceğiniz ve kullanacağınız ile ilgili aşağıdaki rehberlere bakın:
- WebAIM - Web Erişilebilirliğini Değerlendirmek için VoiceOver’ı Kullanmak
- Deque - OS X Klavye Kısayolları için VoiceOver
- Deque - iOS Kısayolları için VoiceOver
Internet Explorer içindeki JAWS
Job Access With Speech (Konuşma ile İş Erişimi) veya JAWS, Windows üzerinde üretken olarak kullanılan ekran okuyucudur.
JAWS’ın en iyi nasıl kullanılacağına ilişkin aşağıdaki rehberlere başvurun:
Diğer Ekran Okuyucuları
Google Chrome içindeki ChromeVox
ChromeVox, Chromebooks’daki bir ekran okuyucudur ve Google Chrome için bir uzantı olarak vardır.
ChromeVox’un en iyi nasıl kullanılacağına ilişkin aşağıdaki rehberlere başvurun: