我想在不需要的时候禁用:focus
,因为我不喜欢焦点放在它上时导航的外观.它使用与.active
相同的风格,而且令人困惑.不过,我不想为使用键盘的人go 掉它.
我想在Tab键上的Body上添加一个类enabled-focus
,然后有body.enabled-focus a:focus{...}
个,但这会 for each 有焦点的元素添加很多额外的CSS.然后在第一次按下鼠标时将该类从主体中移除.
我该怎么做呢?有没有更好的解决方案?
我想在不需要的时候禁用:focus
,因为我不喜欢焦点放在它上时导航的外观.它使用与.active
相同的风格,而且令人困惑.不过,我不想为使用键盘的人go 掉它.
我想在Tab键上的Body上添加一个类enabled-focus
,然后有body.enabled-focus a:focus{...}
个,但这会 for each 有焦点的元素添加很多额外的CSS.然后在第一次按下鼠标时将该类从主体中移除.
我该怎么做呢?有没有更好的解决方案?
other0other02提到了:focus-visible
伪类-现在有像样的browser support.
我想补充的是,在spec which covers the :focus-visible pseudo class的基础上,浏览器现在应该只有indicate focus个,当它对用户有帮助时-例如在用户通过键盘或其他非定点设备与页面交互的情况下
这基本上意味着原始问题不再相关,因为现在,当用户单击/点击按钮(或其他可聚焦元素)时,用户代理将不再显示聚焦环——即使按钮已聚焦——因为在这种情况下,聚焦环对用户没有帮助.
从the spec开始:
而:focus伪类始终与当前聚焦的
事实上,从90版开始,Chromium的用户代理样式表从:focus
切换到:focus-visible,并且由于这种更改,点击按钮不再调用焦点环
此外,在version 87版本中,Firefox还在其用户代理风格上使用:Focus-Visible.
话虽如此,如果需要自定义焦点样式,因为焦点样式现在已经从:focus
变为:focus-visible
,所以当用自定义焦点样式覆盖默认样式时-应该使用:focus-visible
伪类.
比如:
button:focus-visible {
/* remove default focus style */
outline: none;
/* custom focus styles */
box-shadow: 0 0 2px 2px #51a7e8;
color: lime;
}
像这样使用:Focus-Visible可能存在的问题是,不支持:focus-visible
的浏览器将显示默认的焦点环,根据设计的不同,默认的焦点环可能不清晰或不可见.
Šime Vidas在this article年中描述了一种可行的策略,目前使用:focus visible伪类,即使在尚不支持:focus visible的浏览器中也可以使用-
开始使用的一个好方法是:定义焦点
不支持:Focus-Visible的浏览器使用Focus样式 在:Focus规则中定义,并完全忽略第二个样式规则 (因为:焦点-可见对他们来说是未知的).
在支持"焦点可见"的浏览器中,第二个样式规则
button:focus {
outline: none;
background: #ffdd00; /* gold */
}
button:focus:not(:focus-visible) {
background: white; /* undo gold */
}
This excellent articlexRoman Komarov为实现buttons、links和其他容器元素(如spans或divs)(通过tabindex属性人工设置为可聚焦)实现keyboard-only focus styles提供了一个可行的解决方案
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>
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>
将CSS样式移至内部元素(布局CSS应保留在原始外部元素上)-因此外部元素的宽度/高度来自内部元素,依此类推.
从外部和内部元素中删除默认焦点样式:
.btn:专注,
将焦点样式添加回内部元素only when.外部元素具有焦点:
.btn:焦点>;.btn__内容{ 方框阴影:0 0 2px 2px#51a7e8;/*纯键盘聚焦样式/ color: lime; /纯键盘聚焦样式*/ }
这里的诀窍是将内部元素设置为tabindex="-1"
-请参见MDN:
负值(通常为tabindex="-1"表示元素应 可聚焦,但不能通过顺序键盘到达 导航.
所以元素是focusable,通过鼠标点击或编程,但另一方面-它不能通过键盘的"制表符"到达.
因此,当点击交互元素时,inner element将获得焦点.不会显示焦点样式,因为我们已删除它们.
.btn:focus,
.btn__content:focus {
outline: none;
}
请注意,only 1 DOM element can be focused at a given time(document.activeElement
返回此元素)-因此only内部元素将成为焦点.
另一方面:当我们使用键盘-only the outer element will get the focus进行制表符时(请记住:内部元素的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
键时,我们没有 destruct 我们的交互元素,javascript将运行.
这里有一个演示来证明事实的确如此,不过请注意,你只能免费获得(即按Enter键导致点击事件),用于按钮和链接等固有的交互元素.对于其他元素(如跨度),您需要手动编码:)
//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>
NB:个
: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>
这个解决方案并不完美:Windows上的Firefox仍然会在点击时获得按钮的焦点样式-但这似乎是Firefox的一个错误(参见the article)
当浏览器实现:focus-ring个伪类时-这个问题可能有一个简单得多的解决方案-(参见the article)
不管它值多少钱,:focus-ring
比a polyfill--见this article by Chris DeMars
因此,实现只使用键盘的焦点样式是出人意料的困难.一种替代/变通方法是much simpler,它既可以满足设计者的期望,又可以使用--就像设计悬停时的样式一样聚焦于样式.
因此,虽然从技术上讲,这并不是实现仅键盘样式,但它基本上消除了对仅键盘样式的需要.