Включить: сфокусируйтесь только на использовании клавиатуры (или нажмите клавишу)
Я хочу отключить :focus
когда это не нужно, потому что мне не нравится, как выглядит моя навигационная система, когда фокус на ней. Он использует тот же стиль, что и .active
и это запутывает. Однако я не хочу избавляться от него для людей, которые используют клавиатуру.
Я думал добавить класс с enabled-focus
на тело при нажатии табуляции, а затем body.enabled-focus a:focus{...}
но это добавит много дополнительного CSS для каждого элемента, который имеет фокус. Затем удалите этот класс из тела при первой мыши вниз.
Как я могу это сделать? Есть ли лучшее решение?
Ответы
Ответ 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> 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>
Ответ 2
Пример из практики: страница входа в Facebook
Facebook использует чуть-чуть Javascript на своей странице входа в систему (июнь 2018 года).
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');
});
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 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>
Ответ 3
Удаление outline
ужасно для доступности! В идеале кольцо фокусировки появляется только тогда, когда пользователь намеревается использовать клавиатуру.
2018 Ответ: Использование : видимый фокус. В настоящее время это предложение W3C для стилизации фокуса только на клавиатуре с использованием CSS. Пока основные браузеры не поддерживают его, вы можете использовать этот надежный полифилл. Не требует добавления дополнительных элементов или изменения tabindex
.
/* Remove outline for non-keyboard :focus */
*:focus:not(.focus-visible) {
outline: none;
}
/* Optional: Customize .focus-visible */
.focus-visible {
outline-color: lightgreen;
}
Я также написал более подробный пост на всякий случай, если вам нужно больше информации.
Ответ 4
Это проблема, с которой вам, вероятно, придется столкнуться. Хорошая вещь о таких проблемах - если вы когда-нибудь найдете решение, это вас больше не беспокоит.
Самое элегантное решение кажется самым простым: не удаляйте схему: focus, сделайте это: active вместо этого - в конце концов: active - это динамический псевдокласс, который явно ссылается на стили, которые должны применяться, когда фокусируемый элемент нажата или активирована иным образом.
a:hover, a:active { outline: none; }
Единственные незначительные проблемы с этим методом: если пользователь активирует ссылку и затем использует кнопку возврата к браузеру, контур становится видимым. Ох, и старые версии Internet Explorer заведомо путаются с точным значением: focus,: hover и: active, поэтому этот метод терпит неудачу в IE6 и ниже.
Типп
Существует тривиальное обходное решение для предотвращения контуров от " overflow:hidden
" путем добавления простого overflow:hidden
, что позволяет проверять контур вокруг кликабельной части самого элемента.
Ответ 5
Играя с принятым решением 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") и не получает схему фокусировки при нажатии.
Ответ 6
Нет четкого решения. Я сделал одно решение Hackish: примените событие 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");
}
Ответ 7
&:focus:not(:hover) { }
Это не будет работать в 100% случаев, но я думаю, что для большинства людей этого должно быть достаточно.
Это предотвратит срабатывание :focus
состояния при щелчке, потому что мышь должна находиться над элементом мыши, чтобы щелкнуть по нему.
https://codepen.io/heyvian/pen/eopOxr