一尘不染

启用:仅专注于键盘使用(或按Tab键)

css

我想在:focus不需要时禁用它,因为我不喜欢焦点放在导航上时的外观。它使用与相同的样式.active并且令人困惑。但是我不想为使用键盘的人摆脱它。

我当时想enabled-focus在按Tab时在正文上添加一个类,然后添加一个类,body.enabled-focus a:focus{...}但这将为每个具有焦点的元素添加很多额外的CSS。然后,首先将鼠标从身体上移开该类。

我将如何处理?有更好的解决方案吗?


阅读 223

收藏
2020-05-16

共1个答案

一尘不染

这种优良制品由罗马科马罗夫构成用于实现可行的解决方案 仅键盘聚焦样式按钮链接
及其它容器元件,例如 跨度div的 (其是人工制造可对焦用的tabindex属性)

解决方案:

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>

码笔

1)将原始交互元素的内容包装在另一个内部元素中tabindex="-1"(请参见下面的说明)

因此,与其说:

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

做这个:

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

2)将CSS样式移至内部元素(布局CSS应保留在原始外部元素上)-这样外部元素的宽度/高度将来自内部元素等。

3)从外部和内部元素中删除默认的焦点样式:

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

4) 仅当 外部元素具有焦点 将焦点样式添加回内部元素:

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

为什么这样做?

这里的技巧是使用tabindex="-1"- 设置MDN设置内部元素:

负值(通常为tabindex =“-1”表示该元素应可聚焦,但不应通过顺序键盘导航来访问…

因此,该元素 通过单击鼠标或以编程方式进行 聚焦 ,但另一方面-无法通过键盘的“选项卡”访问。

因此,当单击交互式元素时, 内部元素 将获得焦点。由于我们已删除焦点样式,因此不会显示。

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

请注意, 在给定的时间只能集中1个DOM元素 (并document.activeElement返回此元素)-因此,
内部元素将被聚焦。

另一方面:当我们使用键盘进行制表时- 只有外部元素会获得焦点 (请记住:内部元素具有tabindex
=“-1”并且无法通过顺序键盘导航访问)[请注意,对于固有的非可聚焦的外部元素(如可点击的元素)<div>-我们必须通过添加tabindex="0"]
人为地使其变得可聚焦

现在,我们的CSS开始运行,并向中添加了仅键盘的焦点样式the inner element

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

当然,我们要确保当我们点击并按下时enter-我们没有破坏我们的交互元素,并且javascript将运行。

这是一个演示,确实是这种情况的演示,请注意,尽管您仅免费获得了固有交互元素(例如按钮和链接)(例如,跨度-您需要手动进行编码:)

//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>

码笔


注意:

1)尽管这似乎是一个过于复杂的解决方案,但对于非JavaScript解决方案而言,它确实令人印象深刻。简单的纯css的“解决方案”
:hover:active伪类样式都根本不起作用。(当然,除非您假设交互元素在单击时像模态提示中的按钮一样立即消失)

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>

码笔

2)此解决方案并不完美:Windows上的Firefox仍将获得单击按钮的焦点样式-
但这似乎是Firefox的错误(请参阅文章

3)当浏览器实现:focus-ring伪类时-可能有一个更简单的解决方案-对于它的价值,这里有一个polyfill用于:focus-ring-参见Chris DeMars的本文。


实用的替代仅键盘的焦点样式

因此,实现仅键盘的焦点样式非常困难。一种 更简单 且可能既满足设计师的期望又可以访问的替代方法/解决方法是,将样式设置为焦点,就像悬停样式一样。

码笔

因此,尽管从技术上讲这不是在实现仅键盘样式,但从本质上讲,它消除了对仅键盘样式的需要。

2020-05-16