Ich möchte deaktivieren, :focus
wenn 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 .active
und ist verwirrend. Ich möchte es jedoch nicht für Leute loswerden, die Tastatur benutzen.
Ich habe darüber nachgedacht, enabled-focus
beim 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?
addClass()
die Elemente, um das Fokus-Styling zu erhalten.Antworten:
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:
Code-Snippet anzeigen
button { -moz-appearance: none; -webkit-appearance: none; background: none; border: none; outline: none; font-size: inherit; } .btn { all: initial; margin: 1em; display: inline-block; } .btn__content { background: orange; padding: 1em; cursor: pointer; display: inline-block; } /* Fixing the Safari bug for `<button>`s overflow */ .btn__content { position: relative; } /* All the states on the inner element */ .btn:hover > .btn__content { background: salmon; } .btn:active > .btn__content { background: darkorange; } .btn:focus > .btn__content { box-shadow: 0 0 2px 2px #51a7e8; color: lime; } /* Removing default outline only after we've added our custom one */ .btn:focus, .btn__content:focus { outline: none; }
<h2>Keyboard-only focus styles</h2> <button id="btn" class="btn" type="button"> <span class="btn__content" tabindex="-1"> I'm a button! </span> </button> <a class="btn" href="#x"> <span class="btn__content" tabindex="-1"> I'm a link! </span> </a> <span class="btn" tabindex="0"> <span class="btn__content" tabindex="-1"> I'm a span! </span> </span> <p>Try clicking any of the the 3 focusable elements above - no focus styles will show</p> <p>Now try tabbing - behold - focus styles</p>
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 :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.activeElement
dieses 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ügentabindex="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
enter
nicht 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 :)
Code-Snippet anzeigen
//var elem = Array.prototype.slice.call(document.querySelectorAll('.btn')); var btns = document.querySelectorAll('.btn'); var fakeBtns = document.querySelectorAll('.btn[tabindex="0"]'); var animate = function() { console.log('clicked!'); } var kbAnimate = function(e) { console.log('clicking fake btn with keyboard tab + enter...'); var code = e.which; // 13 = Return, 32 = Space if (code === 13) { this.click(); } } Array.from(btns).forEach(function(element) { element.addEventListener('click', animate); }); Array.from(fakeBtns).forEach(function(element) { element.addEventListener('keydown', kbAnimate); });
button { -moz-appearance: none; -webkit-appearance: none; background: none; border: none; outline: none; font-size: inherit; } .btn { all: initial; margin: 1em; display: inline-block; } .btn__content { background: orange; padding: 1em; cursor: pointer; display: inline-block; } /* Fixing the Safari bug for `<button>`s overflow */ .btn__content { position: relative; } /* All the states on the inner element */ .btn:hover > .btn__content { background: salmon; } .btn:active > .btn__content { background: darkorange; } .btn:focus > .btn__content { box-shadow: 0 0 2px 2px #51a7e8; color: lime; } /* Removing default outline only after we've added our custom one */ .btn:focus, .btn__content:focus { outline: none; }
<h2>Keyboard-only focus styles</h2> <button id="btn" class="btn" type="button"> <span class="btn__content" tabindex="-1"> I'm a button! </span> </button> <a class="btn" href="#x"> <span class="btn__content" tabindex="-1"> I'm a link! </span> </a> <span class="btn" tabindex="0"> <span class="btn__content" tabindex="-1"> I'm a span! </span> </span> <p>Try clicking any of the the 3 focusable elements above - no focus styles will show</p> <p>Now try tabbing + enter - behold - our interactive elements work</p>
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
:hover
und:active
Pseudo-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.)Code-Snippet anzeigen
button { -moz-appearance: none; -webkit-appearance: none; background: none; border: none; font-size: inherit; } .btn { margin: 1em; display: inline-block; background: orange; padding: 1em; cursor: pointer; } .btn:hover, .btn:active { outline: none; }
<h2>Remove css :focus outline only on :hover and :active states</h2> <button class="btn" type="button">I'm a button!</button> <a class="btn" href="#x">I'm a link!</a> <span class="btn" tabindex="0">I'm a span!</span> <h3>Problem: Click on an interactive element.As soon as you hover out - you get the focus styling back - because it is still focused (at least regarding the button and focusable span) </h3>
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 DeMarsEine 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.
quelle
:not(:hover):focus
Selektors scheint den Trick zu tun.:not(:hover):focus
ist 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)"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
:focus
oben das Äquivalent zu*:focus
allen Elementen entspricht. Wenn Sie nur das Styling von den Schaltflächen entfernen möchten, können Siebutton:focus
es 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.
quelle
Das Entfernen
outline
ist 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.
quelle
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.quelle
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.
quelle
&: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
:focus
Status beim Klicken ausgelöst wird, da sich die Maus über dem Element befinden muss, um darauf zu klicken.https://codepen.io/heyvian/pen/eopOxr
quelle
UPDATE 2020
:focus-visible
ist in stabilem Chrome gelandet. Benutze es einfach schon!ORIGINAL POST
Bis
:focus-visible
es 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: coarse
Medienabfrage 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-visible
wird es also die bessere Lösung sein, aber im Moment sollte dies ausreichen.quelle
pointer: coarse
Bit. 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).:focus-visible
sie 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.:focus-visible
ist in Chrome implementiert. Wichtiger Meilenstein!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"); }
quelle
Die blueprintjs Bibliothek hat dafür eine gute Lösung.
https://blueprintjs.com/docs/#core/accessibility
Ich konnte jedoch noch nicht verstehen, wie sie es geschafft haben.
quelle