WCAG framgångskriterier · Level A

WCAG 2.1.2: Ingen tangentbordsfälla

WCAG 2.1.2 kräver att tangentbordsanvändare aldrig blir fast i en komponent — om fokus kan flyttas in i ett UI-element med hjälp av ett tangentbord, måste det också vara möjligt att flytta fokus därifrån med enbart tangentbordet. Detta kriterium är avgörande för användare som förlitar sig uteslutande på tangentbordsnavigering, inklusive personer med motoriska funktionsnedsättningar och skärmläsaranvändare.

Vad den här regeln innebär

WCAG 2.1.2 — No Keyboard Trap (Ingen tangentbordsfälla) — är ett framgångskriterium på nivå A under principen Operable (Hanterbar). Det säger: "If keyboard focus can be moved to a component of the page using a keyboard interface, then focus can be moved away from that component using only a keyboard interface, and, if it requires more than unmodified arrow keys or tab keys to move focus away, the user is informed of the method for moving focus."

I praktiska termer innebär detta att varje interaktiv komponent på en webbsida som en tangentbordsanvändare kan tabba in i också måste låta användaren tabba ut ur den. En tangentbordsfälla uppstår när en användare navigerar in i en widget, dialogruta, anpassad formulärkontroll, inbäddad mediaspelare eller någon annan fokuserbar region och sedan inte kan lämna den med standardkontroller på tangentbordet — de är i praktiken fast.

Kriteriet omfattar alla HTML-element som kan ta emot tangentbordsfokus: inbyggda interaktiva element såsom <input>, <select>, <textarea>, <button> och <a>-taggar, samt anpassade widgets som får fokus via tabindex, ARIA-roller eller JavaScript-fokushantering. Det gäller i lika hög grad inbäddade tredjepartskomponenter såsom chatt-widgets, videospelare, kartinbäddningar, datumväljare och rich text-redigerare.

En komponent klarar detta kriterium om en tangentbordsanvändare alltid kan flytta fokus bort från den med standardtangenter — vanligtvis Tab, Shift+Tab, Escape eller piltangenter — eller om sidan tydligt informerar användare om en icke-standardiserad tangentbordsmekanism för att flytta fokus bort. En komponent misslyckas om fokus blir låst inuti den utan någon tangentbordsåtkomlig väg ut, eller om den enda utvägen kräver ett musklick, en touchgest eller annan inmatning som inte är tangentbord.

WCAG ger ett snävt undantag: det är acceptabelt att tillfälligt begränsa tangentbordsfokus inom en komponent när detta är en del av ett avsiktligt och tillgängligt designmönster — framför allt en modal dialogruta. En modal dialogruta ska fånga fokus inom dialogen medan den är öppen (för att förhindra att användare interagerar med dold bakgrundsinformation), men den måste alltid erbjuda ett tangentbordsåtkomligt sätt att stänga dialogen och släppa fokus — såsom en Escape-tangenthanterare eller en tydligt märkt stängknapp som kan nås med Tab. Denna typ av avsiktlig, möjlig att lämna, fokusbegränsning är inte en tangentbordsfälla; det är en korrekt implementering av mönstret för modala dialogrutor. Fällan blir bara ett fel när användaren inte kan ta sig därifrån över huvud taget.

Varför det är viktigt

Tangentbordsfällor är ett av de allvarligaste tillgänglighetsfelen en webbplats kan ha. Till skillnad från många andra tillgänglighetsproblem som försämrar upplevelsen för vissa användare kan en tangentbordsfälla helt blockera en användare från att fortsätta använda en sida. Det är i praktiken likvärdigt med att placera ett fysiskt hinder i en korridor utan att ge någon väg runt det.

De grupper som drabbas hårdast är användare med motoriska eller fysiska funktionsnedsättningar som inte kan använda en mus och är helt beroende av tangentbordsnavigering. Detta inkluderar personer med tillstånd som belastningsskador, multipel skleros, Parkinsons sjukdom, tetraplegi och cerebral pares. Enligt Världshälsoorganisationen lever cirka 1,3 miljarder människor — 16% av världens befolkning — med någon form av betydande funktionsnedsättning, och motoriska funktionsnedsättningar utgör en betydande del av den siffran. För dessa användare kan en tangentbordsfälla på en kassasida, ett inloggningsformulär eller en kundtjänstchatt-widget innebära att de helt saknar möjlighet att slutföra uppgiften.

Skärmläsaranvändare — främst blinda och synsvaga användare — drabbas också hårt. Skärmläsare som NVDA, JAWS och VoiceOver navigerar helt via tangentbordskommandon. Om fokus blir fångat i en komponent hör skärmläsaranvändaren samma element upprepas när de trycker på Tab, utan möjlighet att gå framåt eller bakåt på sidan. Detta är djupt desorienterande och tvingar användaren att stänga webbläsarfliken eller uppdatera sidan, vilket gör att allt arbete de gjort går förlorat.

Föreställ dig följande scenario i verkligheten: en användare med begränsad handrörlighet besöker en turkisk e-handelssajt för att köpa en produkt. De lägger en vara i varukorgen och går vidare till kassan. Kassasidan innehåller en tredjepartsadress-autocomplete-widget byggd med ett anpassat JavaScript-ramverk. Widgeten öppnar en rullgardinslista med förslag när adressfältet får fokus. Utvecklaren glömde att lägga till tangentbordshantering för att stänga denna rullgardinslista — så när användaren tabbar in i adressfältet och rullgardinslistan visas kan de inte tabba ut, kan inte trycka Escape och kan inte stänga rullgardinslistan utan ett musklick. Användaren är helt blockerad från att slutföra köpet. Detta är inte en mindre olägenhet — det är ett totalt utestängande från tjänsten.

Utöver tillgång för personer med funktionsnedsättning påverkar tangentbordsfällor också avancerade användare som föredrar tangentbordsnavigering för snabbhet, användare i företagsmiljöer där musanvändning är begränsad, och användare på vissa mobila eller hybridenheter med fysiska tangentbord. Att åtgärda tangentbordsfällor förbättrar därför upplevelsen för en bredare publik än bara användare med funktionsnedsättningar.

Relaterade Axe-core-regler

WCAG 2.1.2 kräver manuell testning. Ingen automatiserad axe-core-regel upptäcker tangentbordsfällor direkt och tillförlitligt. Detta beror på att automatiserade verktyg arbetar genom att analysera den statiska strukturen i DOM:en — de kan identifiera fokuserbara element, kontrollera tabb-ordning och validera ARIA-attribut, men de kan inte simulera den fullständiga interaktiva tangentbordsnavigeringsupplevelse som en mänsklig testare utför. En tangentbordsfälla uppstår vanligtvis ur JavaScript-händelsehanteringslogik som fångar upp eller undertrycker tangentbordshändelser vid körning; detta beteende är inte synligt i DOM-strukturen och kan inte härledas av en statisk analysator.

  • Manuell testning krävs — ingen dedikerad axe-core-regel: Axe-core levereras inte med någon regel som automatiskt upptäcker tangentbordsfällor eftersom feltypen i grunden är beteendemässig. Fällan visar sig bara när en användare faktiskt navigerar in i en komponent med Tab-tangenten och försöker lämna den. En automatiserad skanner kan inte replikera detta eftersom den skulle behöva simulera sekventiell tangentbordsnavigering över varje fokuserbart element på sidan, trigga alla associerade JavaScript-händelselyssnare och sedan avgöra om fokus har lämnat den avsedda regionen — ett problem som är beräkningsmässigt olösligt för komplexa sidor. Dessutom kräver bedömningen av vad som utgör en fälla kontra avsiktlig fokusbegränsning (som en modal) kontextuell bedömning som automatiserade regler inte pålitligt kan göra. Testare bör använda axe DevTools eller Lighthouse för att identifiera fokuserbara element och tabb-ordningsproblem som utgångspunkt, men måste sedan manuellt tangentbordsnavigera genom varje interaktiv region för att bekräfta att inga fällor finns.

Hur man testar

  1. Kör en automatiserad tillgänglighetsskanning som baslinje. Öppna axe DevTools (webbläsartillägg) eller kör en Lighthouse-tillgänglighetsgranskning i Chrome DevTools. Även om inget av verktygen direkt flaggar en tangentbordsfälla kommer skanningen att identifiera fokuserbara element, saknade ARIA-roller och felaktig tabb-ordning som kan indikera riskfyllda interaktiva komponenter värda att undersöka manuellt. Notera alla anpassade widgets, inbäddade iframes, tredjepartskomponenter, modala dialogrutor, rullgardinsmenyer, datumväljare, karuseller och rich text-redigerare — detta är de vanligaste källorna till tangentbordsfällor.
  2. Koppla bort eller lägg undan din mus. För att manuell tangentbordstestning ska vara giltig får du inte använda en mus. Lägg musen utom räckhåll eller inaktivera den i operativsystemets inställningar för att undvika att du av misstag förlitar dig på den under testningen.
  3. Navigera hela sidan med enbart Tab- och Shift+Tab-tangenterna. Börja från webbläsarens adressfält eller toppen av sidan, tryck upprepade gånger på Tab och observera vart fokus flyttas. Följ visuellt fokusindikatorn vid varje steg. När du når varje interaktiv komponent — särskilt alla anpassade widgets, inbäddat innehåll eller komplexa UI-element — kontrollera att tryck på Tab eller Shift+Tab flyttar fokus rent ut ur komponenten till nästa eller föregående fokuserbara element på sidan.
  4. Testa varje interaktiv komponent individuellt. För modala dialogrutor: öppna dialogen, kontrollera att fokus flyttas in i den, tryck sedan på Escape och bekräfta att fokus återgår till det element som öppnade dialogen. För rullgardinsmenyer: öppna rullgardinsmenyn, navigera i den, tryck sedan på Escape och bekräfta att rullgardinsmenyn stängs och att fokus återgår till triggerelementet. För datumväljare, färgväljare och liknande widgets: tabba in, interagera, tabba sedan ut och bekräfta att fokus lämnar komponenten. För inbäddade iframes (t.ex. kartor, videospelare, chatt-widgets): tabba in i iframen, navigera i den och bekräfta att du kan tabba ut ur den tillbaka till huvudsidan.
  5. Testa med NVDA och Firefox. Öppna NVDA, navigera till sidan i Firefox och använd Tab för att gå igenom interaktiva element. Var uppmärksam på om NVDA läser upp ett nytt element varje gång du trycker på Tab eller om det verkar hoppa tillbaka till samma element. Om Tab inte flyttar fokus förbi en komponent är detta en tangentbordsfälla.
  6. Testa med VoiceOver och Safari på macOS. Aktivera VoiceOver (Command + F5), öppna sidan i Safari och använd Tab-tangenten för att navigera. Bekräfta att VoiceOver annonserar ett nytt element vid varje Tab-tryckning och att fokus aldrig fastnar i en region som du inte kan lämna.
  7. Testa med JAWS och Chrome. Öppna JAWS, navigera på sidan i Chrome och använd Tab för att navigera genom alla interaktiva komponenter. Testa särskilt alla komponenter som använder JavaScript-styrd fokushantering, eftersom JAWS interagerar med tillgänglighetsträdet på sätt som kan avslöja fällor som inte är synliga vid visuell testning.
  8. Kontrollera icke-standardiserade sätt att lämna komponenter. Om någon komponent kräver en annan tangent än Tab, Shift+Tab eller Escape för att lämna den, kontrollera att sidan tydligt kommunicerar detta till användaren — till exempel via instruktioner på skärmen, en tooltip eller ett ARIA live region-meddelande när fokus går in i komponenten.

Hur man åtgärdar

Modal dialogruta utan Escape-hantering — felaktig

<!-- Modal opens but has no Escape key handler and no close button reachable by keyboard -->
<div id='modal' role='dialog' aria-modal='true' aria-labelledby='modal-title'>
  <h2 id='modal-title'>Confirm Your Order</h2>
  <p>Are you sure you want to place this order?</p>
  <button onclick='submitOrder()'>Confirm</button>
  <!-- No close button, no Escape key listener -- keyboard users are trapped -->
</div>

Modal dialogruta utan Escape-hantering — korrekt

<!-- Modal with proper focus trap, Escape handler, and accessible close button -->
<div id='modal' role='dialog' aria-modal='true' aria-labelledby='modal-title'>
  <h2 id='modal-title'>Confirm Your Order</h2>
  <p>Are you sure you want to place this order?</p>
  <button onclick='submitOrder()'>Confirm</button>
  <!-- Close button is reachable by Tab and allows keyboard users to exit -->
  <button id='modal-close' onclick='closeModal()' aria-label='Close dialog'>Cancel</button>
</div>

<script>
  document.addEventListener('keydown', function(e) {
    if (e.key === 'Escape') {
      closeModal(); // Escape key closes the modal and returns focus to trigger
    }
  });

  function closeModal() {
    document.getElementById('modal').hidden = true;
    document.getElementById('modal-trigger').focus(); // Return focus to opener
  }
</script>

Anpassad rullgardinsmeny som fångar alla Tab-tangenthändelser — felaktig

<!-- Custom dropdown intercepts all keydown events including Tab, preventing focus from leaving -->
<div id='custom-select' tabindex='0' role='combobox' aria-expanded='true'>
  <ul role='listbox'>
    <li role='option' tabindex='-1'>Option 1</li>
    <li role='option' tabindex='-1'>Option 2</li>
    <li role='option' tabindex='-1'>Option 3</li>
  </ul>
</div>

<script>
  // BUG: This captures ALL keyboard events and calls preventDefault on Tab,
  // meaning the user can never Tab out of this component
  document.getElementById('custom-select').addEventListener('keydown', function(e) {
    e.preventDefault(); // This traps the keyboard
    if (e.key === 'ArrowDown') { /* move focus down */ }
    if (e.key === 'ArrowUp') { /* move focus up */ }
  });
</script>

Anpassad rullgardinsmeny som fångar alla Tab-tangenthändelser — korrekt

<!-- Correct: Only prevent default for arrow keys used for internal navigation;
     allow Tab and Escape to function normally so users can exit -->
<div id='custom-select' tabindex='0' role='combobox' aria-expanded='false'>
  <ul role='listbox' hidden>
    <li role='option' tabindex='-1'>Option 1</li>
    <li role='option' tabindex='-1'>Option 2</li>
    <li role='option' tabindex='-1'>Option 3</li>
  </ul>
</div>

<script>
  document.getElementById('custom-select').addEventListener('keydown', function(e) {
    if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
      e.preventDefault(); // Only prevent default for internal navigation keys
      // move focus between options
    }
    if (e.key === 'Escape' || e.key === 'Tab') {
      // Do NOT call preventDefault -- allow Tab and Escape to propagate
      // so the browser can move focus away from this component naturally
      closeDropdown();
    }
  });
</script>

Inbäddad tredjeparts-iframe utan väg ut — felaktig

<!-- An embedded chat widget iframe that absorbs all Tab keypresses
     and never returns focus to the parent page -->
<iframe
  src='https://example-chat-widget.com/embed'
  title='Customer support chat'
  width='350'
  height='500'>
</iframe>
<!-- The iframe's internal JavaScript consumes Tab events, trapping users inside it -->

Inbäddad tredjeparts-iframe utan väg ut — korrekt

<!-- Use a button to open the chat in a new window rather than embedding
     an iframe that may trap keyboard users -->
<button
  id='open-chat'
  onclick='window.open("https://example-chat-widget.com", "_blank", "noopener")'>
  Open Customer Support Chat (opens in new window)
</button>

<!-- If an iframe must be used, add a visible skip link before it
     so keyboard users can bypass it if they choose -->
<a href='#after-chat-widget' class='skip-link'>Skip chat widget</a>
<iframe
  src='https://example-chat-widget.com/embed'
  title='Customer support chat'
  width='350'
  height='500'>
</iframe>
<span id='after-chat-widget' tabindex='-1'></span>

Vanliga misstag

  • Att anropa event.preventDefault() i en keydown-lyssnare utan att begränsa det till specifika tangenter — att tillämpa preventDefault() på alla tangentbordshändelser på en fokuserbar komponent blockerar Tab och Shift+Tab från att fungera och skapar omedelbart en tangentbordsfälla. Begränsa alltid preventDefault() till endast de specifika tangenter som din komponent behöver hantera internt (såsom piltangenter för listboxar).
  • Att bygga en modal dialogruta som sätter fokus inuti den men inte tillhandahåller någon Escape-hanterare eller stängknapp — utvecklare implementerar ofta delen där fokus går in i modalen korrekt men glömmer att fokusbegränsning inuti en modal bara är acceptabel om det alltid finns en tangentbordsåtkomlig utväg. Varje modal måste hantera Escape-tangenten och inkludera en tabbbar stängknapp.
  • Att använda tabindex='-1' på ett containerelement för att förhindra att det visas i tabb-ordningen, samtidigt som JavaScript fortfarande kan flytta fokus in i det programmatiskt — när fokus flyttas in i ett tabindex='-1'-element via element.focus() finns det inget naturligt Tab-mål att lämna det genom, vilket kan lämna användaren strandsatt om ingen ytterligare tangentbordshantering implementeras.
  • Att bädda in tredjepartswidgets (chatt, kartor, video) utan att granska dem för tangentbordsfällor — leverantörer bygger inte alltid sina inbäddade widgets så att de är tangentbordsåtkomliga. Webbplatsägare förblir ansvariga för allt innehåll på sina sidor, inklusive tredjepartsinbäddningar. Testa alltid inbäddade komponenter manuellt och, om de fångar tangentbordsanvändare, omge dem med en hoppa-över-länk eller ersätt dem med ett tangentbordssäkert alternativ.
  • Att implementera en fokusfälla för en modal eller en sidopanel men inte släppa fällan när komponenten stängs — om JavaScriptet som begränsar fokus inte städas upp ordentligt när modalen stängs kan det fortsätta att fånga upp Tab-händelser och fånga användaren på det nu osynliga lagret.
  • Att använda CSS visibility: hidden eller display: none för att dölja dialogrutans stängknapp av visuella designskäl utan att tillhandahålla en alternativ tangentbordsutväg — om stängknappen är visuellt dold men inte borttagen från tillgänglighetsträdet kan skärmläsaranvändare fortfarande hitta den; men om den också är dold från tillgänglighetsträdet kan det saknas en utväg. Bekräfta att alla stängmekanismer är tangentbordsopererbara även om de visuellt är diskret utformade.
  • Att bygga anpassade autocomplete- eller type-ahead-komponenter som öppnar en förslagslista och sedan dirigerar alla Tab-tryckningar till att cykla genom förslagen i stället för att lämna komponenten — användare ska kunna trycka Escape för att stänga förslagslistan och sedan Tab för att gå till nästa formulärfält. Autocomplete-widgets som omdirigerar Tab till intern navigering bryter mot detta kriterium.
  • Att glömma att testa rich text-redigerare (WYSIWYG-redigerare såsom TinyMCE, CKEditor eller Quill) — dessa komponenter hanterar sin egen tangentbordsinteraktion internt och är en vanlig källa till tangentbordsfällor. Bekräfta alltid att tryck på Escape eller en dokumenterad tangentsekvens lämnar redigeraren och återför fokus till sidans normala tabb-ordning.
  • Att anta att en komponent inte kan vara en tangentbordsfälla bara för att den använder inbyggda HTML-element — ett <select>-element i ett formulär som använder JavaScript för att åsidosätta dess blur-händelse kan fortfarande fånga fokus. Användningen av semantisk HTML garanterar inte ett beteende fritt från tangentbordsfällor när anpassad JavaScript-händelsehantering läggs ovanpå.
  • Att inte tillhandahålla dokumentation på skärmen när en icke-standardiserad tangent krävs för att lämna en komponent — WCAG 2.1.2 tillåter uttryckligen komponenter som kräver icke-standardiserade tangenter för att lämna dem, förutsatt att användaren informeras. Om din widget kräver att man trycker på F6 eller en anpassad tangentkombination för att lämna den måste du tydligt kommunicera detta till användaren, helst via synliga instruktioner intill komponenten eller ett ARIA live region-meddelande när fokus går in.

Relation till Turkiets tillgänglighetsreglering

Turkiets presidentcirkulär 2025/10, publicerat i den officiella tidningen nr 32933 den 21 juni 2025, fastställer bindande krav på digital tillgänglighet för ett brett spektrum av offentliga och privata aktörer som är verksamma i Turkiet. Cirkuläret kräver överensstämmelse med internationellt erkända standarder för webbtillgänglighet — i linje med WCAG 2.1 nivå AA som baslinje, vilket omfattar alla kriterier på nivå A inklusive WCAG 2.1.2 No Keyboard Trap.

WCAG 2.1.2 är ett kriterium på nivå A, vilket representerar den lägsta nivån av överensstämmelse. Enligt cirkuläret är överensstämmelse på nivå A obligatorisk för alla berörda aktörer. Offentliga institutioner måste uppnå denna överensstämmelse inom ett år från cirkulärets publicering, medan privata aktörer får två år på sig att uppfylla kraven.

De aktörer som omfattas av cirkuläret är många och inkluderar offentliga institutioner och myndigheter på alla nivåer, e-handelsplattformar och operatörer av online-marknadsplatser, banker och finansiella tjänsteinstitutioner, sjukhus och vårdgivare, telekommunikationsföretag med 200,000 eller fler abonnenter, resebyråer, privata transportföretag och privatskolor som auktoriserats av Ministry of National Education (MoNE). Detta innebär att underlåtenhet att åtgärda tangentbordsfällor på en webbplats eller webbapplikation som drivs av någon av dessa aktörer utgör ett direkt brott mot Turkiets obligatoriska tillgänglighetsregler.

Med tanke på hur vanligt förekommande tangentbordsfällor är i komplexa webbapplikationer — särskilt i internetbankportaler, system för sjukhustidsbokning, kassaflöden i e-handel och sidor för hantering av telekomkonton — förtjänar WCAG 2.1.2 särskild uppmärksamhet i den turkiska efterlevnadskontexten. Det är just den här typen av interaktionsintensiva, JavaScript-drivna gränssnitt som mest sannolikt innehåller anpassade widgets, modala dialogrutor och tredjepartsinbäddningar som oavsiktligt kan fånga tangentbordsanvändare.

Organisationer som omfattas av cirkuläret bör betrakta testning av tangentbordsfällor som en icke förhandlingsbar del av sin tillgänglighetsgranskningsprocess. Eftersom automatiserade verktyg inte pålitligt kan upptäcka tangentbordsfällor måste berörda aktörer investera i manuell tangentbordstestning utförd av kvalificerade tillgänglighetsspecialister, helst inklusive användare med funktionsnedsättningar, som en del av sin väg mot efterlevnad. Underlåtenhet att åtgärda tangentbordsfällor som identifierats under granskning innebär inte bara en juridisk risk enligt cirkuläret utan också ett betydande hinder för tillgång för användare med motoriska och visuella funktionsnedsättningar som är beroende av tangentbordsnavigering för att använda digitala tjänster.