Direct naar de inhoud

Formulieren

Formulieren worden gebruikt om informatie in te vullen of te verzamelen. Om formulieren toegankelijk te maken, moet je letten op de techniek, vormgeving en tekst. Zorg dat formulier volledig met het toetsenbord te bedienen is. Gebruik duidelijke labels voor de invoervelden en geef heldere foutmeldingen als er iets misgaat. Zo wordt het invullen makkelijk voor iedereen, ook voor mensen die hulptechnolgieën gebruiken.

  • Foutmelding: waar en wat

    Bij formulieren hoort een foutcontrole ingebouwd te zijn. De foutcontrole controleert automatisch of een verplicht onderdeel leeg is gelaten of dat een invoerveld verkeerd is ingevuld. Als er een fout is gevonden, dan moet de foutmelding in tekst worden weergegeven. Deze tekst kan worden aangevuld met andere visuele aanwijzingen, zoals een andere kleur of een icoon.

    Benoem in de tekst van de foutmelding de naam van het veld dat verkeerd is ingevuld en benoem precies wat de fout is. Schrijf dus niet:

    • Dit veld is verplicht.

    Maar schrijf:

    • Het veld ‘Telefoonnummer’ mag niet leeg zijn.

    In de code kan ook worden aangegeven welk veld verkeerd is ingevuld. Gebruik hiervoor het attribuut aria-invalid. Daarnaast hoort de foutmelding in de code aan het bijbehorende invoerveld te worden gekoppeld. Dit voorkomt verwarring bij bezoekers die gebruik maken van hulptechnologieën. Een foutmelding kan op een aantal manieren worden gekoppeld zoals met een aria-describedby-attribuut.

    In de code ziet dat er zo uit:

    <label for="veld1">Telefoonnummer:</label>
    <input type="text" id="veld1" aria-invalid="true" aria-describedby="fout">
    <span id="fout">Het veld &lsquo;Telefoonnummer&rsquo; mag niet leeg zijn.</span>

    Open dit onderwerp op een eigen pagina

  • Foutmelding: suggestie erbij

    Als er een fout is gevonden en suggesties voor verbetering zijn bekend, dan moeten deze suggesties aan de bezoeker worden getoond. De suggesties kunnen worden gebruikt om beter te begrijpen wat er precies ingevuld moet worden.

    Bij veel invoervelden is bekend in welk formaat het ingevuld moet worden. Zo bestaat in Nederland een telefoonnummer uit 10 cijfers en een postcode uit 4 cijfers en 2 letters. Een goede foutmelding bestaat dan uit de mededeling dat het veld ‘telefoonnummer’ niet juist is ingevuld, en dat een telefoonnummer uit 10 cijfers bestaat.

    Schrijf dus niet:

    • Dit veld is niet juist ingevuld.

    Maar schrijf:

    • Geboortedatum is niet juist ingevuld. Gebruik het formaat dd-mm-jjjj.
    • Het veld ‘Telefoonnummer’ is niet juist ingevuld. Een telefoonnummer bestaat uit 10 cijfers.

    Enkele voorbeelden:

    • Datum wordt genoteerd in het formaat dd-mm-jjjj.
    • IBAN begint met 2 letters, 2 cijfers, 4 letters.
    • Postcode bestaat uit 4 cijfers en 2 letters.
    • Telefoonnummer bestaat uit 10 cijfers.
    • URL begint met http:// of https://.
    Doelgroepen
    Succescriteria

    Open dit onderwerp op een eigen pagina

  • Doel van een invoerveld

    Vaak moeten in formulieren gegevens worden ingevuld die bij veel andere formulieren ook worden gevraagd. Dit geldt voor veelgevraagde gegevens zoals naam, e-mailadres en telefoonnummer.

    Het doel van een invoerveld kan worden vastgelegd in de code. Hierdoor begrijpen browsers welke gegevens er worden gevraagd. Een browser kan het formulier dan al (deels) automatisch zelf invullen. Dit is handig voor alle bezoekers, maar voor bezoekers met een motorische beperking is dit nog belangrijker. Het invullen van een formulier kan hen veel tijd kosten.

    Gebruik hiervoor het autocomplete-attribuut in de code om het doel van het invoerveld toe te voegen aan het <​input​>-element.

    In de code ziet dat er zo uit:

    <label for="veld1">Naam:</label>
    <input type="text" id="veld1" autocomplete="name">
    
    <label for="veld2">Geboortedatum:</label>
    <input type="text" id="veld2" autocomplete="bday">

    Het W3C heeft een lijst met 53 doelen van invoer die in de code horen vastgelegd te worden. (https://www.w3.org/TR/WCAG21/#input-purposes).

    Open dit onderwerp op een eigen pagina

  • Slepen: wat het criterium vraagt

    Slepen vraagt drie dingen tegelijk: precies raken, ingedrukt houden en tegelijk bewegen. Voor wie beeft, met zijn ogen aanwijst of een schakelaar gebruikt zijn dat drie opgaven achter elkaar. Kan een functie alleen met slepen worden bediend, zorg dan dat die ook met losse klikken of tikken werkt.

    Dit criterium is nieuw in WCAG 2.2 en staat op niveau AA.

    Waar het opduikt:

    • Schuifregelaars voor een prijsbereik of het volume.
    • Lijsten die je herschikt door onderdelen te verslepen.
    • Kaarten die je moet verschuiven om een ander gebied te zien.
    • Een carrousel die alleen met vegen te bedienen is.

    Er is een uitzondering als het slepen de handeling zelf is: een handtekening zetten, tekenen, schilderen. Bij twijfel helpt één vraag: is hetzelfde resultaat met knoppen te bereiken? Bij een schuifregelaar wel, bij een handtekening niet.

    Dit criterium gaat over de aanwijzer, niet over het toetsenbord. Dat laatste is 2.1.1. Ook wie een muis of aanraakscherm gebruikt maar niet kan slepen, moet erlangs kunnen. Beide criteria moeten dus kloppen.

    Open dit onderwerp op een eigen pagina

  • Tooltips: er een bouwen die blijft staan

    De eenvoudigste oplossing is geen tooltip bouwen maar de tekst op de pagina zetten. Kan dat niet, dan moeten er drie dingen kloppen.

    Escape sluit de uitleg:

    element.addEventListener('keydown', function (e) {
      if (e.key === 'Escape') { verbergTooltip(); }
    });

    De aanwijzer kan erheen. Laat geen gat tussen het onderdeel en de uitleg: beweegt de aanwijzer over dat gat, dan telt dat als wegwijzen en verdwijnt de uitleg.

    .tooltip {
      margin-block-start: 0;
      padding-block-start: 8px;
      pointer-events: auto;
    }

    En er zit geen tijdklok op. Een bezoeker die langzaam leest is na drie seconden halverwege:

    setTimeout(verbergTooltip, 3000);   /* niet doen */

    Gebruik :focus-visible naast :hover, anders krijgt een bezoeker met een toetsenbord de uitleg nooit te zien. Zet daarnaast aria-describedby op het onderdeel, zodat een schermlezer de uitleg voorleest.

    <button aria-describedby="uitleg-btw">Btw-nummer</button>
    <div id="uitleg-btw" role="tooltip">Je btw-nummer staat op je factuur.</div>

    Open dit onderwerp op een eigen pagina

  • Bij input: zo test je het

    Met een muis is deze fout nauwelijks te vinden: je klikt, kiest en bent klaar. Met het toetsenbord komt hij meteen boven.

    Ga als volgt te werk:

    • Tab naar een keuzelijst.
    • Ga met de pijltoetsen omlaag door de opties, alsof je aan het kijken bent.
    • Gebeurt er iets? Dan is dat de fout.
    • Doe hetzelfde met vinkjes en keuzerondjes: spatie erop en kijken of de pagina blijft staan.

    Vergeet de tekstvelden niet. Vul een veld in en druk op Tab om verder te gaan. Verandert er dan iets aan de pagina — een blok dat verschijnt, een sprong naar boven — dan valt dat ook onder dit criterium.

    In de code is het ook op te zoeken:

    document.querySelectorAll('[onchange], select, input[type=checkbox], input[type=radio]')
      .forEach(function (el) {
        if (el.getAttribute('onchange')) console.warn('onchange:', el);
      });

    Zoek in de bronbestanden daarnaast naar form.submit() en addEventListener('change'. Niet elke treffer is fout, maar het zijn wel de plekken om te kijken.

    Open dit onderwerp op een eigen pagina

  • Inloggen: de wachtwoordbeheerder

    Wie een wachtwoordbeheerder gebruikt hoeft niets te onthouden en niets over te typen. Daarmee is de eis vervuld, zolang de site die beheerder niet in de weg zit.

    Zet daarom het juiste autocomplete-woord op elk veld:

    <label for="gebruiker">E-mailadres</label>
    <input id="gebruiker" name="gebruiker" type="email"
           autocomplete="username">
    
    <label for="wachtwoord">Wachtwoord</label>
    <input id="wachtwoord" name="wachtwoord" type="password"
           autocomplete="current-password">
    
    <label for="code">Code uit je sms</label>
    <input id="code" name="code" type="text" inputmode="numeric"
           autocomplete="one-time-code">

    De laatste wordt het vaakst vergeten en helpt het meest: met one-time-code biedt de telefoon de code uit de sms zelf aan boven het toetsenbord.

    Drie dingen die je niet moet doen:

    • Plakken blokkeren. Bedoeld tegen slordigheid, werkt alleen tegen wie het goed doet.
    • De code opknippen in losse vakjes. Geen wachtwoordbeheerder komt daar doorheen.
    • Het wachtwoordveld hernoemen om beheerders te misleiden.

    Is een CAPTCHA echt nodig, kies er dan een die op gedrag let in plaats van op een puzzel. Blijft er een puzzel over, zorg dan voor een echt alternatief: een telefoonnummer waar iemand opneemt of een e-mailadres dat gelezen wordt. “Probeer het opnieuw” is geen alternatief.

    Open dit onderwerp op een eigen pagina

  • Focus zet iets in gang

    Laat geen grote gebeurtenis plaatsvinden als een bezoeker een veld invoerveld invult, een selectievakje of keuzerondje aanklikt of een waarde kiest uit een keuzelijst, tenzij de bezoeker vooraf is geïnformeerd. Voor veel bezoekers kan een onverwachte gebeurtenis verwarrend zijn. Bezoekers met een visuele beperking kunnen de wijziging misschien niet zien. Bezoekers die alleen met het toetsenbord navigeren kunnen hierdoor moeite hebben met de bediening van de website. Laat de bezoeker daarom zelf op een knop klikken om de gebeurtenis in gang te zetten.

    Grote gebeurtenissen worden contextwijzigingen genoemd. Contextwijzigingen zijn bijvoorbeeld:

    • het automatisch inzenden van een formulier;
    • het openen van een venster;
    • het veranderen van de focus naar een ander onderdeel.

    Er mag ook geen contextwijziging plaatsvinden door het veranderen van de focus.

    Succescriteria

    Open dit onderwerp op een eigen pagina

  • Bij input: wat het criterium vraagt

    Het bedienen van een onderdeel mag niet vanzelf de context veranderen: geen nieuwe pagina, geen ander venster en geen verplaatste focus. Tenzij vooraf is aangekondigd dat dat gebeurt. Een keuzelijst die zichzelf verstuurt verandert de pagina terwijl de bezoeker nog aan het kiezen is — wie met de pijltjestoetsen door een lijst met landen gaat, is al weg bij de tweede optie.

    De drie klassiekers:

    • Een keuzelijst die verstuurt. Van land, taal of sortering.
    • Een veld dat de focus doorzet. Vier vakjes voor een pincode, en na elk cijfer springt de focus door. Bij een typefout is er geen weg terug.
    • Een vinkje dat de pagina herlaadt, bijvoorbeeld een filter dat meteen zoekt.

    Wie kijkt, ziet dat de pagina verandert. Wie luistert, hoort een schermlezer opnieuw beginnen zonder te weten waarom. Wie langzaam bedient, raakt in de knel omdat het gebeurt vóór hij klaar is.

    Een filter dat de lijst eronder bijwerkt zonder de pagina te herladen en zonder de focus te verplaatsen is geen contextverandering. Dat is een resultaat. Meld de nieuwe stand wel met role="status".

    Open dit onderwerp op een eigen pagina

  • Inloggen: wat het criterium vraagt

    Bij het inloggen mag geen cognitieve test worden opgelegd: geen puzzel, geen code die onthouden en overgetypt moet worden, en geen vraag naar iets wat de bezoeker uit zijn hoofd moet weten. De inlog is de plek waar iedere gebruiker langs moet; wat daar misgaat maakt de rest van de dienst onbereikbaar.

    Er zijn twee uitwegen. Er mag een alternatief zijn dat de test niet vraagt, of de test mag gaan over het herkennen van objecten of van een plaatje dat de bezoeker zelf heeft aangeleverd. Dit criterium is nieuw in WCAG 2.2 en staat op niveau AA.

    Waar het misgaat:

    • Een CAPTCHA met vervormde letters. Dat is puur een test.
    • Een code uit een sms die overgetypt moet worden in een venster dat de sms bedekt.
    • Zes losse vakjes voor die code, waar geen wachtwoordbeheerder mee overweg kan.
    • Een beveiligingsvraag over een eerste huisdier of de meisjesnaam van een moeder.
    • Plakken blokkeren in het wachtwoordveld.

    Dit is de AA-versie en valt onder de wet. 3.3.9 Toegankelijke authenticatie (uitgebreid) is de AAA-versie en laat die uitwegen niet toe: daar mag ook een plaatjespuzzel niet.

    Open dit onderwerp op een eigen pagina

  • Inloggen: zo test je het

    Deze test duurt vijf minuten en gaat met een eigen account.

    Ga als volgt te werk:

    • Zet het wachtwoord in een wachtwoordbeheerder.
    • Log uit en weer in. Vult de beheerder beide velden?
    • Komt er een tweede stap? Is die code te plakken, of wordt hij aangeboden?
    • Noteer alles wat met het hoofd of de vingers moest gebeuren.

    Waar je op let:

    • Losse vakjes voor de code. Probeer te plakken — lukt het?
    • Een CAPTCHA in welke vorm dan ook.
    • Een beveiligingsvraag.
    • Een tijdslimiet die niet gehaald wordt bij langzaam typen.
    • Een venster dat de sms bedekt, zodat de code niet te lezen is.

    De controle in de code:

    document.querySelectorAll('input').forEach(function (el) {
      console.log(el.type, '·', el.autocomplete || 'GEEN AUTOCOMPLETE', '·', el.name);
    });

    Staat er bij het wachtwoordveld geen current-password en bij het codeveld geen one-time-code, dan is duidelijk waar te beginnen.

    Open dit onderwerp op een eigen pagina

  • Overbodige invoer: zo test je het

    Dit is een test met pen en papier. Er is geen software voor nodig, en juist daarom wordt hij zelden gedaan.

    Ga als volgt te werk:

    • Begin bij het begin van een proces met meerdere stappen: een bestelling, een aanvraag, een aanmelding.
    • Schrijf bij elke stap op wélke gegevens er gevraagd worden. Niet wat je invult, maar wat er gevraagd wordt.
    • Loop het lijstje na. Staat er iets twee keer op?

    Staat er iets twee keer, dan is dat een afwijking — tenzij het een wachtwoord is of iets wat echt veranderd kan zijn.

    Waar het meestal zit:

    • Factuuradres en afleveradres.
    • E-mailadres bij het aanmaken van een account en daarna nog eens bij het bestellen.
    • Een naam bovenaan een formulier en nog eens bij de ondertekening.
    • Een klantnummer dat in stap 1 wordt ingevoerd en in stap 3 opnieuw.

    Doe daarna de test die verder gaat: vul het formulier één keer verkeerd in en verstuur. Staat alles wat wél goed was ingevuld er nog? Zo niet, dan wordt niet twee keer hetzelfde gevraagd maar alles opnieuw — precies op het moment dat de bezoeker toch al iets fout deed.

    Open dit onderwerp op een eigen pagina

  • Statusberichten

    Veranderingen in de inhoud van een pagina worden aangegeven met een statusbericht. Een statusbericht voegt nieuwe informatie toe aan de pagina. Het geeft de bezoeker bijvoorbeeld informatie over de resultaten van een actie, over de voortgang van een laadtijd of een waarschuwing over eventuele fouten in een formulier. Deze informatie is belangrijk voor iedereen. Deze informatie moet dus ook beschikbaar worden gemaakt voor een bezoeker die gebruik maakt van hulptechnologieën.

    Hulptechnologie synchroniseert continu met het DOM en merkt de wijziging dus wel op, maar de bezoeker die hiervan gebruik maakt wordt er nietover geïnformeerd. Met het attribuut aria-live wordt een blok een live region. Deze informatie moeten in de code worden opgemaakt zodat ze de aandacht krijgen van hulptechnologieën op een manier die de bezoeker niet onnodig onderbreekt.

    • Bij succes of informatie over voortgang wordt dit gedaan met ARIA role="status" of aria-live="polite".
    • Bij waarschuwing wordt dit gedaan met ARIA role="alert" of aria-live="assertive".
    <div role="status">
      <p>Je instellingen zijn opgeslagen.</p>
    </div>

    Standaard zal hulptechnologie alleen de gewijzigde tekst voorlezen. Als toch het hele blok moet worden voorlezen, voeg dan aria-atomic=”true” toe.

    Een bezoeker heeft geen controle over de uitgesproken informatie. Als een bezoeker (per ongeluk) een toets aanraakt, wordt de aankondiging onderbroken en is er geen manier om de informatie opnieuw te beluisteren.

    Open dit onderwerp op een eigen pagina

  • Focusvolgorde: de volgorde in je HTML

    Eén regel lost het meeste op: schrijf de HTML in de volgorde waarin de pagina gelezen moet worden, en gebruik CSS alleen om te bepalen wáár iets staat.

    Deze drie eigenschappen verplaatsen het beeld zonder de volgorde te veranderen. Het oog volgt de nieuwe plek, het toetsenbord de oude:

    .blok    { order: -1; }
    .raster  { grid-row: 1; grid-column: 2; }
    .zijbalk { position: absolute; right: 0; }

    Wil je de tekst links en het beeld rechts, zet de tekst dan eerst in de HTML. Op een smal scherm komt alles onder elkaar in die volgorde te staan, en dan klopt het daar ook.

    <div class="tweeluik">
      <div class="tekst">…</div>       <!-- eerst lezen, eerst in de code -->
      <figure class="beeld">…</figure>
    </div>
    
    .tweeluik { display: grid; grid-template-columns: 1fr 1fr; }

    Gebruik geen positieve tabindex. Een getal boven nul zet het onderdeel vooraan in de rij, vóór alles wat geen tabindex heeft. Eén zo’n onderdeel zet de hele volgorde op zijn kop. tabindex="0" en tabindex="-1" zijn wel in orde.

    Let daarnaast op twee plekken waar de volgorde met script wordt bepaald. Een venster dat opengaat hoort de focus mee te nemen en bij het sluiten terug te geven aan de knop waarop is gedrukt. Een menu dat uitklapt hoort zijn onderdelen meteen na de knop te hebben staan, niet onderaan de pagina.

    Open dit onderwerp op een eigen pagina

  • Focusvolgorde: zo test je het

    De focusvolgorde is te toetsen met het toetsenbord en het oog. Er is geen software voor nodig.

    Ga als volgt te werk:

    • Klik bovenaan de pagina, buiten een link of invoerveld.
    • Druk op Tab en volg met je ogen waar de focus heen springt.
    • Teken die route in gedachten na: loopt hij van links naar rechts en van boven naar beneden?

    Springt de focus vooruit en dan weer terug omhoog, dan is de afwijking gevonden. Begin bij formulieren: daar heeft een verkeerde volgorde de meeste gevolgen.

    Drie plekken waar het vaak misgaat:

    • Een venster dat opengaat en de focus achterlaat op de pagina erachter.
    • Een uitklapmenu waarvan de onderdelen onderaan de pagina in de code staan.
    • Een tweeluik met beeld en tekst waarvan de code omgekeerd is.

    Zoek in de bronbestanden daarnaast naar een positieve tabindex. Elke treffer is vrijwel zeker een fout:

    tabindex="1"
    tabindex="2"

    Zoek ook naar order: en flex-direction: row-reverse in het stijlbestand. Dat hoeft geen fout te zijn, maar het is wel de plek waar je moet kijken.

    Open dit onderwerp op een eigen pagina

  • Tooltips: zo test je het

    Zoek eerst alles op wat verschijnt bij aanwijzen of bij focus. Dat zijn meestal vraagtekens, pictogrammen, menu’s en linkvoorbeelden.

    Ga daarna als volgt te werk:

    • Wijs het onderdeel aan tot de uitleg verschijnt.
    • Beweeg de aanwijzer langzaam naar de uitleg toe. Blijft hij staan?
    • Ga met de aanwijzer over de uitleg heen. Blijft hij nog steeds staan?
    • Druk op Escape zonder de aanwijzer te verplaatsen. Verdwijnt hij?
    • Wijs opnieuw aan en wacht tien seconden. Verdwijnt hij vanzelf?

    Doe de test daarna met het toetsenbord. Tab naar hetzelfde onderdeel: verschijnt de uitleg ook dan? Zo niet, dan mist een deel van de bezoekers hem helemaal.

    Vind je een tooltip met informatie die nergens anders staat, dan is dat meer dan een afwijking op dit criterium. Dan mist een deel van de bezoekers inhoud.

    Open dit onderwerp op een eigen pagina

  • Slepen: zo test je het

    Zoek eerst alles op wat normaal versleept wordt: schuifregelaars, herschikbare lijsten, kaarten en carrousels.

    Ga daarna als volgt te werk:

    • Bedien het onderdeel zonder ingedrukt te houden.
    • Gebruik alleen losse klikken of tikken.
    • Lukt het niet, dan is dat de afwijking.

    Doe de test daarna nog eens met alleen het toetsenbord. Dat is 2.1.1 Toetsenbord, maar het gaat vaak om dezelfde onderdelen.

    Test ook op een aanraakscherm. Onderdelen die met een muis goed werken zijn met een vinger soms alleen te vegen, en dan is er geen alternatief.

    Uitzonderingen waar je geen afwijking op hoeft te melden:

    • Een handtekening zetten. Het pad dat wordt getrokken is het resultaat.
    • Tekenen of schilderen.
    • Een handeling waarbij de precieze plek telt en die niet in stappen te doen is.

    Open dit onderwerp op een eigen pagina

  • Overbodige invoer: wat het criterium vraagt

    Gegevens die binnen hetzelfde proces al zijn ingevuld, mogen niet een tweede keer worden gevraagd. Gebeurt dat toch, dan moeten ze automatisch worden ingevuld of te kiezen zijn uit wat er al staat. Overbodig typen is niet gelijk verdeeld: wie met één vinger, met zijn stem of met een schakelaar werkt is er minuten mee kwijt, en maakt bij elke aanslag kans op een fout.

    Dit criterium is nieuw in WCAG 2.2 en staat op niveau A.

    Er zijn twee uitzonderingen: als het opnieuw invullen nodig is voor de veiligheid, zoals bij een wachtwoord, en als de oude informatie niet meer geldig is.

    Voor bezoekers met een geheugenprobleem is dit scherper dan het lijkt. Wordt een klantnummer uit stap twee in stap vier opnieuw gevraagd, dan is teruggaan soms de enige uitweg — en daarmee het risico dat alles weg is.

    Open dit onderwerp op een eigen pagina

  • Overbodige invoer: invullen of laten kiezen

    De eis laat vrij hóe het wordt opgelost. Er zijn drie manieren, en welke past hangt af van hoe zeker het antwoord hetzelfde is.

    Weet je het antwoord zeker, vul het dan in. De bezoeker kan het nog aanpassen:

    <label for="post-straat">Straat en huisnummer</label>
    <input id="post-straat" name="post_straat"
           value="Marsweg 89A"
           autocomplete="shipping street-address">

    Een vinkje “hetzelfde als hierboven” is de bekendste oplossing en meestal de beste. Zet hem aan als dat het gewone geval is, dan hoeft de meerderheid niets te doen:

    <input type="checkbox" id="zelfde" name="zelfde" checked>
    <label for="zelfde">Mijn afleveradres is hetzelfde als mijn factuuradres</label>

    Zijn er meerdere eerdere antwoorden, geef dan een keuzelijst in plaats van een leeg veld.

    Zet daarnaast op elk veld het juiste autocomplete-woord. Dan vult de browser of de wachtwoordbeheerder het zelf in, zonder eigen code. Daarmee voldoe je meteen aan 1.3.5 Identificeer het doel van de input:

    autocomplete="name"
    autocomplete="email"
    autocomplete="postal-code"
    autocomplete="shipping street-address"
    autocomplete="billing street-address"

    Verbergt het vinkje de velden eronder, zorg dan dat ze weer verschijnen als de bezoeker het uitzet, en dat de focus meegaat.

    Open dit onderwerp op een eigen pagina

  • Bij input: een knop ernaast

    Er is één oplossing die altijd werkt en die in twee minuten is gebouwd: zet er een knop naast.

    <!-- niet doen -->
    <select onchange="this.form.submit()">
    
    <!-- wel doen -->
    <select id="sortering" name="sortering">…</select>
    <button type="submit">Toon resultaten</button>

    Dat kost één klik en voorkomt dat een bezoeker per ongeluk ergens anders belandt. Het werkt bovendien zonder JavaScript.

    Wil je toch automatisch versturen, dan mag dat als je het vooraf aankondigt. Zet die aankondiging in het label en niet erachter, anders wordt hij pas gelezen als het al is gebeurd:

    <label for="taal">Taal <span class="hint">(de pagina laadt opnieuw)</span></label>
    <select id="taal" name="taal" onchange="this.form.submit()">

    Bij een pincode in losse vakjes mag de focus doorspringen, zolang er een weg terug is. Werkt Backspace niet meer omdat de focus al weg is, dan zit de bezoeker vast. Eén veld voor de hele code is bijna altijd beter — en dan werkt een wachtwoordbeheerder ook.

    Open dit onderwerp op een eigen pagina

  • Slepen: knoppen ernaast

    De oplossing is bijna altijd hetzelfde: het slepen blijft, er komt een manier met losse klikken naast.

    Bij een schuifregelaar gebruik je input type="range", die met de pijltoetsen te bedienen is. Voor de aanwijzer zet je er twee knoppen naast, met het getal erbij zodat zichtbaar is wat er verandert:

    <button type="button" aria-label="Minder">−</button>
    <input type="range" id="prijs" min="0" max="500" step="10" value="100">
    <button type="button" aria-label="Meer">+</button>
    <output for="prijs">100 euro</output>

    Bij een lijst die herschikt kan worden zet je bij elk onderdeel een knop omhoog en een knop omlaag. Dat werkt met de muis, met een aanraakscherm, met een toetsenbord en met een schermlezer:

    <li>
      Nieuwsbrief
      <button type="button" aria-label="Nieuwsbrief omhoog">↑</button>
      <button type="button" aria-label="Nieuwsbrief omlaag">↓</button>
    </li>

    Bij een carrousel horen er knoppen voor vorige en volgende te zijn naast het vegen. Bij een kaart knoppen om te verschuiven en te zoomen; de meeste kaartbibliotheken hebben die al, maar soms staan ze uit.

    Let op de maat van die knoppen. Zijn ze te klein, dan ruil je het ene probleem in voor het andere. Zie het artikel over de grootte van het aanwijsgebied.

    Open dit onderwerp op een eigen pagina

  • Focusvolgorde: wat het criterium vraagt

    Wie met het toetsenbord werkt krijgt de pagina als een rij: eerst dit, dan dat. Het overzicht dat een ziende bezoeker in één blik heeft, ontbreekt daarbij. Klopt de volgorde van de focus niet met de volgorde waarin de pagina te lezen is, dan raakt de bezoeker de draad kwijt. Zorg daarom dat de focus in een logische volgorde door de pagina loopt.

    De oorzaak is bijna altijd dezelfde. Het ontwerp vraagt het beeld rechts en de tekst links; in de code staat het beeld eerst en wordt het met CSS naar rechts geschoven. Op het scherm klopt dat, maar de focus volgt de code. De bezoeker springt dan eerst naar rechts, dan naar links en dan weer naar rechts.

    Bij een formulier heeft dat gevolgen. Gaat de focus van Postcode naar Versturen en pas daarna naar Huisnummer, dan wordt het formulier half ingevuld verstuurd.

    Dit criterium gaat over de focusvolgorde: waar Tab naartoe springt. 1.3.2 Betekenisvolle volgorde gaat over de leesvolgorde: waar de tekst over gaat. Vaak is het dezelfde fout, maar niet altijd — een pagina kan goed leesbaar zijn en toch onhandig te bedienen.

    Open dit onderwerp op een eigen pagina

  • Tijdslimiet

    Soms moeten formulieren binnen een bepaalde tijd worden ingevuld of verloopt een inlogsessie na een bepaalde termijn. Zo’n tijdslimiet is niet handig voor bezoekers die meer tijd nodig hebben. Bijvoorbeeld omdat zij gebruik maken van hulptechnologieën of omdat zij door een cognitieve beperking meer tijd nodig hebben om tekst te lezen. Zorg daarom dat er geen tijdslimiet wordt gebruikt. Als het echt niet anders kan, geef bezoekers dan de mogelijkheid om de tijdslimiet aan te passen. Dit kan op één van de volgende manieren:

    • Uitzetten: Laat bezoekers de tijdslimiet uitzetten voordat het begint.
    • Aanpassen: Laat bezoekers de tijdslimiet aanpassen tot ten minste 10 keer de tijdslimiet voordat het begint.
    • Verlengen: Geef bezoekers een waarschuwing voordat de tijd afloopt en geef ze tenminste 20 seconden om de tijdslimiet te verlengen. Laat de bezoeker dit ten minste 10 keer doen.

    Niet bij alle tijdslimieten is het nodig dat deze kan worden uitgezet, aangepast of worden verlengt. Er zijn namelijk een paar uitzonderingen:

    • Real-time: Als de tijdslimiet onderdeel is van een real-time gebeurtenis, zoals het bieden in veiling, en er geen alternatief voor de tijdslimiet mogelijk is.
    • Essentieel: Als de tijdslimiet zelf essentieel is, zoals bij een toets die in een bepaalde tijd moet worden gemaakt, en verlenging de activiteit ongeldig zou maken.
    • Langer dan 20 uur: Als de tijdslimiet langer is dan 20 uur.

    Open dit onderwerp op een eigen pagina

  • Tooltips: wat het criterium vraagt

    Verschijnt er extra inhoud zodra een bezoeker iets aanwijst of met het toetsenbord selecteert — een tooltip, een uitklapmenu, een voorbeeldvenster — dan moet die inhoud te lezen zijn. Wie ingezoomd werkt ziet de uitleg buiten zijn deel van het scherm staan en moet er met de aanwijzer naartoe. Verdwijnt de uitleg onderweg, dan is hij onbereikbaar.

    Er gelden drie eisen:

    • Wegklikbaar. De uitleg is te sluiten met Escape, zonder de aanwijzer te verplaatsen.
    • Aanwijsbaar. De aanwijzer kan erheen zonder dat de uitleg verdwijnt.
    • Blijvend. De uitleg blijft staan tot de bezoeker wegwijst, hem sluit of de informatie niet meer klopt. Niet tot een tijdklok afloopt.

    Waar dit opduikt: tooltips bij een pictogram of vraagteken, uitklapmenu’s die opengaan bij aanwijzen, voorbeeldvensters bij een link, foutmeldingen die bij focus verschijnen, en een winkelmandje dat opengaat bij aanwijzen.

    Op een aanraakscherm bestaat aanwijzen niet. Wat alleen bij aanwijzen verschijnt, moet daar op een andere manier bereikbaar zijn — of de informatie hoort gewoon op de pagina te staan.

    Open dit onderwerp op een eigen pagina

  • Labels en instructies

    Zorg voor labels bij invoervelden

    Labels zijn het belangrijkste element voor een toegankelijk formulier. Zorg voor labels bij alle invoervelden of ander formulierelementen zoals selectievakjes, keuzerondjes en keuzelijsten. Een duidelijk label beschrijft precies wat er in het veld ingevuld moet worden, is zichtbaar voor alle bezoekers en staat dichtbij het invoerveld.

    Het label moet in de code worden gekoppeld aan het invoerveld. Zo maak je het invoerveld ook toegankelijk voor bezoekers die gebruik maken van hulptechnologieën. Het label is de naam van het invoerveld. Een label vergroot ook het klikbare gebied waarmee een invoerveld kan worden geselecteerd. Dit is handig voor bijvoorbeeld bezoekers met een motorische beperking.

    Koppel labels in de code aan een invoerveld

    Labels worden geplaatst met het <​label​>-element. Het koppelen van een <​label​>-element aan een formulierelement gebeurt met een for/id-koppeling. Geef hiervoor het <​label​>-element een for-attribuut en het bijbehorende formulierelement een id-attribuut met dezelfde waarde.

    In de code ziet dat er zo uit:

    <label for="veld1">Naam:</label>
    <input type="text" id="veld1">
    
    <label for="veld2">Kies je kleur:</label>
    <select id="veld2">
      <option value="0">Rood</option>
      <option value="1">Groen</option>
      <option value="2">Blauw</option>
    </select>
    
    <input type="checkbox" id="veld3">
    <label for="veld3">Meld mij aan voor de nieuwsbrief</label>

    Er zijn ook manieren om de labels visueel te verbergen. Vraag je dan wel goed af waarom je dat zou willen doen. Het invoerveld verliest dan het grotere klikbare gebied en het wordt misschien minder duidelijk voor bezoekers. Als het label toch visueel wordt verborgen, zorg er dan er wel voor dat er een label beschikbaar is voor hulptechnologieën. Gebruik hiervoor het attribuut aria-label, aria-labelledby of een title-attribuut. Deze zijn niet zichtbaar.

    In de code ziet dat er zo uit:

    <input type="text" aria-label="Naam">

    Let op: Placeholdertekst mag niet als enige manier worden gebruikt om een label toe te voegen aan een invoerveld.

    Groepeer meerdere secties van gerelateerde invoervelden

    Als een formulier meerdere secties van gerelateerde invoervelden heeft dan wordt een <​fieldset​>-element gebruikt om deze te groeperen. Geef het <​fieldset​>-element een label door een <​legend​>-element in het <​fieldset​>-element te plaatsen. Hulptechnologieën gebruiken het <​legend​>-element alsof het een onderdeel is van het label van de elementen in het <​fieldset​>-element.

    Het <​fieldset​>-element is vooral relevant voor het groeperen selectierondjes en keuzevakjes maar kan ook worden gebruikt om andere invoervelden te groeperen.

    In de code ziet dat er zo uit:

    <fieldset>
      <legend>Ben jij al orgaandonor?</legend>
    
      <input type="radio" id="veld1">
      <label for="veld1" value="ja">Ja, ik ben orgaandonor</label>
    
      <input type="radio" id="veld2">
      <label for="veld2" value="nee">Nee, ik ben geen orgaandonor</label>
    </fieldset>

    Zorg voor instructies bij invoervelden

    Instructies geven een extra hint voor de invoer in het invoerveld. De instructies in een formulier moeten aangeven of er verplichte velden zijn en eventueel of er een verplicht invoerformaat is.

    Geef aan dat een invoerveld verplicht is

    Het aangeven van een verplicht invoerveld kan in tekst of bijvoorbeeld met een asteriks (*). Zorg dat deze aanduiding in het <​label​>-element is geplaatst.

    In de code ziet dat er zo uit:

    <label for="veld1">Naam: (verplicht)</label>
    <input type="text" id="veld1">

    Als de instructies niet duidelijk per invoerveld worden benoemd dan hoort voorafgaand aan het eerste invoerveld in tekst worden aangegeven op welke manier de verplichte velden zijn aangeduid.

    In de code ziet dat er zo uit:

    <p>Alle velden met een * zijn verplicht.</p>
    
    <label for="veld1">Naam: *</label>
    <input type="text" id="veld1">
    
    <label for="veld2">Favoriete dier: *</label>
    <input type="text" id="veld2">

    Markeer verplichte velden ook in de code. Gebruik hiervoor bij voorkeur het aria-required-attribuut.

    <p>Alle velden met een * zijn verplicht.</p>
    
    <label for="veld1">Naam: *</label>
    <input type="text" id="veld1" aria-required="true">
    
    <fieldset>
      <legend>Ben jij al orgaandonor? *</legend>
    
      <input type="radio" id="veld2" value="ja" aria-required="true">
      <label for="veld2">Ja, ik ben orgaandonor</label>
    
      <input type="radio" id="veld3" value="nee" aria-required="true">
      <label for="veld3">Nee, ik ben geen orgaandonor</label>
    </fieldset>

    Geef het aan als er een verplicht invoerformaat is verplicht is

    Ook bij verplichte invoerformaten, zoals een postcode of een e-mailadres die moet worden ingevuld, moeten blijken uit de instructies wat de eisen zijn aan de invoer. Dit kan direct in het <​label​>-element.

    In de code ziet dat er zo uit:

    <label for="veld1">Geboortedatum (dd-mm-jjjj):</label>
    <input type="text" id="veld1">

    Maar dit kan ook via het attribuut aria-describedby.

    In de code ziet dat er zo uit:

    <label for="veld1">Geboortedatum:</label>
    <input type="text" id="veld1" aria-describedby="beschrijving">
    <span id="beschrijving">dd-mm-jjjj</span>

    Open dit onderwerp op een eigen pagina

  • Extra controle bij insturen

    Als er door het insturen van een formulier een onomkeerbare actie wordt uitgevoerd die grote gevolgen kan hebben, dan moet er voor worden gezorgd dat bezoekers de inzending kunnen annuleren, controleren of bevestigen.

    Bezoekers met een functiebeperking lopen vaak meer risico om fouten te maken. Mensen met dyslexie kunnen letters en cijfers omdraaien en mensen met motorische stoornissen kunnen per ongeluk toetsen aanslaan. Eigenlijk hebben alle bezoekers profijt van de mogelijkheid om ernstige fouten te voorkomen.

    Bij een formulier waarmee een wettelijke of financiële transactie wordt gedaan, kun je één van de volgende technieken toepassen:

    • Geef de bezoeker na verzending van het formulier een bepaalde tijd om de inzending te wijzigen of annuleren.
    • Toon voordat het formulier wordt verzonden een overzicht van de ingevulde gegevens en bied de bezoeker de mogelijkheid om deze te verbeteren.
    • Voeg een selectievakje toe aan het formulier waarmee de bezoeker aan kan geven dat hij de gegevens heeft gecontroleerd en dat deze correct zijn, voordat hij het formulier verzendt.

    Bij een formulier waarmee de bezoeker gegevens kan wijzigen of verwijderen, zoals profielgegevens op een website, kun je één van de volgende technieken toepassen:

    • Bied de mogelijkheid om verwijderde gegevens terug te halen.
    • Vraag bevestiging om door te gaan met de actie van het wijzigen of verwijderen.
    • Voeg een selectievakje toe aan het formulier waarmee de bezoeker aan kan geven dat hij de gegevens heeft gecontroleerd en dat deze correct zijn, voordat hij het formulier verzendt.

    Bij een formulier waarmee de bezoeker antwoorden kan geven op vragen uit een test, toets of examen, kun je één van de volgende technieken toepassen:

    • Bied de mogelijkheid om antwoorden te controleren en verbeteren voordat ze worden verzonden.
    • Vraag bevestiging om door te gaan met het inzenden van het antwoord.

    Open dit onderwerp op een eigen pagina

Terug naar boven