Щелчок в iOS Safari запускает "состояние зависания" на элементе под тем, где вы прослушивали
В iOS Safari (я не думаю, что имеет значение, какая версия iOS, но я тестирую на iOS (Safari) 11), если у меня есть <div>
, расположенный над элементом, который имеет эффект :hover
, а <div>
имеет событие, которое заставляет его исчезать при нажатии, тогда моя ссылка "внизу" получает эффект зависания, применяемый после удаления элемента из DOM.
См. ниже для анимированного GIF того, что я говорю:
![iOS click through]()
Я дал кнопке прозрачный фон, чтобы вы могли видеть ссылку позади нее. Когда я нажимаю кнопку на месте, где находится ссылка не, ссылка (т.е. Some link
) остается синей и не меняется на ее кратковременное состояние.
Однако, когда я нажимаю div
в месте, которое происходит непосредственно по ссылке, после удаления div
из DOM, ссылка получает свое зависающее состояние.
Щелчок по ссылке после каждого из них правильно запускает событие on.click
(окно предупреждения).
Я не вижу эту проблему в android в Chrome (см. пример ниже):
![Android click through working]()
Ниже вы также найдете образец HTML/CSS/JS, который я использовал; настройка довольно проста.
Я бы хотел, чтобы iOS действовал так же, как Android Chrome: щелчок по элементу, который сразу же удаляется из DOM, не должен запускать состояние :hover
для элемента сразу за ним.
document.addEventListener("DOMContentLoaded", function ready() {
var button = document.querySelector(".button");
button.addEventListener("click", function() {
button.parentNode.removeChild(button);
});
document.querySelector('a').addEventListener("click", function() {
window.alert('clicked!');
});
});
a:link { color: blue }
a:visited { color: blue }
a:hover { color: red }
a:active { color: green }
.button {
background: rgba(100, 0, 0, .4);
position: absolute;
top: 2px;
left: 2px;
z-index: 1;
width: 100px;
height: 100px;
line-height: 100px;
text-align: center;
border-radius: 5px;
}
.button:hover {
background: rgba(0, 100, 0, .4);
cursor: pointer;
}
<a href="#">Some link</a>
<div class="button">Click me!</div>
Ответы
Ответ 1
Если у вас есть опция отключения зависания, вы можете сделать это с помощью взлома.
Сначала добавьте эту строку в обработчик событий DOMContentLoaded.
var canHover = !(matchMedia('(hover: none)').matches);
if (canHover) {
document.body.classList.add('can-hover');
}
Он добавит класс cancan в тело вашего html-документа.
Затем просто измените правило: hover, чтобы соответствовать этому вместо
ваше правило css:
a:hover {
color: red;
}
должен быть:
.can-hover a:hover {
color: red;
}
это должно помешать устройствам с сенсорным экраном применить стиль наведения к любому якорю.
Ответ 2
... можно ясно видеть, что это предполагаемое поведение на iOS, даже если вы просматриваете список элементов, зависящих от наведения.
Если то, что вы пытаетесь избежать, это просто эффект наведения, вот что я буду делать. Я бы получил устройство с помощью JS-функции, применил класс в теге body
и удалил любые зависающие эффекты по мере необходимости.
JavaScript:
function isAppleDevice() {
return (
(navigator.userAgent.toLowerCase().indexOf("ipad") > -1) ||
(navigator.userAgent.toLowerCase().indexOf("iphone") > -1) ||
(navigator.userAgent.toLowerCase().indexOf("ipod") > -1)
);
}
if (isAppleDevice() {
$('body').addClass('is_apple')
}
CSS
.is_apple a:hover {
// same styling as not hovering
}
Ответ 3
Пробовали ли вы использовать медиа-запрос для проверки возможности: hover?
См. https://drafts.csswg.org/mediaqueries/#hover
Ответ 4
Это, по-видимому, неотъемлемое дизайнерское решение в iOS (или, возможно, способ Chrome - это дизайнерское решение, сделанное ими, не может сказать). Кажется, iOS спроектирован так, чтобы быть "мышиным". Он даже бросает "мыши" на веб-страницы даже на сенсорных устройствах. Я пытался найти способ определить, есть ли у пользователя мышь, поэтому вы можете отключить эффекты зависания, если она есть, но я не могу найти ничего, что будет работать правильно.
Я думаю, что Windows делает то же самое с прикосновением. Прикосновение к точке эффективно перемещает указатель мыши и щелкает, оставляя указатель мыши.
Вы можете просто изменить свой дизайн, если это разблокировка сделки.
Ответ 5
Это похоже на намеренное поведение в Safari. Apple documentation говорит, что однодисковые метчики обрабатываются как события мыши и показывают, какие события возникают во время крана. Там mouseover
в начале нажатия, но mouseout
запускается только при нажатии на что-то еще. Это означает, что Safari предполагает, что указатель остается в одном месте до следующего крана, что будет означать, что нижний элемент имеет смысл в состоянии наведения.
Я пробовал свой код в Chrome на Android, а Chrome и Firefox в Windows (у меня нет устройства Apple). Во всех трех случаях, когда я нажимаю на <div>
с помощью мыши (по ссылке), стиль зависания применяется к ссылке позже, если только я не перемещаю курсор от ссылки до того, как я отпущу мышь. Если я коснувшись <div>
пальцем на сенсорном экране, ссылка не получит стиль наведения.
Firefox и Chrome, похоже, согласуются друг с другом для сенсорной и мыши, но Safari кажется (по дизайну) рассматривать сенсорный экран как мышь: он ведет себя так же, как для сенсорного нажатия, поскольку Chrome и Firefox делают для щелчок мыши.
Я не это, что это ошибка, которую нужно исправить или обойти. Если вы не знаете, что все ваши пользователи будут использовать определенную комбинацию оборудования/браузера, вам, вероятно, необходимо будет запланировать возможность того, что они могут использовать мышь, сенсорный экран или, возможно, оба одновременно; и разработать пользовательский интерфейс, который работает для всех этих случаев. У моего ноутбука Windows и Android-планшета есть мышиные коврики, а также сенсорные экраны, и я иногда использую мышь USB OTG с моим телефоном Android.
Вы также можете посмотреть API указателей проводок, который работает в Chrome, IE и Edge (не путать с pointer-events Свойство CSS, упомянутое в @erier). Поскольку API имеет дело с событиями, а не с CSS, это не будет напрямую способствовать правильному оформлению вашего стиля, но покажет, как прилагать усилия, чтобы браузеры последовательно реагировали на различные типы устройств ввода.
Ответ 6
Я думаю, что этот хак может работать.
Вам нужно отключить наведение с классом, и когда верхний div щелкнет, добавьте прослушиватель событий, который удалит класс блокировки зависания при перемещении мыши.
document.addEventListener("DOMContentLoaded", function ready() {
var button = document.querySelector(".button");
button.addEventListener("click", function() {
button.parentNode.removeChild(button);
var body = document.querySelector("body");
body.addEventListener("mousemove", function() {
var someLink = document.querySelector(".some-link");
someLink.classList.remove("no-hover");
});
});
document.querySelector('a').addEventListener("click", function() {
window.alert('clicked!');
});
});
a:link { color: blue }
a:visited { color: blue }
a:hover { color: red }
a:active { color: green }
a.no-hover:hover { color: blue }
.button {
background: rgba(100, 0, 0, .4);
position: absolute;
top: 2px;
left: 2px;
z-index: 1;
width: 100px;
height: 100px;
line-height: 100px;
text-align: center;
border-radius: 5px;
}
.button:hover {
background: rgba(0, 100, 0, .4);
cursor: pointer;
}
<a href="#" class="some-link no-hover">Some link</a>
<div class="button">Click me!</div>
Ответ 7
Использование указателей-событий может помочь здесь.
document.addEventListener("DOMContentLoaded", function ready() {
var button = document.querySelector(".button");
button.addEventListener("click", function() {
button.parentNode.removeChild(button);
});
document.querySelector('a').addEventListener("click", function() {
window.alert('clicked!');
});
});
a {pointer-events: none;}
a:link { color: blue; pointer-events: auto; }
a:visited { color: blue }
a:hover { color: red; pointer-events: auto; }
a:active { color: green; pointer-events: auto; }
.button {
background: rgba(100, 0, 0, .4);
position: absolute;
top: 2px;
left: 2px;
z-index: 1;
width: 100px;
height: 100px;
line-height: 100px;
text-align: center;
border-radius: 5px;
}
.button:hover {
background: rgba(0, 100, 0, .4);
cursor: pointer;
}
<a href="#">Some link</a>
<div class="button">Click me!</div>
Ответ 8
Я не знаю, будет ли это работать в вашем производственном коде, но это должно быть для этого примера.
Вы можете выплевывать правила наведения на класс и применять этот класс к ссылке в обратном вызове удаления кнопки после того, как вы отменили ее из DOM.
Если это все еще не работает, вы можете добавить класс в обратный вызов onmouseover
. Это будет работать только после удаления кнопки и после выхода (если необходимо) и повторного ввода ссылки.
Все это немного взломанно, но это позволит вам использовать поведение в любом браузере/ОС.
Ответ 9
Это проблема с браузерами. состояние зависания существует везде, даже если оно не должно быть.
Я бы добавил класс .no-touch
к телу и стилю только те.
if (!("ontouchstart" in document.documentElement)) {
document.body.classList.add('no-touch')
}
Здесь все вместе
if (!("ontouchstart" in document.documentElement)) {
document.body.classList.add('no-touch')
}
document.addEventListener("DOMContentLoaded", function ready() {
var button = document.querySelector(".button");
button.addEventListener("click", function(e) {
button.parentNode.removeChild(button);
});
document.querySelector('a').addEventListener("click", function() {
window.alert('clicked!');
});
});
a:link { color: blue }
a:visited { color: blue }
.no-touch a:hover { color: red }
a:active { color: green }
.button {
background: rgba(100, 0, 0, .4);
position: absolute;
top: 2px;
left: 2px;
z-index: 1;
width: 100px;
height: 100px;
line-height: 100px;
text-align: center;
border-radius: 5px;
}
.button:hover {
background: rgba(0, 100, 0, .4);
cursor: pointer;
}
<a href="#">Some link</a>
<div class="button">Click me!</div>