Skip to content

Přístupnost

Přístupnost (accessibility) webu (také známá jako a11y) označuje praxi vytváření webových stránek, které mohou být používány kýmkoli - ať už se jedná o osobu s postižením, pomalým připojením, zastaralým nebo nefunkčním hardwarem nebo jednoduše o někoho v nevhodném prostředí. Například přidání titulků k videu pomůže jak uživatelům se sluchovým postižením, tak uživatelům, kteří se nacházejí v hlučném prostředí a nemohou svůj telefon slyšet. Stejně tak ujištšní se, že váš text nemá příliš nízký kontrast, pomůže jak uživatelům se zrakovým postižením, tak uživatelům, kteří se snaží svůj telefon používat na přímém slunci.

Jste připraveni začít, ale nevíte přesně jak?

Podívejte se na Průvodce plánováním a správou přístupnosti webu poskytovaného World Wide Web Consortium (W3C)

Na začátek každé stránky byste měli přidat odkaz, který vede přímo do hlavního obsahového prostoru, aby uživatelé mohli přeskočit struktury, které se opakují na více webových stránkách.

Obvykle se to dělá na začátku souboru App.vue, protože to bude první focusable prvek na všech vašich stránkách:

template
<ul class="skip-links">
  <li>
    <a href="#main" ref="skipLink" class="skip-link">Přejít na hlavní obsah</a>
  </li>
</ul>

Chcete-li odkaz skrýt, pokud na něm není focus, můžete přidat následující styl:

css
.skip-link {
  white-space: nowrap;
  margin: 1em auto;
  top: 0;
  position: fixed;
  left: 50%;
  margin-left: -72px;
  opacity: 0;
}
.skip-link:focus {
  opacity: 1;
  background-color: white;
  padding: 0.5em;
  border: 1px solid black;
}

Jakmile uživatel změní cestu, vraťte focus zpět na odkaz pro přeskočení na obsah. Toho lze dosáhnout voláním funkce focus() na prvku v rámci template ref (pokud používáte vue-router):

vue
<script>
export default {
  watch: {
    $route() {
      this.$refs.skipLink.focus()
    }
  }
}
</script>
vue
<script setup>
import { ref, watch } from 'vue'
import { useRoute } from 'vue-router'

const route = useRoute()
const skipLink = ref()

watch(
  () => route.path,
  () => {
    skipLink.value.focus()
  }
)
</script>

Přečtěte si dokumentaci pro odkaz na přeskočení na hlavní obsah

Struktura obsahu

Jedním z nejdůležitějších prvků přístupnosti je zajistit, aby design podporoval přístupnou implementaci. Design by měl zohledňovat nejen kontrast barev, výběr písma, velikost textu a jazyk, ale také způsob, jak je obsah v aplikaci strukturován.

Nadpisy

Uživatelé mohou v aplikaci navigovat pomocí nadpisů. Mít popisné nadpisy pro každou část vaší aplikace uživatelům usnadňuje předvídat obsah každé sekce. Pokud jde o nadpisy, pro přístupnost existuje několik doporučených postupů:

  • Vnořujte nadpisy podle jejich pořadí: <h1> - <h6>
  • Nepřeskakujte nadpisy uvnitř sekce
  • Používejte skutečné tagy pro nadpisy místo stylování textu, aby vypadal jako nadpisy

Více informací o nadpisech

template
<main role="main" aria-labelledby="main-title">
  <h1 id="main-title">Hlavní nadpis</h1>
  <section aria-labelledby="section-title-1">
    <h2 id="section-title-1">Nadpis sekce</h2>
    <h3>Nadpis podsekce</h3>
    <!-- Obsah -->
  </section>
  <section aria-labelledby="section-title-2">
    <h2 id="section-title-2">Nadpis sekce</h2>
    <h3>Nadpis podsekce</h3>
    <!-- Obsah -->
    <h3>Nadpis podsekce</h3>
    <!-- Obsah -->
  </section>
</main>

Orientační body

Orientační body (landmarks) poskytují programový přístup k sekcím v rámci aplikace. Uživatelé, kteří se spoléhají na asistenční technologie, mohou přejít na každou sekci aplikace a přeskočit obsah. Abyste tohoto dosáhli, můžete použít ARIA role.

HTMLARIA RoleÚčel orientačního bodu
headerrole="banner"Hlavní nadpis: název stránky
navrole="navigation"Sbírka odkazů vhodných pro navigaci v dokumentu nebo souvisejících dokumentech
mainrole="main"Hlavní nebo centrální obsah dokumentu
footerrole="contentinfo"Informace o nadřazeném dokumentu: poznámky/kopie práv/odkazy na prohlášení o ochraně soukromí
asiderole="complementary"Podporuje hlavní obsah, ale je oddělený a má vlastní význam
searchrole="search"Tato sekce obsahuje funkce pro vyhledávání v aplikaci
formrole="form"Sbírka prvků spojených s formulářem
sectionrole="region"Obsah, který je relevantní a který uživatelé pravděpodobně budou chtít procházet. Pro tento prvek musí být poskytnut label

Více informací o orientačních bodech

Sémantické formuláře

Při vytváření formuláře můžete použít následující elementy: <form>, <label>, <input>, <textarea> a <button>

Popisky (labels) jsou obvykle umístěny nad nebo vlevo od polí formuláře:

template
<form action="/dataCollectionLocation" method="post" autocomplete="on">
  <div v-for="item in formItems" :key="item.id" class="form-item">
    <label :for="item.id">{{ item.label }}: </label>
    <input
      :type="item.type"
      :id="item.id"
      :name="item.id"
      v-model="item.value"
    />
  </div>
  <button type="submit">Odeslat</button>
</form>

Všimněte si, že na element formuláře můžete přidat autocomplete='on' a bude se aplikovat na všechny vstupy ve formuláři. Pro každý vstup můžete také nastavit různé hodnoty atributu autocomplete.

Popisky

Poskytujte popisky (labels), které popisují účel všech ovládacích prvků formuláře; propojte for a id:

template
<label for="name">Jméno:</label>
<input type="text" name="name" id="name" v-model="name" />

Pokud zkontrolujete tento element v nástrojích pro vývojáře v Chrome DevTools a otevřete záložku Přístupnost (Accessibility) v rámci záložky Elements, uvidíte, jak vstup získává své jméno z popisku:

Chrome Developer Tools zobrazující přístupné jméno vstupu z popisku

Varování

Možná jste viděli vstupní pole takto obalená popisky:

template
<label>
  Jméno:
  <input type="text" name="name" id="name" v-model="name" />
</label>

Explicitní nastavení popisků s odpovídajícím id je v asistenčních technologiích podporováno lépe.

aria-label

Také můžete vstupu přidat přístupné jméno (accessible name) pomocí aria-label.

template
<label for="name">Jméno:</label>
<input
  type="text"
  name="name"
  id="name"
  v-model="name"
  :aria-label="nameLabel"
/>

Můžete si tento element prohlédnout v Chrome DevTools, abyste viděli, jak se přístupné jméno změnilo:

Chrome Developer Tools zobrazující přístupné jméno vstupu z aria-label

aria-labelledby

Použití aria-labelledby je podobné jako aria-label, s tím rozdílem, že se používá, pokud je text štítku viditelný na obrazovce. Je propojen s dalšími prvky pomocí jejich id a můžete propojit více id:

template
<form
  class="demo"
  action="/dataCollectionLocation"
  method="post"
  autocomplete="on"
>
  <h1 id="billing">Fakturace</h1>
  <div class="form-item">
    <label for="name">Jméno:</label>
    <input
      type="text"
      name="name"
      id="name"
      v-model="name"
      aria-labelledby="billing name"
    />
  </div>
  <button type="submit">Odeslat</button>
</form>

Chrome Developer Tools zobrazující přístupné jméno vstupu z aria-labelledby

aria-describedby

aria-describedby se používá stejným způsobem jako aria-labelledby, ale poskytuje popis s dodatečnými informacemi, které by uživatel mohl potřebovat. Lze to použít k popisu kritérií pro jakýkoli vstup:

template
<form
  class="demo"
  action="/dataCollectionLocation"
  method="post"
  autocomplete="on"
>
  <h1 id="billing">Fakturace</h1>
  <div class="form-item">
    <label for="name">Celé jméno:</label>
    <input
      type="text"
      name="name"
      id="name"
      v-model="name"
      aria-labelledby="billing name"
      aria-describedby="nameDescription"
    />
    <p id="nameDescription">Prosím, zadejte křestní jméno a příjmení.</p>
  </div>
  <button type="submit">Odeslat</button>
</form>

Popis můžete vidět v Chrome DevTools:

Chrome Developer Tools zobrazující přístupné jméno vstupu z aria-labelledby a popis z aria-describedby

Placeholder

Vyhněte se používání placeholderů, protože mohou řadu uživatelů zmást.

Jedním z problémů s placeholdery je, že výchozí stav nesplňuje kritéria barevného kontrastu; oprava barevného kontrastu způsobí, že placeholder vypadá jako předvyplněná data ve vstupních polích. Podívejte se na následující příklad, kde můžete vidět, že placeholder pro příjmení, který splňuje kritéria barevného kontrastu, vypadá jako předvyplněná data:

Přístupný placeholder

template
<form
  class="demo"
  action="/dataCollectionLocation"
  method="post"
  autocomplete="on"
>
  <div v-for="item in formItems" :key="item.id" class="form-item">
    <label :for="item.id">{{ item.label }}: </label>
    <input
      type="text"
      :id="item.id"
      :name="item.id"
      v-model="item.value"
      :placeholder="item.placeholder"
    />
  </div>
  <button type="submit">Odeslat</button>
</form>
css
/* https://www.w3schools.com/howto/howto_css_placeholder.asp */

#lastName::placeholder {
  /* Chrome, Firefox, Opera, Safari 10.1+ */
  color: black;
  opacity: 1; /* Firefox */
}

#lastName:-ms-input-placeholder {
  /* Internet Explorer 10-11 */
  color: black;
}

#lastName::-ms-input-placeholder {
  /* Microsoft Edge */
  color: black;
}

Nejlepší je poskytnout všechny informace, které uživatel k vyplnění formuláře potřebuje, mimo jakékoli vstupy.

Instrukce

Při přidávání instrukcí pro vaše vstupní pole se ujistěte, že je správně propojíte s vstupem. Můžete poskytnout dodatečné instrukce a propojit více ID uvnitř aria-labelledby. To umožňuje flexibilnější design.

template
<fieldset>
  <legend>Použití aria-labelledby</legend>
  <label id="date-label" for="date">Aktuální datum:</label>
  <input
    type="date"
    name="date"
    id="date"
    aria-labelledby="date-label date-instructions"
  />
  <p id="date-instructions">DD.MM.YYYY</p>
</fieldset>

Alternativně můžete instrukce k vstupu připojit pomocí aria-describedby:

template
<fieldset>
  <legend>Použití aria-describedby</legend>
  <label id="dob" for="dob">Datum narození:</label>
  <input type="date" name="dob" id="dob" aria-describedby="dob-instructions" />
  <p id="dob-instructions">DD.MM.YYYY</p>
</fieldset>

Skrývání obsahu

Obvykle se nedoporučuje vizuálně skrývat popisky, i když má vstup přístupné jméno. Pokud však funkčnost vstupu lze z okolního kontextu pochopit, můžeme popisek skrýt.

Podívejme se na toto vyhledávací pole:

template
<form role="search">
  <label for="search" class="hidden-visually">Hledat:</label>
  <input type="text" name="search" id="search" v-model="search" />
  <button type="submit">Hledat</button>
</form>

Můžeme to udělat, protože tlačítko pro vyhledávání pomůže vizuálním uživatelům účel vstupního pole identifikovat.

Můžeme použít CSS k vizuálnímu skrytí prvků, ale přitom je ponechat dostupné pro asistenční technologie:

css
.hidden-visually {
  position: absolute;
  overflow: hidden;
  white-space: nowrap;
  margin: 0;
  padding: 0;
  height: 1px;
  width: 1px;
  clip: rect(0 0 0 0);
  clip-path: inset(100%);
}

aria-hidden="true"

Přidáním aria-hidden="true" se prvek skryje před asistenční technologií, ale zůstane vizuálně dostupný pro ostatní uživatele. Nepoužívejte jej na ovladatelných prvcích, pouze na dekorativním, duplikovaném nebo mimo obrazovku umístěném obsahu.

template
<p>Toto není před čtečkami obrazovky skryto.</p>
<p aria-hidden="true">Toto je před čtečkami obrazovky skryto.</p>

Tlačítka

Při použití tlačítek uvnitř formuláře musíte nastavit typ, aby nedošlo k odeslání formuláře. Pro vytvoření tlačítek můžete také použít element input:

template
<form action="/dataCollectionLocation" method="post" autocomplete="on">
  <!-- Tlačítka -->
  <button type="button">Zrušit</button>
  <button type="submit">Odeslat</button>

  <!-- Input tlačítka -->
  <input type="button" value="Zrušit" />
  <input type="submit" value="Odeslat" />
</form>

Funkční obrázky

Můžete použít tuto techniku k vytvoření funkčních obrázků (functional images).

  • Vstupní pole

    • Tyto obrázky budou ve formulářích sloužit jako tlačítko typu submit
    template
    <form role="search">
      <label for="search" class="hidden-visually">Hledat:</label>
      <input type="text" name="search" id="search" v-model="search" />
      <input
        type="image"
        class="btnImg"
        src="https://img.icons8.com/search"
        alt="Hledat"
      />
    </form>
  • Ikony

template
<form role="search">
  <label for="searchIcon" class="hidden-visually">Hledat:</label>
  <input type="text" name="searchIcon" id="searchIcon" v-model="searchIcon" />
  <button type="submit">
    <i class="fas fa-search" aria-hidden="true"></i>
    <span class="hidden-visually">Hledat</span>
  </button>
</form>

Standardy

World Wide Web Consortium (W3C) Web Accessibility Initiative (WAI) vyvíjí standardy pro přístupnost webu pro různé komponenty:

Směrnice pro přístupnost webového obsahu (WCAG)

WCAG 2.1 rozšiřuje WCAG 2.0 a umožňuje implementaci nových technologií tím, že se zabývá změnami na webu. W3C doporučuje při vývoji nebo aktualizaci politiky přístupnosti webu používat nejnovější verzi WCAG.

Čtyři hlavní zásady WCAG 2.1 (zkráceně POUR):

Web Accessibility Initiative – Accessible Rich Internet Applications (WAI-ARIA)

WAI-ARIA od W3C poskytuje pokyny, jak vytvářet dynamický obsah a pokročilé ovládací prvky uživatelského rozhraní.

Zdroje

Dokumentace

Pomůcky pro asistenční technologie

Testování

Uživatelé

Světová zdravotnická organizace odhaduje, že 15 % světové populace má nějakou formu postižení, z toho 2-4 % závažnou formu. To je přibližně 1 miliarda lidí po celém světě, což ze zdravotně postižených činí největší menšinovou skupinu na světě.

Existuje široká škála postižení, která lze hrubě rozdělit do čtyř kategorií:

  • Vizuální - Tito uživatelé mohou využít čteček obrazovky, zvětšování obrazovky, ovládání kontrastu obrazovky nebo braillova displeje.
  • Sluchová - Tito uživatelé mohou využít titulky, přepisy nebo videa ve znakové řeči.
  • Motorická - Tito uživatelé mohou využít řadu asistenčních technologií pro motorické postižení: softwaru pro rozpoznávání hlasu, sledování očí, přístupu pomocí jednoho tlačítka, hlavového ovladače, přepínacího ovladače ‚sip and puff‘, přizpůsobeného trackballu, adaptivní klávesnice nebo jiných asistenčních technologií.
  • Kognitivní - Tito uživatelé mohou využít doplňková média, strukturální organizaci obsahu, jasné a jednoduché psaní.

Podívejte se na následující odkazy od WebAim, abyste uživatelům lépe porozuměli:

Přístupnost has loaded