Я пишу веб-сайт, предназначенный для использования как с настольных компьютеров, так и с планшетов. Когда его посещают с рабочего стола, я хочу, чтобы интерактивные области экрана подсвечивались :hover
эффектами (разным цветом фона и т. Д.). На планшете нет мыши, поэтому я не хочу никаких эффектов наведения.
Проблема в том, что когда я нажимаю что-то на планшете, в браузере, очевидно, есть какой-то «невидимый курсор мыши», который перемещается в место, которое я коснулся, а затем оставляет его там, поэтому то, что я только что коснулся, загорается эффект наведения, пока я не коснусь чего-нибудь еще.
Как мне получить эффекты наведения, когда я использую мышь, но подавить их, когда я использую сенсорный экран?
Если кто-то думал об этом, я не хочу использовать сниффинг пользовательского агента. Одно и то же устройство может иметь как сенсорный экран, так и мышь (возможно, сегодня это не так распространено, но в будущем станет еще больше). Устройство меня не интересует, меня интересует, как оно сейчас используется: мышь или тачскрин.
Я уже пытался зацепить touchstart
, touchmove
и touchend
событие , и призывая preventDefault()
на всех из них, что делает подавляющий «невидимый курсор мыши» некоторое время; но если я быстро нажимаю вперед и назад между двумя разными элементами, после нескольких нажатий он все равно начнет перемещать «курсор мыши» и зажигать эффекты наведения - это как будто меня preventDefault
не всегда уважают. Я не буду утомлять вас подробностями, если в этом нет необходимости - я даже не уверен, что это правильный подход; если у кого есть исправление попроще, я весь уши.
Изменить: это можно воспроизвести с помощью стандартного CSS :hover
, но вот краткое воспроизведение для справки.
<style>
.box { border: 1px solid black; width: 150px; height: 150px; }
.box:hover { background: blue; }
</style>
<div class="box"></div>
<div class="box"></div>
Если вы наведете курсор мыши на любой из полей, он получит синий фон, который я хочу. Но если вы нажмете на любой из полей, он также получит синий фон, что я пытаюсь предотвратить.
Я также отправил образец здесь , что делает выше , а также перехватывает события мыши JQuery в. Вы можете использовать его, чтобы увидеть, что события касания также срабатывают mouseenter
, mousemove
и mouseleave
.
источник
Ответы:
Я понял из вашего вопроса, что ваш эффект наведения меняет содержимое вашей страницы. В таком случае мой совет:
touchstart
иmouseenter
.mouseleave
,touchmove
иclick
.Кроме того, вы можете отредактировать свою страницу, чтобы не было изменения содержимого.
Задний план
Чтобы имитировать мышь, браузеры, такие как Webkit Mobile, запускают следующие события, если пользователь касается и отпускает палец на сенсорном экране (например, iPad) (источник: Touch And Mouse на html5rocks.com):
touchstart
touchmove
touchend
mouseover
mouseenter
mouseover
,mouseenter
илиmousemove
изменяет содержимое страницы, следующие события никогда не запускаются.mousemove
mousedown
mouseup
click
Невозможно просто указать веб-браузеру пропустить события мыши.
Что еще хуже, если событие наведения указателя мыши изменяет содержимое страницы, событие click никогда не запускается, как объясняется в Safari Web Content Guide - Handling Events , в частности на рисунке 6.4 в One-Finger Events . Что такое «изменение содержимого», будет зависеть от браузера и версии. Я обнаружил, что для iOS 7.0 изменение цвета фона не является (или больше не?) Изменением содержимого.
Объяснение решения
Резюмируем:
touchstart
иmouseenter
.mouseleave
,touchmove
иclick
.Обратите внимание, что на
touchend
!Это явно работает для событий мыши:
mouseenter
иmouseleave
(слегка улучшенные версииmouseover
иmouseout
) запускаются, а также добавляют и удаляют наведение.Если пользователь действительно
click
переходил по ссылке, эффект наведения также удаляется. Это гарантирует, что он будет удален, если пользователь нажмет кнопку «Назад» в веб-браузере.Это также работает для сенсорных событий: при сенсорном запуске добавляется эффект наведения. Это '' 'не' '' удалено при касании. Он добавляется снова
mouseenter
, и поскольку это не вызывает изменений содержимого (оно уже было добавлено),click
событие также запускается, и по ссылке переходят без необходимости повторного нажатия пользователем!Задержка в 300 мс, которую браузер имеет между
touchstart
событиями, наclick
самом деле хорошо используется, потому что в течение этого короткого времени будет отображаться эффект наведения.Если пользователь решает отменить щелчок, движение пальца будет происходить как обычно. Обычно это проблема, поскольку
mouseleave
событие не запускается, а эффект наведения остается на месте. К счастью, это можно легко исправить, убрав эффект зависанияtouchmove
.Это оно!
Обратите внимание, что можно удалить задержку в 300 мс , например, с помощью библиотеки FastClick , но это выходит за рамки этого вопроса.
Альтернативные решения
Я обнаружил следующие проблемы со следующими альтернативами:
touchend
: это приведет к неправильному переходу по ссылке, даже если пользователь хотел только прокрутить или увеличить масштаб без намерения фактически щелкнуть ссылку.touchend
которая используется в качестве условия if в последующих событиях мыши, чтобы предотвратить изменения состояния в этот момент времени. Переменная сбрасывается в событии щелчка. См. Ответ Уолтера Романа на этой странице. Это достойное решение, если вам действительно не нужен эффект наведения на сенсорные интерфейсы. К сожалению, это не работает, еслиtouchend
запускается по другой причине и не запускается событие щелчка (например, пользователь прокручивает или увеличивает масштаб), а затем пытается перейти по ссылке с помощью мыши (например, на устройстве с интерфейсом мыши и сенсорного экрана). ).Дальнейшее чтение
mouseover
илиmousemove
.источник
touchend
вместо изtouchstart
в большинстве случаев избежать инициирующих действий немедленно , когда пользователь пытается взмах-прокрутка вверх или вниз страница. Все равно произойдет, но с меньшей вероятностью отвлечет или запутает (при условии, что это что-то безобидное, например, отображение метки, а не то, что пользователь должен знать, произошло)Может быть, не думайте об этом как о подавлении эффектов наведения для сенсорных экранов, а как о добавлении эффектов наведения для событий мыши?
Если вы хотите сохранить
:hover
эффекты в своем CSS, вы можете указать разные стили для разных медиа:За исключением того, что, к сожалению, существует множество мобильных устройств, которые игнорируют это и просто используют правила экрана. К счастью, многие новые браузеры для мобильных устройств и планшетов поддерживают некоторые более изящные медиа-запросы:
Таким образом, даже если часть «экран» или «портативный» игнорируется, «максимальная ширина» поможет вам. Вы можете просто предположить, что все, что имеет экран меньше 800 пикселей, должно быть планшетом или телефоном и не использовать эффекты наведения. Редкие пользователи, которые используют мышь на устройстве с низким разрешением, не увидят эффекты наведения, но в противном случае ваш сайт будет в порядке.
Дальнейшее чтение по медиа-запросам? В Интернете есть множество статей об этом - вот одна: http://www.alistapart.com/articles/return-of-the-mobile-stylesheet
Если вы переместите эффекты наведения из своего CSS и примените их с помощью JavaScript, тогда вы можете привязать конкретно к событиям мыши, и / или снова вы можете просто сделать некоторые предположения, основанные только на размере экрана с худшей «проблемой», заключающейся в пользователь, использующий мышь, пропускает эффекты наведения.
источник
preventDefault()
, это иногда подавляет события мыши, но, как я сказал в своем вопросе, это ненадежно.Я написал следующий JS для недавнего проекта, который был сайтом для настольных компьютеров / мобильных устройств / планшетов с эффектами наведения, которые не должны появляться при прикосновении.
В
mobileNoHoverState
приведенном ниже модуле есть переменнаяpreventMouseover
(изначально объявленная какfalse
), для которой устанавливается значение,true
когда пользователь запускаетtouchstart
событие для элемента$target
.preventMouseover
затем возвращается вfalse
исходное состояние всякий раз, когдаmouseover
событие запускается, что позволяет сайту работать должным образом, если пользователь использует и сенсорный экран, и мышь.Мы знаем, что
mouseover
это срабатывает послеtouchstart
из-за порядка, в котором они объявляютсяinit
.Затем создается экземпляр модуля ниже по строке:
источник
Я действительно хотел получить чистое
css
решение для этого сам, так как разбрызгивание весомого решения javascript вокруг всех моих представлений казалось неприятным вариантом. Наконец, был обнаружен запрос @ media.hover , который может определить, «разрешает ли основной механизм ввода пользователю наводить курсор на элементы». Это позволяет избежать сенсорных устройств, на которых «наведение» - это скорее эмулируемое действие, чем прямая возможность устройства ввода.Так, например, если у меня есть ссылка:
Тогда я могу безопасно стилизовать его только
:hover
тогда, когда устройство легко поддерживает этоcss
:Хотя большинство современных браузеров поддерживают запросы интерактивных мультимедийных функций, некоторые популярные браузеры, такие как IE и Firefox , не поддерживают . В моем случае это работает нормально, поскольку я намеревался поддерживать только Chrome на ПК и Chrome и Safari на мобильных устройствах.
источник
Мое решение - добавить активный при наведении класс css в тег HTML и использовать его в начале всех селекторов CSS с помощью: hover и удалить этот класс при первом событии touchstart.
http://codepen.io/Bnaya/pen/EoJlb
JS:
HTML:
CSS:
источник
'ontouchstart' in window
. напримерif ('ontouchstart' in window) document.querySelector('html').classList.remove('hover-active');
Что я сделал для решения той же проблемы, так это обнаружил функцию (я использую что-то вроде этого кода ), чтобы посмотреть, определено ли onTouchMove, и если да, я добавляю класс css "touchMode" в тело, иначе я добавляю " desktopMode ".
Затем каждый раз, когда какой-либо эффект стиля применяется только к сенсорному устройству или только к рабочему столу, к правилу css добавляется соответствующий класс:
Изменить : эта стратегия, конечно, добавляет несколько дополнительных символов в ваш css, поэтому, если вас беспокоит размер css, вы можете искать определения touchMode и desktopMode и помещать их в разные файлы, чтобы вы могли обслуживать оптимизированный css для каждого устройства тип; или вы можете изменить имена классов на что-то более короткое, прежде чем переходить к продукту.
источник
Да, у меня была похожая проблема, но мне удалось ее исправить с помощью медиа-запросов и простого CSS. Я уверен, что нарушаю здесь некоторые правила, но у меня это работает.
По сути, мне пришлось взять огромное приложение, которое кто-то сделал, и сделать его адаптивным. Они использовали jQueryUI и попросили меня не вмешиваться ни в один из их jQuery, поэтому я был ограничен использованием только CSS.
Когда я нажимал одну из их кнопок в режиме сенсорного экрана, эффект наведения срабатывал на секунду до того, как действие кнопки вступило в силу. Вот как я это исправил.
источник
В моем проекте мы решили эту проблему, используя https://www.npmjs.com/package/postcss-hover-prefix и https://modernizr.com/. Сначала мы обрабатываем выходные файлы css с помощью
postcss-hover-prefix
. Он добавляет.no-touch
для всехhover
правил css .CSS
становится
Во время выполнения
Modernizr
автоматически добавляет классы css вhtml
теги, подобные этомуТакая пост-обработка css plus Modernizr отключает наведение для сенсорных устройств и включает для других. Фактически, этот подход был вдохновлен Bootstrap 4, как они решают ту же проблему: https://v4-alpha.getbootstrap.com/getting-started/browsers-devices/#sticky-hoverfocus-on-mobile
источник
Вы можете запускать
mouseLeave
событие всякий раз, когда касаетесь элемента на сенсорном экране. Вот решение для всех<a>
тегов:источник
Iv нашел два решения проблемы, которые подразумевали, что вы обнаруживаете касание с помощью modernizr или чего-то еще и устанавливаете класс касания для элемента html.
Это хорошо, но не очень хорошо поддерживается :
Но у этого есть очень хорошая поддержка :
Для меня работает безупречно, он делает все эффекты наведения похожими на то, когда вы нажимаете кнопку, она загорается, но не глючит, как начальный эффект наведения для событий мыши.
Обнаружение касания с устройств без касания я думаю, что modernizr справился лучше всего:https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touchevents.jsРЕДАКТИРОВАТЬ
Я нашел лучшее и более простое решение этой проблемы
Как определить, является ли клиент сенсорным устройством
источник
Это может помочь увидеть ваш CSS, поскольку это звучит как довольно странная проблема. Но в любом случае, если это происходит, а все остальное в порядке, вы можете попробовать переключить эффект наведения на javascript (вы также можете использовать jquery). Просто привяжите к событию mouseover или, еще лучше, mouseenter и включите свой элемент при срабатывании события.
Ознакомьтесь с последним примером здесь: http://api.jquery.com/mouseover/ , вы можете использовать что-то подобное, чтобы регистрировать, когда событие срабатывает, и брать его оттуда!
источник
mouseenter
; нет кубиков. Нажатие перемещает «невидимый курсор мыши», поэтому он срабатываетmouseenter
иmousemove
(иmouseleave
когда вы касаетесь в другом месте).Если вам нравится использовать JavaScript, вы можете использовать Modernizr на своей странице. Когда страница загружается, браузер без сенсорного экрана будет иметь класс '.no-touch', добавленный к тегу html, но для браузера с сенсорным экраном тег html будет иметь класс '.touch', добавленный к тегу html. .
Тогда это просто случай проверки, есть ли у тега html класс no-touch, прежде чем принимать решение о добавлении ваших слушателей mouseenter и mouseleave.
Для устройства с сенсорным экраном у событий не будет слушателей, поэтому вы не получите эффекта наведения при нажатии.
источник
.touch
и.no-touch
. Переписать свой ответ в CSS вместе с Modernizerhtml.no-touch .box:hover {background-color: "#0000ff"}
и ничего не определять дляhtml.touch .box:hover
должно сработать, поскольку OP только пытается избежать мобильных:hover
s.В недавнем проекте я решил эту проблему с помощью функции делегированных событий jQuery. Он ищет определенные элементы с помощью селектора jQuery и добавляет / удаляет класс CSS для этих элементов, когда указатель мыши находится над элементом. Кажется, он работает хорошо, насколько мне удалось его протестировать, включая IE10 на ноутбуке с сенсорным экраном под управлением Windows 8.
edit: это решение, конечно, требует, чтобы вы изменили свой CSS, чтобы удалить селекторы «: hover», и заранее продумать, какие элементы вы хотите «парить».
Если на вашей странице очень много элементов (например, несколько тысяч), это может стать немного медленным, потому что это решение улавливает события трех типов на всех элементах на странице, а затем делает свое дело, если селектор совпадает. Я назвал класс CSS «mouseover» вместо «hover», потому что я не хотел, чтобы читатели CSS читали «: hover» там, где я написал «.hover».
источник
Вот мое решение: http://jsfiddle.net/agamemnus/g56aw709/ - код ниже.
Все, что нужно сделать, это преобразовать их ": hover" в ".hover" ... вот и все! Большая разница между этим и остальным в том, что это также будет работать с неособыми селекторами элементов, такими как
.my_class > *:hover {
.источник
Включите Modernizr на свою страницу и вместо этого установите состояния наведения, например:
источник
Здравствуйте, человек из будущего, вы, вероятно, захотите использовать запрос
pointer
и / илиhover
медиа.handheld
Запрос СМИ осуждались.источник
Попробуйте это простое решение jquery 2019 года, хотя оно уже давно существует;
добавьте этот плагин в заголовок:
src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"
добавьте это в js:
$("*").on("touchend", function(e) { $(this).focus(); }); //applies to all elements
Предлагаются следующие варианты:
Ноты
Ссылки:
https://code.jquery.com/ui/
https://api.jquery.com/category/selectors/jquery-selector-extensions/
источник