it-swarm.com.de

Aktivieren: Nur auf die Verwendung der Tastatur fokussieren

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

Ich habe mir überlegt, eine Klasse enabled-focus auf dem Hauptteil der Tabulatortaste hinzuzufügen und dann body.enabled-focus a:focus{...} zu verwenden, aber das würde eine Menge zusätzlicher CSS für jedes Element hinzufügen, das den Fokus hat. Entfernen Sie dann diese Klasse aus dem Körper, wenn Sie die Maus mit der Maus nach unten bewegen.

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

26
Miro

Dieser ausgezeichnete Artikel by Roman Komarov ist eine praktikable Lösung, um keyboard-only-Fokusstile für buttons, links und andere Containerelemente wie z als Spannweiten oder Divs (die künstlich mit dem tabindex-Attribut fokussierbar gemacht werden können) 

Die Lösung:

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) Packen 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 zum inneren Element (Layout css sollte auf dem ursprünglichen äußeren Element bleiben) - so kommen Breite/Höhe des äußeren Elements aus dem inneren Element usw.

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

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

4) Füge das Fokus-Styling wieder dem inneren Element hinzu nur 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 Tastatur erreichbar ist. Navigation. ...).

Das Element ist also per Mausklick oder programmgesteuert fokussierbar, aber andererseits - es ist nicht über Tastatur-Tabs erreichbar. 

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 nur 1 DOM-Element zu einem bestimmten Zeitpunkt fokussiert werden kann (und document.activeElement gibt dieses Element zurück). Daher wird nur das innere Element only fokussiert.

Auf der anderen Seite: Wenn wir mit der Tastatur tippen - erhält nur das äußere Element den Fokus (Denken Sie daran: das innere Element hat tabindex = "- 1" und ist nicht über die sequentielle Tastaturnavigation erreichbar.) [Beachten Sie das für inhärent nicht fokussierbare äußere Elemente wie einen anklickbaren <div> - wir müssen sie künstlich fokussierbar machen, indem Sie tabindex="0" hinzufügen.] 

Jetzt setzt unser CSS ein und fügt the inner element die ausschließlich für die Tastatur bestimmten Fokusstile hinzu.

.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, wenn wir auf enter tippen und drücken, unser interaktives Element nicht gebrochen 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 kostenlos erhalten (dh drücken Sie die Eingabetaste, um ein Klickereignis zu verursachen) für inhärent interaktive Elemente, wie z. Sie müssen das manuell codieren :)

//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 wie eine zu komplizierte Lösung erscheint, ist es für Nicht-Javascript-Lösungen wirklich beeindruckend. Einfachere "Nur-Lösungen" -Lösungen mit :hover und :active Pseudo-Klassen-Styling funktionieren einfach nicht. (es sei denn, Sie gehen natürlich davon aus, dass das interaktive Element sofort beim Klicken wie eine Schaltfläche innerhalb eines modalen Sprichworts verschwindet.) 

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 immer noch Fokusstile für Schaltflächen beim Klicken. Dies scheint jedoch ein Firefox-Fehler zu sein (siehe den Artikel ). 

3) Wenn Browser die : focus-ring pseudo-Klasse implementieren, gibt es möglicherweise eine viel einfachere Lösung für dieses Problem - (siehe den Artikel ) Was es wert ist, ist a polyfill für :focus-ring - siehe diesen Artikel von Chris DeMars


Eine pragmatische Alternative zu den nur für Tastatur bestimmten Fokusstilen

Daher ist es überraschend schwierig, nur Tastaturstile zu erreichen. Eine Alternative/Workaround, die viel einfacher ist und sowohl die Erwartungen des Designers erfüllen kann als auch zugänglich ist - wäre, den Fokus so zu gestalten, wie Sie es für den Schwebeflug tun würden. 

Codepen

Auch wenn dies technisch nicht nur für Styles der Tastatur implementiert ist, sind im Wesentlichen nur Styles für die Tastatur erforderlich.

33
Danield

Fallbeispiel: Facebook-Anmeldeseite

Facebook verwendet momentan ein kleines bisschen Javascript auf ihrer Anmeldeseite (Juni 2018).

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

Anschließend können CSS-Regeln diese Klasse verwenden, um den entsprechenden Fokusstil der relevanten Elemente anzuzeigen oder auszublenden.

Hier ist ein Beispielcode (auch verfügbar on CodePen ):

// Let the document know when the mouse is being used
document.body.addEventListener('mousedown', function() {
  document.body.classList.add('using-mouse');
});
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. */
/* You could apply this selector only to buttons, if you wanted. */
body.using-mouse :focus {
  outline: none;
}
<input>
<button>Submit</button>


Fallbeispiel: GMail-Login-Seite

Alternativ gestaltet GMail nur fokussierte Tasten mit einem stärkeren Schatten als unkonzentrierte Tasten, unabhängig davon, ob sich der Benutzer auf der Maus oder auf der Tastatur befindet.

Dies ist konsistent, einfacher zu implementieren und zu testen und erfordert kein Javascript.

Aber es ist ein Kompromiss. Es vermittelt Fokusinformationen, an denen Mausbenutzer nicht wirklich interessiert sind, und es ist wohl ein bisschen too subtil für Tastaturbenutzer.

Dennoch ist dieser Kompromiss viel besser als eines der Extreme (überall eine starke Kontur oder überhaupt keine Kontur).

16
joeytwiddle

outline zu entfernen ist schrecklich für die Zugänglichkeit! Im Idealfall wird der Fokusring nur angezeigt, wenn der Benutzer die Tastatur verwenden möchte.

2018 Antwort: Verwenden Sie : Fokus sichtbar . Es ist derzeit ein Vorschlag des W3C, nur den Tastaturfokus mit CSS zu gestalten. Solange wichtige Browser dies nicht unterstützen, können Sie dieses robuste polyfill verwenden. Es ist nicht erforderlich, zusätzliche Elemente hinzuzufügen oder tabindex zu ändern.

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

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

Ich habe auch ein ausführlicheres post geschrieben, falls Sie weitere Informationen benötigen. 

12

Dies ist ein Problem, dem Sie wahrscheinlich viel begegnen werden. Das Gute an solchen Problemen ist, wenn Sie einmal eine Lösung finden, wird es Sie nicht mehr stören.

Die eleganteste Lösung scheint die einfachste zu sein: Entfernen Sie die Gliederung nicht: Fokus, tun Sie es auf: Aktiv stattdessen - Aktiviert schließlich: Aktiv ist die dynamische Pseudoklasse, die sich explizit mit den Stilen befasst, die angewendet werden sollen, wenn a Das fokussierbare Element wird angeklickt oder auf andere Weise aktiviert.

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

Das einzige kleinere Problem bei dieser Methode: Wenn ein Benutzer einen Link aktiviert und dann die Zurück-Schaltfläche des Browsers verwendet, wird die Gliederung sichtbar. Oh, und alte Versionen von Internet Explorer werden verwirrt durch die genaue Bedeutung von: focus,: hover und: active verwirrt. Diese Methode schlägt daher im IE6 und darunter fehl.

Tipp

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

11
Jeremy Zahner

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

1) Erstellen Sie ein äußeres und ein 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 in der CSS die Kontur aus dem inneren Element, wenn Sie fokussiert sind:

.inner:focus{
    outline: none;
}

3) Wenden Sie beliebige Maus- oder Klick-Ereignishandler 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>

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

Wie das funktioniert:

Wenn der Benutzer auf die "Schaltfläche" klickt, klickt er auf das innere Element, dessen Fokusumriss entfernt wurde. Es ist nicht möglich, das äußere Element anzuklicken, da es vom inneren Element verdeckt wird. Wenn der Benutzer die Tastatur verwendet, um zur "Schaltfläche" zu wechseln, gelangen Sie zum äußeren Element (tabindex = "0" macht das Element mit "tab" erreichbar), das eine Fokusumrisslinie erhält, das innere Element ist jedoch nicht über das Symbol erreichbar tab (mit tabindex = "- 1") und erhält beim Klicken keine Fokuskontur.

3
nutsandbolts
&:focus:not(:hover) { }

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

Es wird verhindern, dass die :focus Status wird beim Klicken ausgelöst, da sich die Maus über dem Element befinden muss, um darauf zu klicken.

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

1

Es gibt keine klare Lösung. Ich habe eine Hackish-Lösung gemacht:. Klicken Sie auf das Ereignis "Ereignis" in Ihrem Hauptcontainer, und geben Sie den folgenden Code ein

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

Wenn Sie mit der Maus klicken, erhalten Sie event.detail = 1. Klicken Sie auf das Element. Verwischen Sie das Element, sodass die Umrisslinie entfernt wird Wenn Sie auf die Tastatur klicken, wird event.detail = 0 angezeigt 

OR

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");
            }
0
pareshm