Aktivieren: Konzentrieren Sie sich nur auf die Verwendung der Tastatur (oder das Drücken von Tabulatoren).


78

Ich möchte deaktivieren, :focuswenn es nicht benötigt wird, weil mir nicht gefällt, wie meine Navigation aussieht, wenn der Fokus darauf liegt. Es verwendet den gleichen Stil wie .activeund ist verwirrend. Ich möchte es jedoch nicht für Leute loswerden, die Tastatur benutzen.

Ich habe darüber nachgedacht, enabled-focusbeim Drücken der Tabulatortaste eine Klasse zum Textkörper body.enabled-focus a:focus{...}hinzuzufügen und dann zu haben, aber das würde für jedes Element, das den Fokus hat, eine Menge zusätzliches CSS hinzufügen. Entfernen Sie dann diese Klasse mit der ersten Maus nach unten aus dem Körper.

Wie würde ich vorgehen? Gibt es eine bessere Lösung?


Fügen Sie in jquery einen Ereignis-Listener für bestimmte Tasten hinzu, die Sie möchten. Wenn diese gedrückt werden, verwenden Sie einfach addClass()die Elemente, um das Fokus-Styling zu erhalten.
Odedta

Es gibt nur eine CSS-Lösung, aber nur in Firefox. Es ist ein W3C-Vorschlag css-tricks.com/keyboard-only-focus-styles
jcubic

Antworten:


100

Diese ausgezeichneten Artikel von Roman Komarov stellt eine tragfähige Lösung für das Erreichen Tastatur-only Fokus Stile für Schaltflächen , Links und andere Containerelemente wie Spannweiten oder divs (die mit dem Attribut tabindex künstlich hergestellt fokussierbar sind)

Die Lösung:

Codepen

1) Wickeln Sie den Inhalt des ursprünglichen interaktiven Elements in ein zusätzliches inneres Element mit tabindex="-1"(siehe Erklärung unten).

Also anstatt zu sagen:

<button id="btn" class="btn" type="button">I'm a button!</button>

mach das:

<button id="btn" class="btn" type="button">
    <span class="btn__content" tabindex="-1">
        I'm a button!
    </span>
</button>

2) Verschieben Sie das CSS-Styling auf das innere Element (Layout-CSS sollte auf dem ursprünglichen äußeren Element verbleiben) - so dass die Breite / Höhe des äußeren Elements vom inneren usw. stammt.

3) Entfernen Sie das Standard-Fokus-Styling von den äußeren und inneren Elementen:

.btn:focus,
.btn__content:focus {
    outline: none;
}

4) Fügen Sie dem inneren Element nur dann wieder Fokus-Styling hinzu, wenn das äußere Element den Fokus hat:

.btn:focus > .btn__content  {
    box-shadow: 0 0 2px 2px #51a7e8; /* keyboard-only focus styles */
    color: lime; /* keyboard-only focus styles */
} 

Warum funktioniert das?

Der Trick hier ist das Setzen des inneren Elements mit tabindex="-1"- siehe MDN :

Ein negativer Wert (normalerweise tabindex = "- 1" bedeutet, dass das Element fokussierbar sein sollte, aber nicht über die sequentielle Tastaturnavigation erreichbar sein sollte ...

Das Element kann also per Mausklick oder programmgesteuert fokussiert werden. Andererseits kann es nicht über Tastatur-Registerkarten erreicht werden.

Wenn also auf das interaktive Element geklickt wird, erhält das innere Element den Fokus. Es werden keine Fokusstile angezeigt, da wir sie entfernt haben.

.btn:focus,
.btn__content:focus {
    outline: none;
}

Beachten Sie, dass zu einem bestimmten Zeitpunkt nur 1 DOM-Element fokussiert werden kann (und document.activeElementdieses Element zurückgibt), sodass nur das innere Element fokussiert wird.

Auf der anderen Seite: Wenn wir mit der Tastatur tippen, wird nur das äußere Element fokussiert (denken Sie daran: Das innere Element hat tabindex = "- 1" und ist nicht über die sequentielle Tastaturnavigation erreichbar). fokussierbare äußere Elemente wie ein klickbares <div>- wir müssen sie künstlich fokussierbar machen, indem wir hinzufügen tabindex="0"]

Jetzt wird unser CSS aktiviert und die Fokusstile nur für die Tastatur hinzugefügt the inner element.

.btn:focus > .btn__content  {
    box-shadow: 0 0 2px 2px #51a7e8; /* keyboard-only focus styles */
    color: lime; /* keyboard-only focus styles */
} 

Natürlich möchten wir sicherstellen, dass wir beim Aktivieren und Drücken enternicht unser interaktives Element beschädigt haben und das Javascript ausgeführt wird.

Hier ist eine Demo, die zeigt, dass dies tatsächlich der Fall ist. Beachten Sie jedoch, dass Sie diese nur für inhärent interaktive Elemente wie Schaltflächen und Links kostenlos erhalten (dh die Eingabetaste drücken, um ein Klickereignis auszulösen). Für andere Elemente wie z. B. Bereiche - Sie müssen das manuell codieren :)

Codepen


NB:

1) Obwohl dies eine übermäßig komplizierte Lösung zu sein scheint, ist sie für eine Nicht-Javascript-Lösung tatsächlich ziemlich beeindruckend. Einfachere CSS-only ‚Lösungen‘ beteiligt :hoverund :activePseudo-Klasse Styling tun einfach nicht funktionieren. (es sei denn, Sie gehen natürlich davon aus, dass das interaktive Element beim Klicken wie eine Schaltfläche innerhalb eines modalen Sprichworts sofort verschwindet.)

Codepen

2) Diese Lösung ist nicht perfekt: Firefox unter Windows erhält weiterhin Fokusstile für Schaltflächen beim Klicken - aber das scheint ein Firefox-Fehler zu sein (siehe Artikel ).

3) Wenn Browser die Pseudoklasse : focus-ring implementieren - es gibt möglicherweise eine viel einfachere Lösung für dieses Problem - (siehe Artikel ) Für das, was es wert ist, gibt es eine Polyfüllung für :focus-ring- siehe diesen Artikel von Chris DeMars


Eine pragmatische Alternative zu Nur-Tastatur-Fokusstilen

Das Erreichen von Nur-Tastatur-Fokusstilen ist daher überraschend schwierig. Eine Alternative / Problemumgehung, die viel einfacher ist und sowohl die Erwartungen des Designers erfüllt als auch zugänglich ist, besteht darin, den Fokus so zu gestalten, wie Sie ihn für den Schwebeflug stylen würden.

Codepen

Obwohl dies technisch gesehen keine Nur-Tastatur-Stile implementiert, entfällt im Wesentlichen die Notwendigkeit von Nur-Tastatur-Stilen.


1
Der Firefox unter Windows-Fehler scheint ab FF 60 nicht mehr vorhanden zu sein. Die Verwendung eines :not(:hover):focusSelektors scheint den Trick zu tun.
Wegry

@wegry :not(:hover):focusist aufgrund des oben beschriebenen Problems keine sehr gute Lösung: "Sobald Sie den Mauszeiger herausfahren, erhalten Sie das Fokus-Styling wieder - weil es immer noch fokussiert ist (zumindest in Bezug auf die Schaltfläche und die fokussierbare Spanne)"
Zbynek

@Zbynek Ich stimme zu, ich habe es in der Vergangenheit jedoch als Notlösung verwendet.
Wegry

Wie kann dies implementiert werden, wenn wir den Eingangstyp = "Radio" haben?
Thewebtud

79

Fallstudie: Facebook-Anmeldeseite

Facebook verwendet derzeit (Juni 2018) ein kleines Stück Javascript auf seiner Anmeldeseite.

Das Javascript erkennt, wenn der Benutzer mit der Maus geklickt oder die Tastatur verwendet hat, und schaltet eine Klasse am Körper ein und aus: <body class="using-mouse">

Dann können CSS-Regeln diese Klasse verwenden, um das entsprechende Fokus-Styling für die relevanten Elemente anzuzeigen oder auszublenden.

Hier ist ein Beispielcode (auch auf CodePen verfügbar ). Vergleichen Sie das Klicken und Tabulieren.

// Let the document know when the mouse is being used
document.body.addEventListener('mousedown', function() {
  document.body.classList.add('using-mouse');
});

// Re-enable focus styling when Tab is pressed
document.body.addEventListener('keydown', function(event) {
  if (event.keyCode === 9) {
    document.body.classList.remove('using-mouse');
  }
});

// Alternatively, re-enable focus styling when any key is pressed
//document.body.addEventListener('keydown', function() {
//  document.body.classList.remove('using-mouse');
//});
/* The default outline styling, for greatest accessibility. */
/* You can skip this to just use the browser's defaults. */
:focus {
  outline: #08f auto 2px;
}

/* When mouse is detected, ALL focused elements have outline removed. */
body.using-mouse :focus {
  outline: none;
}
<input>
<button>Submit</button>

Beachten Sie, dass :focusoben das Äquivalent zu *:focusallen Elementen entspricht. Wenn Sie nur das Styling von den Schaltflächen entfernen möchten, können Sie button:focuses stattdessen dort platzieren.


Fallstudie: GMail-Anmeldeseite

Alternativ dazu gestaltete GMail zu dieser Zeit nur fokussierte Tasten mit einem stärkeren Schatten als nicht fokussierte Tasten, unabhängig davon, ob sich der Benutzer auf Maus oder Tastatur befand.

Dies ist einfach zu implementieren und zu verstehen und erfordert kein Javascript.

:focus {
  outline: none;
  box-shadow: 0 0px 16px #0005;
}

Aber es ist ein Kompromiss. Es vermittelt Fokusinformationen, an denen Mausbenutzer nicht wirklich interessiert sind, und ist für Tastaturbenutzer möglicherweise etwas zu subtil .

Dennoch ist dieser Kompromiss wahrscheinlich besser als eines der Extreme (ein starker Umriss für alle Benutzer oder überhaupt kein Umriss).


Stackoverflow ‚s Haupttasten verwenden , um einen ähnlichen Ansatz wie GMail, aber mit einem stilisierten Look:

box-shadow: inset 0 1px 0 0 rgba(102,191,255,0.5), 0 0 0 4px rgba(0,149,255,0.15);

Persönlich würde ich für die Zugänglichkeit eine stärkere (kontrastreichere) Farbe verwenden.


5
Ich mag die Facebook-Lösung, obwohl sie Javascript verwendet. Der Code ist einfach zu verstehen und das CSS liegt vollständig in Ihren Händen. Ich denke, ich werde damit anfangen. Vielen Dank.
Bram Vanroy

3
Geniale einfache Lösung.
Gabriel Rodriguez

3
Ich denke, diese Lösung ist besser und weniger hackig als die akzeptierte. Außerdem ist weniger Markup-Unordnung erforderlich.
CunningFatalist

1
beste Lösung +1
Mas

1
@IOIIOOIO Ja, ihr Verhalten hat sich geändert. Heutzutage scheinen sie Fokusstile nur wieder zu aktivieren, wenn Sie die Tabulatortaste drücken, und es gibt ein leeres / fehlerhaftes Feld. Aber eigentlich denke ich, dass das, was Sie vorgeschlagen haben, das intuitivste ( POLA ) ist, also habe ich die Antwort entsprechend aktualisiert. Vielen Dank!
joeytwiddle

40

Das Entfernen outlineist für die Zugänglichkeit schrecklich! Im Idealfall wird der Fokusring nur angezeigt, wenn der Benutzer die Tastatur verwenden möchte .

2018 Antwort: Verwenden Sie : Fokus sichtbar . Derzeit handelt es sich um einen W3C-Vorschlag zur Gestaltung des Nur-Tastatur-Fokus mithilfe von CSS. Bis die meisten Browser dies unterstützen, können Sie diese robuste Polyfüllung verwenden . Es ist nicht erforderlich, zusätzliche Elemente hinzuzufügen oder die zu ändern tabindex.

/* Remove outline for non-keyboard :focus */
*:focus:not(.focus-visible) {
  outline: none;
}

/* Optional: Customize .focus-visible */
.focus-visible {
  outline-color: lightgreen;
}

Ich habe auch einen ausführlicheren Beitrag geschrieben, falls Sie weitere Informationen benötigen.


2
Super! Habe +1 Internet.
Joeytwiddle

1
Ugghhhh warum ist dieser Standard nicht schon. Liebe zukünftige Leser, ich beneide Sie.
Chunky Chunk

19

Dies ist ein Problem, auf das Sie wahrscheinlich häufig stoßen werden. Das Gute an solchen Problemen ist, wenn Sie einmal eine Lösung gefunden haben, wird es Sie nicht mehr stören.

Die eleganteste Lösung scheint die einfachste zu sein: Entfernen Sie nicht die Gliederung auf: focus, machen Sie es stattdessen auf: active - schließlich ist: active die dynamische Pseudoklasse, die sich explizit mit den Stilen befasst, die angewendet werden sollen, wenn a fokussierbares Element wird angeklickt oder anderweitig aktiviert.

a:hover, a:active { outline: none; }

Die einzigen kleineren Probleme bei dieser Methode: Wenn ein Benutzer einen Link aktiviert und dann die Zurück-Schaltfläche des Browsers verwendet, wird der Umriss sichtbar. Oh, und alte Versionen von Internet Explorer werden notorisch durch die genaue Bedeutung von: focus ,: hover und: active verwirrt, sodass diese Methode in IE6 und darunter fehlschlägt.

Tipp

Es gibt eine einfache Problemumgehung, um zu verhindern, dass Konturen überlaufen, indem eine einfache hinzugefügt wird overflow:hidden, die die Kontur um den anklickbaren Teil des Elements selbst in Schach hält.


1
Das war aufschlussreich! Vielen Dank.
Miro

2
Was ist mit Knöpfen?
DanV

4

Beim Spielen mit der von Danield akzeptierten Lösung fand ich einen alternativen, einfacheren Weg, der auf dem inneren / äußeren Div-Konzept basiert.

1) Erstellen Sie ein äußeres und inneres Element. Geben Sie das äußere Element tabindex = "0" und das innere Element tabindex = "- 1" an.

<div role="button" class="outer" tabindex="0">
    <span class="inner" tabindex="-1">
        I'm a button!
    </span>
</div>

2) Entfernen Sie im CSS den Umriss vom inneren Element, wenn Sie fokussiert sind:

.inner:focus{
    outline: none;
}

3) Wenden Sie beliebige Maus- oder Klickereignishandler auf das innere Element an. Wenden Sie alle Fokusereignisse (onfocus, onblur, onkeydown) auf das äußere Element an.

Zum Beispiel:

<div role="button" class="outer" tabindex="0" onfocus="focusEventHandler()" onkeydown="handleKeyDown.bind(this, myEventHandler)">
    <div class="inner" tabindex="-1" onClick="myEventHandler()">
        I'm a button!
    </div>
</div>

** Behalten Sie die Größe und Position so bei, dass das innere Element das äußere Element vollständig überlappt. Positionieren Sie den gesamten "Knopf" mit Styling auf dem äußeren Element.

So funktioniert das:

Wenn der Benutzer auf die "Schaltfläche" klickt, klickt er auf das innere Element, bei dem die Fokuskontur entfernt wurde. Es ist nicht möglich, auf das äußere Element zu klicken, da es vom inneren Element abgedeckt wird. Wenn der Benutzer die Tastatur verwendet, um auf die "Schaltfläche" zu tippen, gelangt er zum äußeren Element (tabindex = "0" macht das Element mit "tab" erreichbar), das eine Fokuskontur erhält, aber das innere Element ist nicht über die "Schaltfläche" erreichbar Tabulator (mit tabindex = "- 1") und erhält beim Klicken keine Fokuskontur.


Können Sie erläutern, warum dies besser / einfacher ist als die akzeptierte Lösung?
Tamlyn

4
&:focus:not(:hover) { }

Es wird in 100% der Fälle nicht funktionieren, aber ich denke, für die Bedürfnisse der meisten Menschen sollte dies ausreichen.

Dadurch wird verhindert, dass der :focusStatus beim Klicken ausgelöst wird, da sich die Maus über dem Element befinden muss, um darauf zu klicken.

https://codepen.io/heyvian/pen/eopOxr


1

UPDATE 2020

:focus-visibleist in stabilem Chrome gelandet. Benutze es einfach schon!

ORIGINAL POST

Bis :focus-visiblees nicht in allen gängigen immergrünen Browsern vorhanden ist, können Sie diesen einfachen Trick im globalen Teil Ihres CSS ohne Polyfills verwenden:

@media (pointer: coarse) {
  *:focus {
    outline: none;
  }
}

und fügen Sie dann wie gewohnt Fokuseffekte hinzu :focus .

An diesem Punkt haben Sie wahrscheinlich gelernt, dass die Einstellung der outline: none; auf fokussierte Elemente standardmäßig aus Sicht der Barrierefreiheit eine schreckliche Idee ist. Das ist sicherlich wahr.

Wenn Sie diese Regel jedoch in der pointer: coarseMedienabfrage anwenden, ist sie sehr nützlich, da sie nur für Mobiltelefone und Tablets gilt, nicht jedoch für Desktops. Welches ist genau das, was Sie erreichen wollen.

Das einzige Problem, an das ich denken kann, sind mobile Benutzer mit Tastaturen, die sie zum Durchsuchen von Inhalten verwenden, aber ich bin mir nicht sicher, ob es viele solcher Benutzer gibt. Letztendlich :focus-visiblewird es also die bessere Lösung sein, aber im Moment sollte dies ausreichen.


Dies scheint auch auf dem Desktop nicht zu funktionieren: jsfiddle.net/mirohristov/Lovp947w Können Sie eine funktionierende Demo bereitstellen?
Miro

@Miro es wird nicht angenommen, auf dem Desktop zu "arbeiten", siehe das pointer: coarseBit. Es ist eine Problemumgehung, Fokusumrisse nur auf Mobilgeräten auszublenden (Telefone, Tablets oder alles ohne ein feines Zeigegerät, z. B. Maus oder Touchpad / Trackpad).
Neurotransmitter

Aha. Ich dachte du beantwortest meine Frage. (Was auch über Desktop ist)
Miro

Ja, aber nicht wirklich ... Es war eher eine Problemumgehung für Leute, die hier nach praktischen Lösungen suchen, bis :focus-visiblesie in den wichtigsten Browsern implementiert sind. Das ist richtig, dass die Antwort nicht für alle in der Frage aufgeführten Probleme eine Lösung bietet. In diesem Fall können Sie sie zu Recht ablehnen - es wird keine Beleidigung begangen.
Neurotransmitter

2020 ist da und das :focus-visibleist in Chrome implementiert. Wichtiger Meilenstein!
Neurotransmitter

0

Es gibt keine klare Lösung. Ich habe eine Hackish-Lösung durchgeführt: Wenden Sie das Klickereignis auf Ihren Hauptcontainer an und schreiben Sie den folgenden Code beim Klicken

    _handleMouseClick = (event) => {
        if(event.detail){
            document.activeElement.blur();
        }
    }

Wenn Sie mit der Maus klicken, erhalten Sie event.detail = 1 bei diesem Klick. Verwischen Sie dieses Element, sodass der Umriss entfernt wird. Beim Klicken auf die Tastatur erhalten Sie event.detail = 0, sodass Sie sich im Tastaturfall normal verhalten

ODER

In CSS-Datei

     body.disableOutline *:focus{
        outline: none !important;
    }

In Main js

     document.addEventListener('click', _handleMouseClick,true);
            document.addEventListener('keydown',_keydown,true);
            function _handleMouseClick(event){
                if(event.detail){
                    document.getElementsByTagName("body")[0].classList.add("disableOutline");
                }
            }
            function _keydown(e){
                document.getElementsByTagName("body")[0].classList.remove("disableOutline");
            }

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.