我想在:focus
不需要时禁用它,因为我不喜欢焦点放在导航上时的外观。它使用与相同的样式,.active
并且令人困惑。但是我不想为使用键盘的人摆脱它。
我当时想enabled-focus
在按Tab时在正文上添加一个类,然后添加一个类,body.enabled-focus a:focus{...}
但这将为每个具有焦点的元素添加很多额外的CSS。然后,首先将鼠标从身体上移开该类。
我将如何处理?有更好的解决方案吗?
我想在:focus
不需要时禁用它,因为我不喜欢焦点放在导航上时的外观。它使用与相同的样式,.active
并且令人困惑。但是我不想为使用键盘的人摆脱它。
我当时想enabled-focus
在按Tab时在正文上添加一个类,然后添加一个类,body.enabled-focus a:focus{...}
但这将为每个具有焦点的元素添加很多额外的CSS。然后,首先将鼠标从身体上移开该类。
我将如何处理?有更好的解决方案吗?
Answers:
这种优良制品由罗马科马罗夫构成用于实现可行的解决方案仅键盘聚焦样式为按钮,链接及其它容器元件,例如跨度或div的(其是人工制造可对焦用的tabindex属性)
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将运行。
这是一个演示,表明确实是这种情况,请注意,尽管您仅免费获得了固有交互元素(例如按钮和链接)(例如,跨度-您需要手动进行编码:)
注意:
1)尽管这似乎是一个过于复杂的解决方案,但是对于非JavaScript解决方案而言,它确实令人印象深刻。简单的纯css的“解决方案”:hover
和:active
伪类样式都根本不起作用。(当然,除非您假设交互式元素在单击时像模态提示中的按钮一样立即消失)
2)此解决方案并不完美:Windows上的Firefox仍将获得单击按钮的焦点样式-但这似乎是Firefox的错误(请参阅文章)
3)当浏览器实现:focus-ring伪类时-这个问题可能有一个更简单的解决方案-(请参阅文章)对于它的价值,这里有一个polyfill用于:focus-ring
-参见Chris DeMars的本文。
因此,实现仅键盘的焦点样式非常困难。一种更简单且可能既满足设计师的期望又可以访问的替代方法/解决方法是将样式设置为焦点,就像为悬停样式一样。
因此,尽管从技术上讲这不是在实现仅键盘样式,但从本质上讲,它消除了对仅键盘样式的需要。
:not(:hover):focus
选择器似乎可以解决问题。
:not(:hover):focus
由于上面描述的问题,@ wegry并不是一个很好的解决方案:“一旦悬停,就可以重新获得焦点样式-因为它仍然处于焦点状态(至少在按钮和可聚焦范围方面)”
Facebook现在(2018年6月)在其登录页面上使用了少量Javascript。
Javascript检测用户何时单击鼠标或使用键盘,并在主体上打开和关闭类: <body class="using-mouse">
然后CSS规则可以使用该类在相关元素上显示或隐藏适当的焦点样式。
这是一些示例代码(也可以在CodePen上获得)。比较点击和制表。
// 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>
请注意,:focus
上述等效于*:focus
,匹配所有元素。如果只想从按钮中删除样式,则可以放在button:focus
那里。
另外,当时的GMail只是给焦点对准的按钮设计比没有焦点对准的按钮更重的阴影,而不管用户是使用鼠标还是键盘。
这很容易实现和理解,不需要任何Javascript。
:focus {
outline: none;
box-shadow: 0 0px 16px #0005;
}
但这是一个折衷。它传达的焦点信息是鼠标用户并不真正感兴趣的信息,对于键盘用户来说可能有些微妙。
不过,这种折衷方案可能比其中一种极端情况要好(对所有用户来说都是很强的轮廓,或者根本没有轮廓)。
StackOverflow的主要按钮使用与GMail类似的方法,但外观更具风格:
box-shadow: inset 0 1px 0 0 rgba(102,191,255,0.5), 0 0 0 4px rgba(0,149,255,0.15);
就个人而言,我会使用更强(对比度更高)的颜色以实现可访问性。
拆卸outline
很容易造成伤害!理想情况下,仅当用户打算使用键盘时才会显示聚焦环。
2018年答案:使用:focus-visible。目前,这是W3C提案,旨在使用CSS设置仅键盘焦点的样式。在主流浏览器支持之前,您可以使用此强大的polyfill。不需要添加额外的元素或更改tabindex
。
/* Remove outline for non-keyboard :focus */
*:focus:not(.focus-visible) {
outline: none;
}
/* Optional: Customize .focus-visible */
.focus-visible {
outline-color: lightgreen;
}
我还写了一篇更详细的文章,以防万一您需要更多信息。
这是您可能会遇到很多的问题。这些问题的好处是,一旦找到解决方案,它就不会再打扰您了。
最优雅的解决方案似乎是最简单的解决方案:不要删除:focus上的轮廓,而要使用:active代替它–毕竟,:active是动态伪类,用于显式处理当单击或激活了可聚焦元素。
a:hover, a:active { outline: none; }
此方法的唯一小问题:如果用户激活链接然后使用浏览器的后退按钮,则轮廓将可见。哦,众所周知,旧版本的Internet Explorer被:focus,:hover和:active的确切含义弄糊涂了,因此该方法在IE6及以下版本中失败。
Tipp
有一个简单的解决方法,通过添加一个simple来防止轮廓“溢出” overflow:hidden
,从而使轮廓始终围绕元素本身的可单击部分进行检查。
在研究Danield接受的解决方案时,我发现了基于内部/外部div概念的另一种更简单的方法。
1)创建一个外部和内部元素。给外部元素tabindex =“ 0”和内部元素tabindex =“-1”
<div role="button" class="outer" tabindex="0">
<span class="inner" tabindex="-1">
I'm a button!
</span>
</div>
2)在CSS中,聚焦时从内部元素中删除轮廓:
.inner:focus{
outline: none;
}
3)将任何鼠标或单击事件处理程序应用于内部元素。将任何焦点事件(onfocus,onblur,onkeydown)应用于外部元素。
例如:
<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>
**保持尺寸和位置,以使内部元件与外部元件完全重叠。在外部元素上放置带有样式的整个“按钮”。
工作原理:
当用户单击“按钮”时,他们正在单击已删除焦点轮廓的内部元素。由于外部元素被内部元素覆盖,因此无法单击外部元素。当用户使用键盘将标签切换到“按钮”时,他们会到达外部元素(tabindex =“ 0”使该元素可通过“ tab”访问),该元素会获得焦点轮廓,但内部元素则无法通过标签(带有tabindex =“-1”),并且单击时不会收到焦点轮廓。
&:focus:not(:hover) { }
它不能在100%的情况下起作用,但是我认为对于大多数人来说这应该足够了。
这将防止:focus
在单击时触发状态,因为鼠标必须悬停在(悬停)元素上才能单击它。
:focus-visible
已登陆稳定的Chrome。就已经使用了!
:focus-visible
在所有流行的常绿浏览器中都没有这种方法之前,您可以在CSS的全局部分使用此简单技巧,而无需任何polyfill:
@media (pointer: coarse) {
*:focus {
outline: none;
}
}
然后使用通常的方法添加焦点效果:focus
。
在这一点上,您可能已经了解到,outline: none;
从可访问性的角度来看,默认情况下将焦点设置为焦点元素是一个可怕的想法。确实是这样。
但是,如果在pointer: coarse
媒体查询中将此规则作为范围,它将非常有用,因为它仅适用于手机和平板电脑,不适用于台式机。这正是您想要实现的目标。
我能想到的唯一问题是带有键盘的移动用户,他们使用它们来浏览内容,但是我不确定是否有很多这样的用户。因此,最终:focus-visible
将是更好的解决方案,但就目前而言,这已经足够了。
pointer: coarse
一点。这是一种仅在移动设备(电话,平板电脑或没有精细定位设备(例如鼠标或触摸板/触控板)的设备)上隐藏焦点轮廓的解决方法。
:focus-visible
在主要浏览器中实现之前寻求实用解决方案的人们来说,这更像是一种解决方法。这是正确的,因为答案并不能解决问题中列出的所有问题,在这种情况下,您可以正确地投票否决-不会冒犯。
:focus-visible
已在Chrome中实现。重要的里程碑!
没有明确的解决方案。我已经完成了一种Hackish解决方案:在您的主容器上应用click事件,并在click上编写以下代码
_handleMouseClick = (event) => {
if(event.detail){
document.activeElement.blur();
}
}
当您使用鼠标单击时,将获得event.detail = 1,使该元素模糊,以便删除轮廓;在键盘单击时,我们将得到event.detail = 0,因此在键盘情况下表现正常
要么
在css文件中
body.disableOutline *:focus{
outline: none !important;
}
在主要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");
}
addClass()
要具有该焦点样式的元素。