En CSS-Strategi för att Fälla Fokus på Insidan av ett Element

0
53

Jag läste nyligen den här artikeln av Keith Grant som infördes den nyanlända <dialogrutan>. Upphetsad av detta nya element i ANVÄNDARGRÄNSSNITTET, som jag genast satte mig ner för att experimentera med detta för att se hur den kan användas effektivt som en modal — den vanligaste användningen av det. När experimentera, upptäckte jag en snygg CSS-trick om hur man fälla fokus inom <dialogrutan> – element, ett gemensamt krav på tillgänglighet för modals, och en notoriskt svårt.

Vad är fokus att fånga?

Först ett citat från W3C: s dokumentation om vad som ska hända efter att en knapp inne i en dialogruta:

Fliken:

  • Flyttar fokus till nästa flik-kan-element inuti dialogrutan.
  • Om fokus är på den senaste fliken som-kan-element inuti dialogrutan, flyttar fokus till den första fliken kan element i dialogrutan.

Shift + Tab

  • Flyttar fokus till föregående flik-kan-element inuti dialogrutan.
  • Om fokus ligger på den första fliken kan element i dialogrutan, flyttar fokus till den sista fliken som-kan-element inuti dialogrutan.

För att sammanfatta, när inne i en dialogruta, trycka på Tabb eller Skift+Tabb bör cykel fokus i dialogrutan bara—bland tabbindexvärden delar i dialogrutan.

Detta är logiskt eftersom när en dialogruta är öppen, är en användare interagera bara inne i den och låter den fokusera på att fly utanför dialogrutan skulle i huvudsak vara att blanda sammanhang och eventuellt skapa en stat där användaren inte vet vilken faktor som är i fokus.

Så, gå tillbaka till tanken på en modal, vår förhoppning skulle vara att tabbing insidan av modal bara skulle fokusera på delar insidan av modal. Något utanför ramen av den modala skulle vara utom räckvidd, eftersom den fliken är endast om vad som är inne i det. Detta är vad vi menar med fokus svällning.

En implementation med JavaScript

Om vi skulle genomföra fokus svällning inuti en <dialogrutan>, som är den vanligaste metoden skulle vara att göra följande när dialogrutan öppnas:

1. Ta alla tabbindexvärden/tappable delar i dialogrutan.
2. Lyssna för Tab och Shift+Tab för knapptryckningar och manuellt fokus till nästa eller föregående element, respektive.
3. Om tryckning sker på första tabbindexvärden element, då fokus de senaste tabbindexvärden element i kedjan, och vice versa.

På detta sätt skapar vi en slinga på fokus när användaren trycker på Tab eller Skift+Tab. Se detta W3C kodavsnittet som ett exempel på hur detta kan ske med JavaScript. Du kommer att se att det är ganska lite av JavaScript.

Ange :fokus-inom

Tillbaka till min experimentera med nya <dialogrutan> – elementet. När man tänker på att fokusera svällning, en CSS-pseudo-klass (också mycket senare i webbläsare) omedelbart kom att tänka på : :fokus-inom.

Om du inte har hört talas om det förut, det är en del som har fått fokus eller innehåller ett element som har fått fokus. Så, till exempel, har du en <div> och insidan av det är en input-elementet. Om du vill stil som <div> när den innehöll ingång har fokus kan du göra det så här:

div:fokus-inom {
border: 2px solid red;
}

Se Pennan :fokus-inom av Geoff Graham (@geoffgraham) på CodePen.

CSS-trick för att fokusera svällning

Låt oss utnyttja :fokus-inom och CSS övergångar för att genomföra en grundläggande fokus fälla inuti en <dialogrutan> – elementet.

För att sammanfatta, här är hur tricket fungerar. När fokus inte ligger inom dialogen (och dialogen är öppen), vi:

  1. utlösa en CSS-övergången
  2. upptäcka att övergången tillägg i JavaScript
  3. fokus på det första elementet i dialogrutan

Men, låt oss först få ställa upp. Här är de grundläggande dialogrutan och öppna funktionalitet:

<button id=”knapp”>dialogrutan för att Öppna</button>
<dialogrutan id=”modal”>
<form action=””>
<etikett> >
<input type=”text” /> Användarnamn
</label>
<etikett> >
<input type=”password” /> Lösenord
</label>
<input type=”submit” value=”Skicka” />
</form>
</dialog>
– knappen.onclick = () => {
modal.showModal();
}

Där har vi det. Klicka på knappen som ska öppna dialogen. Bara så mycket kod som behövs för att göra en grundläggande arbets-modal använder ny <dialogrutan> – element!

Se Pennan Enkel <dialogrutan&ng; av Geoff Graham (@geoffgraham) på CodePen.

Om du öppnade dialogrutan i exemplet ovan och började tabb flera gånger, du kanske redan har uppmärksammat problemet: man börjar med element i dialogrutan, men lämnar sedan en gång till det sista elementet i dialogrutan har gått.

Detta är kärnan av vår trick. Vi på något sätt måste skicka tappat fokus detekteras med :fokus-inom över att JavaScript så att vi kan skicka fokus tillbaka till dialogrutan. Det är där CSS övergångar spelar in. En CSS-övergången är något som sker genom CSS, men avger händelser i JavaScript också. I vårt fall kan vi utlösa en övergång på alla fastigheter med en försumbar (eftersom det inte spelar någon roll i vårt fall) visuell skillnad och lyssna för övergången tillägg i JavaScript.

Observera att vi behöver för att utlösa denna övergång när dialogen är öppen, men inte har fokus i den.

dialogrutan {
background-color: rgb(255, 255, 255);
}
dialogrutan[öppna]:inte(:fokus-inom) {
background-color: rgb(255, 255, 254);
övergång: background-color 0.01 s.
}

Låt oss se vad som CSS gör.

  1. Vi sätter en background-color av våra val i dialogrutan. Detta är inte nödvändigt, men säkerställer att vi har samma bakgrundsfärg i olika webbläsare.
  2. Dialogrutan[öppna]:inte(:fokus-inom) selector gäller när dialogen är öppen, men inte har fokus på eller inuti det. Detta fungerar eftersom native <dialogrutan> – elementet ger en öppen attribut när det är öppet.
  3. Inuti denna artikel, vi ändra background-color av ett minimibelopp. Detta är den minsta förändring som krävs för att trigga en CSS-animation och på samma gång inte orsakar någon visuell skillnad för användaren (kom ihåg att detta är ett dummypaket för övergången). Vi kan också ställa övergången fastighet med en mycket liten tid eftersom vi vill att det ska sluta så snart som möjligt och få upptäckts i JavaScript.

En touch av JavaScript

Nu är allt vi behöver göra är att upptäcka slutet av vår utlöste CSS övergången och fokus tillbaka på det första elementet inuti modal, så här:

modal.addEventListener(‘transitionend’, (e) => {
modal.querySelector (“input”).fokus();
});

Vi fäster transitionend lyssnare på modal och inne återuppringning fokuserar vi den första ingången inne i modal. Gjort!

Se Pennan Dialogrutan fokus svällning med CSS genom att Kushagra Gour (@chinchang) på CodePen.

Begränsningar

Detta är en sammanfattning av experiment jag gjorde för att skapa en fungerande proof-of-concept i fokus svällning med :fokus-inom pseudo klass. Det har flera begränsningar jämfört med dedikerade JavaScript lösningar för att uppnå detta. Ändå, något är bättre än ingenting!

Här är ett par saker som detta genomförande saknar:

  1. Enligt W3C: s riktlinjer bör fokus cykel på tabbindexvärden element. Men vi är alltid med fokus på den första input-elementet. Detta är på grund utan att skriva mer JavaScript, vi kan inte veta om det var fokus försvinner från den första eller sista elementet.
  2. Vi är alltid med fokus tillbaka till det första input-elementet. Men det finns många fler tabbindexvärden HTML-element som kan finnas innan inmatning eller kanske är det inte bidrag inslag på alla inne i modal. Igen, fullfjädrad JavaScript lösningar upptäcka och underhålla en lista över alla tabbindexvärden delar och fokusera rätt.

Bättre (JavaScript) implementeringar av fokus svällning

  1. Som tidigare nämnts, ett fungerande exempel finns inne i W3C: s dokumentation sig.
  2. Här är en annan tillämpning av Rodney Rehm som också lyssnar för fliken.
  3. Greg Kraus har ett bibliotek som uppnår detta. Hans genomförandet upprätthåller en lista av väljare för alla giltiga tabbindexvärden element.
  4. En mer lätt bibliotek för att skapa tillgängliga modals.

Det var allt för den här experimentet. Om du gillade detta trick, kan du följa mig på där jag delar med fler artiklar och sida-projekt för mig.