Kuinka kirjoittaa esteetön JavaScript

Käärität verkkoprojektia ja aivan kuten viimeistelet, saat lähettämäsi luettelon esteettömyysvirheistä, jotka projektipäällikkö on lähettänyt sinulle. Riittämätön värikontrasti. Puuttuvat alt-tunnisteet. Tämän interaktiivisen komponentin on oltava näppäimistön käytettävissä.

Emme ehkä halua myöntää sitä, mutta olemme kaikki olleet siellä: lopussa projekti, joka yrittää kääntää suunnittelijoiden esteettömyyden sivustollemme. Se on turhauttavaa kehittäjille, suunnittelijoille, projektipäälliköille ja asiakkaille.

Vaikka saavutettavuus voi olla turhauttavaa, voit asettaa itsesi, ryhmäsi ja asiakkaasi menestymään suunnittelemalla saavutettavuuden alusta alkaen. Tässä on neljä tekniikkaa, joilla säästät aikaa ja vaivaa, kun rakennat esteettömiä JavaScript-yhteensopivia verkkosivustoja ja sovelluksia.

1. Käytä

Semanttisten HTML-elementtien käyttö on yleensä apu verkkoprojektisi saavutettavuudelle. Kun työskentelet interaktiivisuuden kanssa, on semanttinen tunniste käyttäjille napsauttamalla asioita, jotka eivät ole linkkejä tai muita tuloja. Semanttinen tapa ilmaista, että elementti on napsautettavissa ja on uusi paras ystäväsi.

HTML <-painike> -elementti edustaa napsautettavaa painiketta.
- Mozilla-kehittäjäverkko

Kun käytät

        
  • Näytelinkki
  •     
  • Näytelinkki 2
  •     
  • Mallilinkki 3
  • Nyt meidän on vaihdettava laajennettua tilaa. Tavallisesti teen tämän setAttribute () -menetelmällä.

    const listExpander = document.querySelector ('. list-expander');
    const list = document.querySelector ('# laajennettavissa oleva lista-1');
    listExpander.addEventListener ('napsauta', (e) => {
        if (list.getAttribute ('aria-expand') === "true") {
            list.setAttribute ('aria-laajennettu', 'väärä');
        } muuta {
            list.setAttribute ('aria-laajennettu', 'tosi');
        }
    });

    Huomaa, että kun tarkistan nähdäksesi aaria-laajennetun määritteen arvon, käytän === "true". Tämä johtuu siitä, että getAttribute tuottaa joko merkkijonon "true" tai "false", ei todellisen todellisen tai väärän arvon. (Se laukaisi minut ensin).

    Voit käyttää samanlaista ajattelua muiden tosi / väärien ARIA-määritteiden kanssa. Yleensä käytän tätä aria-piilotettuna modaalien valintaikkunoiden näyttämiseen ja piilottamiseen.

    4. Tarkennuksen hallinta

    Viimeinen asia, jonka käsittelemme tässä oppaassa, on keskittymisen hallinta. Tarkennus viittaa selaimen yksittäiseen elementtiin, johon voidaan toimia näppäimistön kautta. Elementit keskittyvät usein, kun käyttäjä napsauttaa niitä, käyttää TAB-näppäintä selataksesi tarkennettavia elementtejä tai käyttää näytönlukijaa. Perustasolla sinun on varmistettava, että käyttäjät voivat milloin tahansa visuaalisesti kertoa, mikä elementti on keskittynyt.

    Yleisin paikka, jossa pääsen hallitsemaan keskittymistä, on modaalikomponentit.

    Tässä on näyteongelma, joka meidän on ratkaistava. Meillä on noin sivu, joka sisältää henkilön biografian ja painikkeen, jonka otsikko on ”Ota yhteyttä tähän ihmiseen”. Tämä painike avaa modaalin, joka sisältää yhteyslomakkeen. Mutta jos muoto ei ole sivun luonnollisessa välilehtijärjestyksessä (kuten on yleistä modaalien kohdalla), kun käyttäjä osuu välilehteen, hänen näppäimistön painopiste on modaalin takana. On tavallista, että näppäimistön ja avustavan tekniikan käyttäjät takertuvat ja turhautuvat huonosti suunniteltuihin malleihin.

    Tämän ratkaisemiseksi haluamme tehdä pari asiaa:

    1. Kun modaali aukeaa, siirrä tarkennus ensimmäiseen tarkennettavaan elementtiin modaalin sisällä.
    2. Varmista, että käyttäjät voivat helposti sulkea modaalin näppäimistön kautta, kun se on auki.
    3. Kun modaali sulkeutuu, palaa keskittyminen elementtiin, joka oli aktiivinen modaalin avautuessa.
    4. Jos haluamme olla todella varovaisia, voimme ansata TAB: n eteenpäin ja taaksepäin modaalin sisällä, jotta käyttäjät eivät pääse pakenemaan, elleivät sulje modaalia.

    Hanki ensimmäinen tarkennettava elementti.

    Minulla on muutamia auttajamenetelmiä, jotka auttavat minua määrittämään kaikki tarkennettavat elementit ja ensimmäisen tarkennettavan elementin tietyssä yhteydessä. Näin löydät kaikki tarkennettavat elementit sivulta (Chris Ferdinandi).

    / **
      * Hanki kaikki tarkennettavat elementit määriteltyyn kontekstiin.
      *
      * @param {String} [context = 'document'] DOM-konteksti, josta haluat etsiä.
      * @return {Array} Tarkennettavien elementtien ryhmä
      * /
    funktio getFocusable (konteksti = 'asiakirja') {
        anna tarkennettavissa = Array.from (konteksti.querySelectorAll ('painike, [href], valitse, tekstialue, syöttö: ei ([type = "piilotettu"]), [tabindex]: ei ([tabindex = "- 1"]) '));
        palata keskittyvä;
    }

    Tämä toiminto käyttää querySelectorAll-luetteloa valitsimista, jotka ovat yleensä tarkennettavissa: , linkit href-määriteeseen, tulot ja asiat, joissa on tabindex-asetus (joka ei ole -1). Suodatin myös -valitsinta poistamalla kaikki piilotetut tulot, koska niitä ei voi tarkentaa. Suoritan samanlaista suodatusta elementeille, joiden tabindex-määrite on asetettu arvoon -1, koska näiden elementtien tulisi olla tarkennettavissa vain JavaScript-menetelmällä, ei normaalissa välilehtihakemistossa. Käytän Array.from-yksikköä luomalla taulukon kyselyn palauttamasta NodeList-tiedostosta.

    Pidän tästä toiminnosta, että voin myös kulkea tilanteessa. Oletusarvon mukaan konteksti on asetettu dokumentoitavaksi, joten se löytää kaikki asiakirjassa tarkennettavat elementit. Mutta yllä olevassa modaalisessa esimerkissämme voisit siirtää modaalielementin itse kontekstina ja saada luettelon modaalin kaikista tarkennettavista elementeistä elements.

    Ensimmäisen tarkennettavan elementin löytäminen on nyt triviaalia, kysymys on ryhmän ensimmäisen elementin hyppäämisestä. Minulla on yleensä toinen avustajatoiminto saadakseni minulle ensimmäisen tarkennettavan elementin, enkä oikeastaan ​​soita ensimmäiselle. Se on näin:

    / **
     * Hanki kaikki tarkennettavat elementit määriteltyyn kontekstiin.
     *
     * @param {String} [context = 'document'] DOM-konteksti, josta haluat etsiä.
     * @return {Array} Tarkennettavien elementtien ryhmä
     * /
    funktio getFocusable (konteksti = 'asiakirja') {
        anna tarkennettavissa = Array.from (konteksti.querySelectorAll ('painike, [href], valitse, tekstialue, syöttö: ei ([type = "piilotettu"]), [tabindex]: ei ([tabindex = "- 1"]) '));
        palata keskittyvä;
    }

    Ohitat kontekstin, ja se kutsuu alkuperäistä getFocusable () -toimintoamme ja palauttaa taulukon ensimmäisen kohteen. Nyt voimme kutsua fokusta () siihen elementtiin, jotta voidaan kohdistaa ohjelmoidusti ensimmäinen tarkennettava elementti. Se näyttää tältä:

    getFirstFocusable (modaalinen) .focus ();

    Varmista, että käyttäjät voivat helposti sulkea modaalin näppäimistön kautta, kun se on auki

    Olemme käsitellyt tätä osittain aiemmin, kun keskustelemme yhteisten näppäimistötoimintojen suunnittelusta. Tämä on täydellinen esimerkki ajasta, jolloin haluat käyttäjän päästä ESC-komponenttiin.

    Voit myös lisätä peittokuvan modaalin ja sivustosisällön väliin, jota voidaan napsauttaa ja tarkentaa, kun napsautustapahtumat sulkevat modaalin.

    Kun modaali sulkeutuu, palaa keskittyminen elementtiin, joka oli aktiivinen modaalin avautuessa.

    Esimerkissämme käyttäjä napsautti painiketta ja sitten heidän keskittymisensä hyppäsi modaaliin. Kun he sulkevat modaalin, haluamme palauttaa heidän tarkennuksensa painikkeeseen, joka laukaisi modaalin. Tämä on oikeastaan ​​melko triviaalia document.activeElement-ominaisuuden avulla.

    Kun havaitsemme, että modaalin pitäisi avautua, ja ennen kuin siirrämme tarkennuksen siihen modaaliin, voimme tallentaa nykyisen aktiivisen elementin muuttujaan, joka on seuraava:

    anna previousActiveElement = document.activeElement;

    Sitten voimme siirtää tarkennuksen ensimmäiseen tarkennettavissa olevaan elementtiin, ja aina kun käyttäjä suorittaa modaalin ja päättää sulkea sen, siirrämme tarkennuksen takaisin tallennettuun elementtiin:

    previousActiveElement.focus ();

    Ja nyt käyttäjä on palannut mihin he aloittivat!

    Lukitse TAB ja SHIFT + TAB modaalin sisään

    Kuten edellä mainitsin, jos haluamme olla todella varovaisia, voimme ansata TAB: n eteenpäin ja taaksepäin modaalin sisällä, jotta käyttäjät eivät pääse pakenemaan, elleivät sulje modaalia.

    Tätä varten meidän on kuunneltava näppäimistötapahtumaa, kun modaali on aktiivinen, ja tässä on toiminto, jota käytän tarkennuksen vangitsemiseen (se riippuu getFocusable () -toiminnostamme ylhäältä:

    / **
     * Sieppaa välilehden näppäimen kontekstin sisään, joten käyttäjä ei pääse vahingossa
     * jumissa sen takana.
     *
     * Huomaa, että tämä ei toimi VoiceOver-käyttäjille, jotka navigoivat
     * VoiceOver-komennot, vain välilehden oletustoimintoihin. Meidän pitäisi
     * ota käyttöön jotain inerttiä ominaisuutta, kuten (katso https://github.com/WICG/inert)
     * @param {object} e Tapahtumaobjekti
     * /
    vientitoiminto trapTabKey (e, konteksti) {
        if (e.key! == 'Tab') palaa;
    
        anna focusableItems = getFocusable (konteksti);
        anna focusItem = document.activeElement;
    
        anna focusItemIndex = focusableItems.indexOf (focusItem);
    
        if (e.shiftKey) {
            if (focusItemIndex == 0) {
                focusableItems [focusableItems.length - 1] .focus ();
                e.preventDefault ();
            }
        } muuta {
            if (focusItemIndex == focusableItems.length - 1) {
                focusableItems [0] .focus ();
                e.preventDefault ();
            }
        }
    }

    Ensinnäkin meidän on läpäistävä tapahtumaobjekti, jotta voimme havaita mitä näppäintä painetaan ja konteksti, jonka avulla käyttäjä voidaan "loukkaa" sisälle.

    Jos heidän paintama avain ei ollut TAB-näppäin, voimme palata turvallisesti emmekä tee mitään.

    Jos se oli TAB-näppäin, saamme kaikki tarkennettavat elementit modaaliin ja elementin, johon ne ovat tällä hetkellä keskittyneet. Kun nämä kaksi asiaa on saatu, voimme käyttää indexOf-menetelmää kertoaksesi käyttäjän sijainnin tässä kontekstin välilehtijärjestyksessä.

    Jos he pitivät vaihtonäppäintä (e.shiftKey === totta), he menivät taaksepäin, joten haluamme pysäyttää ne, kun he pääsevät modaalin ensimmäiseen tarkennettavaan kohtaan ja keskittyä viimeiseen tarkennettavaan kohtaan: focusableItems [focusableItems .length - 1] .focus ().

    Jos he etenivät eteenpäin ja pääsivät modaalin viimeiseen tarkennettavaan kohtaan (focusItemIndex == focusableItems.length - 1), meidän on tarkennettava ensimmäinen tarkennettava kohta.

    Meidän on kutsuttava e.preventDefault () molemmille näille tapauksille, jotta estetään oletusarvoisen TAB-toiminnon käynnistyminen. Kaikissa muissa tapauksissa voimme kuitenkin antaa heidän olla TAB normaalisti.

    Haluat varmistaa, että olet poistanut näppäimistötapahtuman kuuntelijan, kun käyttäjä sulkee muodon antaa TAB-toiminnallisuutensa palata normaaliksi.

    johtopäätös

    Olemme käsitellyt paljon täällä, mutta sinun pitäisi olla todella hyvä lähtökohta aloittaa kehitettävien interaktiivisten JavaScript-sivustojen ja sovellusten kehittäminen ja antaa sinulle puitteet ajatella, kuinka voit ohjelmoida muita widgettejä ja komponentteja. Muista:

    1. Käytä napsautettaviin elementteihin
    2. Suunnittele tavalliset näppäimistövuorovaikutukset, kuten ESC, Nuolet, Enter ja TAB.
    3. Ajattele ja hallitse kaikkia sopivia ARIA-tiloja.
    4. Hallitse tarkennusta tarvittaessa.

    Jos pidät nämä tekniikat alusta alkaen, säästät aikaa ja vaivaa ja käyttäjän kiitos!

    Ja jos haluat nähdä lisää esimerkkejä pääsyä helpottavien verkkosivustojen rakentamisesta, kirjaudu ilmaiseksi sähköpostikurssilleni: 9 yleistä verkkosivustojen saatavuusvirheitä ja kuinka korjaan ne. Pääset kurssille ilmoittautumalla täällä!

    Alun perin julkaistu osoitteessa benrobertson.io.