我想在:focus不需要时禁用它,因为我不喜欢焦点放在导航上时的外观。它使用与相同的样式.active并且令人困惑。但是我不想为使用键盘的人摆脱它。
:focus
.active
我当时想enabled-focus在按Tab时在正文上添加一个类,然后添加一个类,body.enabled-focus a:focus{...}但这将为每个具有焦点的元素添加很多额外的CSS。然后,首先将鼠标从身体上移开该类。
enabled-focus
body.enabled-focus a:focus{...}
我将如何处理?有更好的解决方案吗?
这种优良制品由罗马科马罗夫构成用于实现可行的解决方案 仅键盘聚焦样式 为 按钮 , 链接 及其它容器元件,例如 跨度 或 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"(请参见下面的说明)
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”表示该元素应可聚焦,但不应通过顺序键盘导航来访问…
因此,该元素 可 通过单击鼠标或以编程方式进行 聚焦 ,但另一方面-无法通过键盘的“选项卡”访问。
因此,当单击交互式元素时, 内部元素 将获得焦点。由于我们已删除焦点样式,因此不会显示。
请注意, 在给定的时间只能集中1个DOM元素 (并document.activeElement返回此元素)-因此, 仅 内部元素将被聚焦。
document.activeElement
另一方面:当我们使用键盘进行制表时- 只有外部元素会获得焦点 (请记住:内部元素具有tabindex =“-1”并且无法通过顺序键盘导航访问)[请注意,对于固有的非可聚焦的外部元素(如可点击的元素)<div>-我们必须通过添加tabindex="0"] 人为地使其变得可聚焦
<div>
tabindex="0"
现在,我们的CSS开始运行,并向中添加了仅键盘的焦点样式the inner element。
the inner element
当然,我们要确保当我们点击并按下时enter-我们没有破坏我们的交互元素,并且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>
注意:
1)尽管这似乎是一个过于复杂的解决方案,但对于非JavaScript解决方案而言,它确实令人印象深刻。简单的纯css的“解决方案” :hover和:active伪类样式都根本不起作用。(当然,除非您假设交互元素在单击时像模态提示中的按钮一样立即消失)
: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的本文。
:focus-ring
因此,实现仅键盘的焦点样式非常困难。一种 更简单 且可能既满足设计师的期望又可以访问的替代方法/解决方法是,将样式设置为焦点,就像悬停样式一样。
因此,尽管从技术上讲这不是在实现仅键盘样式,但从本质上讲,它消除了对仅键盘样式的需要。