Een CSS-Aanpak te vangen Focus Binnen van een Element

0
58

Onlangs las ik dit artikel door Keith Subsidie die de nieuw aangekomen <dialoogvenster>. Enthousiast over deze nieuwe UI-element, ik onmiddellijk zitten om te experimenteren met het om te zien hoe deze effectief kan worden gebruikt als een modal — de meest voorkomende gebruik van. Tijdens het experimenteren, en ontdekte ik een keurige CSS truc op het onderscheppen van focus binnen de <dialoogvenster> element, een gemeenschappelijke toegankelijkheid eis voor modals, en een notoir moeilijk.

Wat is focus trapping?

Eerst een citaat uit het W3C documentatie over wat er moet gebeuren na het indrukken van een toets in een dialoogvenster:

Tabblad:

  • Verplaatst de focus naar het volgende tabblad-kunnen element in de dialoog.
  • Als de focus is op de laatste tab-kunnen element in de dialoog, verplaatst de focus naar het eerste tabblad kunnen element in de dialoog.

Shift + Tab

  • Verplaatst de focus naar het vorige tabblad-kunnen element in de dialoog.
  • Als de focus is op het eerste tabblad kunnen element in de dialoog, verplaatst de focus naar het laatste tabblad kunnen element in de dialoog.

Om samen te vatten, als in een dialoogvenster, druk op Tab of Shift+Tab moet op de fiets de focus binnen de dialoog alleen onder het focussen elementen binnen de dialoog.

Dit is logisch, want als een dialoog open is, een gebruiker interactie alleen binnen het en waardoor de focus te ontsnappen buiten de dialoog in wezen zou het mengen van contexten en eventueel het maken van een lidstaat waar de gebruiker niet weet welk element in focus.

Dus, terug te gaan naar het idee van een modal, onze verwachting dat de tab aan de binnenkant van de modale zou alleen richten op elementen binnenkant van de modal. Iets buiten de context van de modale zou vallen, want het tabblad is alleen bezig met wat zich aan de binnenkant van het. Dit is wat we bedoelen met focus onderscheppen.

Een uitvoering met JavaScript

Als we implementeren focus trapping in een <dialoogvenster> de meest voorkomende aanpak zou zijn om het volgende te doen wanneer het dialoogvenster wordt geopend:

1. Grijp alle focussen/tappable elementen binnen de dialoog.
2. Luister voor de Tab en Shift+Tab toetsen en handmatig de focus naar het volgende of vorige element, respectievelijk.
3. Als de toets gebeurt op de eerste focussen element, dan richten de laatste focussen element in de keten en vice versa.

Zo maken we een lus op de focus als de gebruiker drukt op Tab of Shift+Tab. Zie deze W3C-codefragment als een voorbeeld van hoe dit kan worden benaderd met JavaScript. U zult zien dat het heel wat van JavaScript.

Enter :focus-binnen

Terug naar mijn experiment met het nieuwe <dialoogvenster> element. Wanneer het denken over focus trapping, een CSS pseudo-class (ook zeer recente browsers) onmiddellijk kwam in mijn gedachten : :focus-in.

Als u nog niet gehoord over die voor en vertegenwoordigt een element dat heeft ontvangen, focus of een element bevat dat heeft ontvangen focus. Dus, bijvoorbeeld, je hebt een <div> en de binnenkant van het input element. Als u wilt dat de stijl die <div> wanneer de opgenomen input focus heeft, kunt u dit doen als volgt:

div:focus-in {
border: 2px solid red;
}

Zie de Pen :focus-binnen door Geoff Graham (@geoffgraham) op CodePen.

De CSS truc om zich te concentreren trapping

Laten we benutten :focus-binnen-en CSS-overgangen in te voeren, een basic focus trap binnenkant van een <dialoogvenster> element.

Samengevat, hier is hoe de truc werkt. Wanneer de focus ligt niet binnen de dialoog en de dialoog open is), we:

  1. trigger een CSS-overgang
  2. detecteren dat de overgang voltooiing in JavaScript
  3. focus het eerste element in het dialoogvenster

Maar, laten we eerst alles in te stellen. Hier is de basis van dialoog en het openen van de functionaliteit:

<button id=”knop”>Open dialoog</button>
<dialoog id=”modale”>
<form action=””>
<label>
<input type=”text” /> Gebruikersnaam
</label>
<label>
<input type=”password” /> Wachtwoord
</label>
<input type=”submit” value=”Verzenden” />
</form>
</dialog ->
knop.onclick = () => {
modaal.showModal();
}

Daar gaan we. Te klikken op de knop opent onze dialoog. Alleen deze veel code nodig is om een basis te werken modaal met behulp van de nieuwe <dialoogvenster> element!

Zie de Pen Eenvoudig <dialoog&rt; door Geoff Graham (@geoffgraham) op CodePen.

Als je geopend en de dialoog in het bovenstaande voorbeeld en begonnen met de tab-toets meerdere keren, je hebt misschien al gemerkt dat de problemen: de focus begint met elementen in de dialoog, maar dan laat, zodra het laatste element in de dialoog is voorbij.

Dit is de kern van onze truc. We een of andere manier moet het geen focus gedetecteerd met :focus-in over te JavaScript dus dat kunnen we verzenden de focus terug naar het dialoogvenster. Dit is waar de CSS transities in het spel komen. Een CSS-overgang is iets dat gebeurt via CSS, maar zendt gebeurtenissen in JavaScript. In ons geval kan leiden tot een overgang op een onroerend goed met een verwaarloosbaar (want het maakt niet uit in ons geval) visuele verschil en luister voor de overgang voltooiing in JavaScript.

Merk op dat we moeten zorgen voor deze overgang als het dialoogvenster is geopend, maar niet de focus binnen.

dialoog {
background-color: rgb(255, 255, 255);
}
het dialoogvenster[open]: (: focus-in) {
background-color: rgb(255, 255, 254);
overgang: background-color 0.01 s;
}

Laten we eens kijken wat dat met CSS aan het doen is.

  1. We zetten een achtergrond-kleur van onze keuze in het dialoogvenster. Dit is niet noodzakelijk, maar zorgt ervoor dat we hebben dezelfde achtergrond kleur in verschillende browsers.
  2. Het dialoogvenster[open]: (: focus-in) functie is van toepassing wanneer het dialoogvenster is geopend, maar niet in focus is op of aan de binnenkant. Dit werkt omdat native <dialoogvenster> element brengt een open attribute wanneer het geopend.
  3. In deze regel, veranderen we de achtergrond-kleur van een minimum bedrag. Dit is de minste verandering die nodig is om te leiden tot een CSS-animaties en tegelijkertijd niet wordt veroorzaakt door een visueel verschil voor de gebruiker (denk eraan dit is een dummy overgang). Ook stellen we de overgang woning met een zeer geringe duur omdat we willen dat het tot het einde als snel mogelijk en word ontdekt in JavaScript.

Een vleugje van JavaScript

Nu, alles wat we moeten doen is het detecteren van het einde van onze geactiveerd CSS overgang en de focus terug naar het eerste element in de modal, zoals:

modaal.addEventListener(‘transitionend’, (e) => {
modaal.querySelector(‘input’).focus();
});

Wij hechten een transitionend luisteraar op de modale en de binnenkant van de callback, richten we ons in de eerste invoer in de modal. Gedaan!

Zie de Pen Dialoog focus onderscheppen met CSS door Kushagra Gour (@chinchang) op CodePen.

Beperkingen

Dit is een snelle experiment ik heb een werkende proof-of-concept van focus onderscheppen met de :focus-in pseudo-class. Het heeft een aantal beperkingen ten opzichte van de speciale JavaScript oplossingen om dit te bereiken. Toch, iets is beter dan niets!

Hier zijn een paar van de dingen die deze uitvoering ontbreekt:

  1. Volgens de W3C-richtlijnen, de focus moet cyclus op de focussen element. Maar we zijn altijd gericht op de eerste input element. Dit is omdat zonder het schrijven van JavaScript, weten we niet of de focus verloren uit de eerste of laatste element.
  2. We zijn altijd gericht terug naar de eerste input element. Maar er zijn veel meer focussen HTML-elementen die kunnen aanwezig zijn voor ingang of misschien is er geen input-element op in de modal. Nogmaals, volwaardige JavaScript oplossingen detecteren en handhaven van een lijst van alle elementen te focussen en concentreren.

Beter (JavaScript) implementaties van focus trapping

  1. Zoals eerder vermeld, een voorbeeld is beschikbaar in de W3C documentatie zelf.
  2. Hier is een andere uitvoering door Rodney Rehm, die ook luistert naar het tabblad.
  3. Greg Kraus heeft een bibliotheek die dit bereikt. Zijn uitvoering onderhoudt een lijst van de kiezers voor alle geldige focussen elementen.
  4. Een meer lichtgewicht bibliotheek voor het maken van toegankelijke modals.

Dat is alles voor dit experiment. Als u graag deze truc kunt u mij volgen op waar ik deel meer artikelen en andere projecten van mij.