Отключить эффекты наведения в мобильных браузерах

113

Я пишу веб-сайт, предназначенный для использования как с настольных компьютеров, так и с планшетов. Когда его посещают с рабочего стола, я хочу, чтобы интерактивные области экрана подсвечивались :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.

Джо Уайт
источник
7
@Blender, ты вопрос прочитал? Я уже объяснял, почему сниффинг пользовательского агента - плохой выбор.
Джо Уайт
Привет, Джо, ты нашел какое-нибудь решение для этого?
Ismatjon 02
Я искал такой вопрос, рад, что нашел!
agpt
См. Также этот вопрос, который касается отключения наведения на любых устройствах с сенсорным
blade

Ответы:

83

Я понял из вашего вопроса, что ваш эффект наведения меняет содержимое вашей страницы. В таком случае мой совет:

  • Добавьте эффекты наведения на touchstartи mouseenter.
  • Удалить парения воздействие на mouseleave, touchmoveи click.

Кроме того, вы можете отредактировать свою страницу, чтобы не было изменения содержимого.

Задний план

Чтобы имитировать мышь, браузеры, такие как Webkit Mobile, запускают следующие события, если пользователь касается и отпускает палец на сенсорном экране (например, iPad) (источник: Touch And Mouse на html5rocks.com):

  1. touchstart
  2. touchmove
  3. touchend
  4. Задержка 300 мс, когда браузер проверяет, что это одно нажатие, а не двойное.
  5. mouseover
  6. mouseenter
    • Примечание . Если событие mouseover, mouseenterили mousemoveизменяет содержимое страницы, следующие события никогда не запускаются.
  7. mousemove
  8. mousedown
  9. mouseup
  10. 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 , но это выходит за рамки этого вопроса.

Альтернативные решения

Я обнаружил следующие проблемы со следующими альтернативами:

  • Обнаружение браузера: Чрезвычайно подвержен ошибкам. Предполагается, что устройство оснащено мышью или сенсорным экраном, в то время как их комбинация станет все более и более распространенной по мере увеличения количества сенсорных дисплеев.
  • Обнаружение мультимедиа CSS: единственное известное мне решение только для CSS. По-прежнему подвержен ошибкам и по-прежнему предполагает, что на устройстве есть мышь или сенсорный экран, хотя оба варианта возможны.
  • Эмулировать событие щелчка в touchend: это приведет к неправильному переходу по ссылке, даже если пользователь хотел только прокрутить или увеличить масштаб без намерения фактически щелкнуть ссылку.
  • Использовать переменную для подавления событий мыши: это устанавливает переменную в, touchendкоторая используется в качестве условия if в последующих событиях мыши, чтобы предотвратить изменения состояния в этот момент времени. Переменная сбрасывается в событии щелчка. См. Ответ Уолтера Романа на этой странице. Это достойное решение, если вам действительно не нужен эффект наведения на сенсорные интерфейсы. К сожалению, это не работает, если touchendзапускается по другой причине и не запускается событие щелчка (например, пользователь прокручивает или увеличивает масштаб), а затем пытается перейти по ссылке с помощью мыши (например, на устройстве с интерфейсом мыши и сенсорного экрана). ).

Дальнейшее чтение

MacFreek
источник
1
Хороший ответ. Я использовал вашу скрипку, чтобы начать создавать собственное решение. Однако иногда требуется тученд. (когда touchmove не запускается - то есть когда пользователь сам уходит с документа ...)
Агамемнус
Великий ответ , но в большинстве случаев я предлагаю использовать touchend вместо из touchstartв большинстве случаев избежать инициирующих действий немедленно , когда пользователь пытается взмах-прокрутка вверх или вниз страница. Все равно произойдет, но с меньшей вероятностью отвлечет или запутает (при условии, что это что-то безобидное, например, отображение метки, а не то, что пользователь должен знать, произошло)
user56reinstatemonica8
19

Как мне получить эффекты наведения, когда я использую мышь, но подавить их, когда я использую сенсорный экран?

Может быть, не думайте об этом как о подавлении эффектов наведения для сенсорных экранов, а как о добавлении эффектов наведения для событий мыши?

Если вы хотите сохранить :hoverэффекты в своем CSS, вы можете указать разные стили для разных медиа:

@media screen { /* hover styles here */ } 

@media handheld { /* non-hover styles here */ }

За исключением того, что, к сожалению, существует множество мобильных устройств, которые игнорируют это и просто используют правила экрана. К счастью, многие новые браузеры для мобильных устройств и планшетов поддерживают некоторые более изящные медиа-запросы:

@media screen and (max-width:800px) { /* non-hover styles here */ }

Таким образом, даже если часть «экран» или «портативный» игнорируется, «максимальная ширина» поможет вам. Вы можете просто предположить, что все, что имеет экран меньше 800 пикселей, должно быть планшетом или телефоном и не использовать эффекты наведения. Редкие пользователи, которые используют мышь на устройстве с низким разрешением, не увидят эффекты наведения, но в противном случае ваш сайт будет в порядке.

Дальнейшее чтение по медиа-запросам? В Интернете есть множество статей об этом - вот одна: http://www.alistapart.com/articles/return-of-the-mobile-stylesheet

Если вы переместите эффекты наведения из своего CSS и примените их с помощью JavaScript, тогда вы можете привязать конкретно к событиям мыши, и / или снова вы можете просто сделать некоторые предположения, основанные только на размере экрана с худшей «проблемой», заключающейся в пользователь, использующий мышь, пропускает эффекты наведения.

NNNNNN
источник
Я бы хотел добавить эффекты наведения только для событий мыши. Но события касания имитируют события мыши. Если я перехватываю события касания и вызываю preventDefault(), это иногда подавляет события мыши, но, как я сказал в своем вопросе, это ненадежно.
Джо Уайт
6
Что касается медиа-запросов, что произойдет, когда выйдет Windows 8 и на ПК будут и сенсорные экраны, и мыши? Если пользователь наводит указатель мыши, он увидит курсор мыши, и мне нужны эффекты наведения; если они касаются сенсорным экраном, мне не нужны эффекты наведения. Но я не нашел надежного способа обнаружить разницу между сенсорным экраном и мышью.
Джо Уайт
Что ж, возможно, разработчики браузеров будут более мотивированы к тому, чтобы сделать обнаружение более последовательным, когда у них будет больше пользователей на устройствах с сенсорным экраном и мышью. Но сейчас? Я бы делал предположения на основе размера экрана, но в других ответах есть и другие советы. Извините, я ничем не могу помочь.
nnnnnn
9

Я написал следующий JS для недавнего проекта, который был сайтом для настольных компьютеров / мобильных устройств / планшетов с эффектами наведения, которые не должны появляться при прикосновении.

В mobileNoHoverStateприведенном ниже модуле есть переменная preventMouseover(изначально объявленная как false), для которой устанавливается значение, trueкогда пользователь запускает touchstartсобытие для элемента $target.

preventMouseoverзатем возвращается в falseисходное состояние всякий раз, когда mouseoverсобытие запускается, что позволяет сайту работать должным образом, если пользователь использует и сенсорный экран, и мышь.

Мы знаем, что mouseoverэто срабатывает после touchstartиз-за порядка, в котором они объявляются init.

var mobileNoHoverState = function() {

    var hoverClass = 'hover',
        $target = $(".foo"), 
        preventMouseover = false;

    function forTouchstart() {
        preventMouseover = true;
    }

    function forMouseover() {
        if (preventMouseover === false) {
            $(this).addClass(hoverClass);
        } else {
            preventMouseover = false;
        }
    }

    function forMouseout() {
        $(this).removeClass(hoverClass);
    }

    function init() {
        $target.on({
            touchstart  : forTouchstart,
            mouseover   : forMouseover,
            mouseout    : forMouseout
        });                
    }

    return {
        init: init
    };
}();

Затем создается экземпляр модуля ниже по строке:

mobileNoHoverState.init();
Вальтер Роман
источник
«preventMouseover затем возвращается в значение true всякий раз, когда запускается событие mouseover, что позволяет сайту работать должным образом, если пользователь использует и сенсорный экран, и мышь». - Ваш код этого не делает. Я что-то упускаю?
Redtopia
@Redtopia Спасибо за внимание! Я обновил ответ, добавив в него пропущенный кусок кода.
Уолтер Роман
Вам не нужны точки с запятой после объявления функции
nacholibre
@nacholibre Введено правильное использование точки с запятой
Вальтер Роман
6

Я действительно хотел получить чистое cssрешение для этого сам, так как разбрызгивание весомого решения javascript вокруг всех моих представлений казалось неприятным вариантом. Наконец, был обнаружен запрос @ media.hover , который может определить, «разрешает ли основной механизм ввода пользователю наводить курсор на элементы». Это позволяет избежать сенсорных устройств, на которых «наведение» - это скорее эмулируемое действие, чем прямая возможность устройства ввода.

Так, например, если у меня есть ссылка:

<a href="/" class="link">Home</a>

Тогда я могу безопасно стилизовать его только :hoverтогда, когда устройство легко поддерживает это css:

@media (hover: hover) {
  .link:hover { /* hover styles */ }
}

Хотя большинство современных браузеров поддерживают запросы интерактивных мультимедийных функций, некоторые популярные браузеры, такие как IE и Firefox , не поддерживают . В моем случае это работает нормально, поскольку я намеревался поддерживать только Chrome на ПК и Chrome и Safari на мобильных устройствах.

Flintinatux
источник
Хорошее решение, которое, похоже, работает, когда вы эмулируете устройства в Chrome devtools. Но он по-прежнему не работает для Chrome Android :-(
Sjeiti
Считаю это наиболее удобным и правильным решением. Надеюсь, что скоро он будет добавлен в стандарты W3C.
GProst
5

Мое решение - добавить активный при наведении класс css в тег HTML и использовать его в начале всех селекторов CSS с помощью: hover и удалить этот класс при первом событии touchstart.

http://codepen.io/Bnaya/pen/EoJlb

JS:

(function () {
    'use strict';

    if (!('addEventListener' in window)) {
        return;
    }

    var htmlElement = document.querySelector('html');

    function touchStart () {
        document.querySelector('html').classList.remove('hover-active');

        htmlElement.removeEventListener('touchstart', touchStart);
    }

    htmlElement.addEventListener('touchstart', touchStart);
}());

HTML:

<html class="hover-active">

CSS:

.hover-active .mybutton:hover {
    box-shadow: 1px 1px 1px #000;
}
Bnaya
источник
Вместо того, чтобы слушать событие касания, вы можете протестировать 'ontouchstart' in window. напримерif ('ontouchstart' in window) document.querySelector('html').classList.remove('hover-active');
Yuval A.
@YuvalA. Причина, по которой я жду события касания, заключается в том, что есть устройства с поддержкой указателя и касания, а пользователь использует указатель, и я не хочу удалять наведение. Возможно, пользователь будет использовать прикосновение, а затем указатель, но мне особо нечего с этим делать
Бная,
2

Что я сделал для решения той же проблемы, так это обнаружил функцию (я использую что-то вроде этого кода ), чтобы посмотреть, определено ли onTouchMove, и если да, я добавляю класс css "touchMode" в тело, иначе я добавляю " desktopMode ".

Затем каждый раз, когда какой-либо эффект стиля применяется только к сенсорному устройству или только к рабочему столу, к правилу css добавляется соответствующий класс:

.desktopMode .someClass:hover{ color: red }
.touchMode .mainDiv { width: 100%; margin: 0; /*etc.*/ }

Изменить : эта стратегия, конечно, добавляет несколько дополнительных символов в ваш css, поэтому, если вас беспокоит размер css, вы можете искать определения touchMode и desktopMode и помещать их в разные файлы, чтобы вы могли обслуживать оптимизированный css для каждого устройства тип; или вы можете изменить имена классов на что-то более короткое, прежде чем переходить к продукту.

Стейн Г. Стриндхауг
источник
2

Да, у меня была похожая проблема, но мне удалось ее исправить с помощью медиа-запросов и простого CSS. Я уверен, что нарушаю здесь некоторые правила, но у меня это работает.

По сути, мне пришлось взять огромное приложение, которое кто-то сделал, и сделать его адаптивным. Они использовали jQueryUI и попросили меня не вмешиваться ни в один из их jQuery, поэтому я был ограничен использованием только CSS.

Когда я нажимал одну из их кнопок в режиме сенсорного экрана, эффект наведения срабатывал на секунду до того, как действие кнопки вступило в силу. Вот как я это исправил.

@media only screen and (max-width:1024px) {

       #buttonOne{
            height: 44px;
        }


        #buttonOne:hover{
            display:none;
        }
}   
бесшабашный
источник
2

В моем проекте мы решили эту проблему, используя https://www.npmjs.com/package/postcss-hover-prefix и https://modernizr.com/. Сначала мы обрабатываем выходные файлы css с помощью postcss-hover-prefix. Он добавляет .no-touchдля всех hoverправил css .

const fs = require("fs");
const postcss = require("postcss");
const hoverPrfx = require("postcss-hover-prefix");

var css = fs.readFileSync(cssFileName, "utf8").toString();
postcss()
   .use(hoverPrfx("no-touch"))
   .process(css)
   .then((result) => {
      fs.writeFileSync(cssFileName, result);
   });

CSS

a.text-primary:hover {
  color: #62686d;
}

становится

.no-touch a.text-primary:hover {
  color: #62686d;
}

Во время выполнения Modernizrавтоматически добавляет классы css в htmlтеги, подобные этому

<html class="wpfe-full-height js flexbox flexboxlegacy canvas canvastext webgl 
  no-touch 
  geolocation postmessage websqldatabase indexeddb hashchange
  history draganddrop websockets rgba hsla multiplebgs backgroundsize borderimage
  borderradius boxshadow textshadow opacity cssanimations csscolumns cssgradients
  cssreflections csstransforms csstransforms3d csstransitions fontface
  generatedcontent video audio localstorage sessionstorage webworkers
  applicationcache svg inlinesvg smil svgclippaths websocketsbinary">

Такая пост-обработка css plus Modernizr отключает наведение для сенсорных устройств и включает для других. Фактически, этот подход был вдохновлен Bootstrap 4, как они решают ту же проблему: https://v4-alpha.getbootstrap.com/getting-started/browsers-devices/#sticky-hoverfocus-on-mobile

Станислав Берков
источник
1

Вы можете запускать mouseLeaveсобытие всякий раз, когда касаетесь элемента на сенсорном экране. Вот решение для всех <a>тегов:

function removeHover() {
    var anchors = document.getElementsByTagName('a');
    for(i=0; i<anchors.length; i++) {
        anchors[i].addEventListener('touchstart', function(e){
            $('a').mouseleave();
        }, false);
    }
}
Саид Холов
источник
JSHint говорит: «Не создавайте функции внутри цикла».
NetOperator Wibby
Это взлом. Это НЕ многократно используемый код, который можно считать хорошей практикой. @NetOperatorWibby
Саид Холов
Ну, публиковать код, который нельзя считать хорошей практикой, не очень-то полезно. Это как наложить пластырь на ножевую рану.
NetOperator Wibby,
1

Iv нашел два решения проблемы, которые подразумевали, что вы обнаруживаете касание с помощью modernizr или чего-то еще и устанавливаете класс касания для элемента html.

Это хорошо, но не очень хорошо поддерживается :

html.touch *:hover {
    all:unset!important;
}

Но у этого есть очень хорошая поддержка :

html.touch *:hover {
    pointer-events: none !important;
}

Для меня работает безупречно, он делает все эффекты наведения похожими на то, когда вы нажимаете кнопку, она загорается, но не глючит, как начальный эффект наведения для событий мыши.

Обнаружение касания с устройств без касания я думаю, что modernizr справился лучше всего:

https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touchevents.js

РЕДАКТИРОВАТЬ

Я нашел лучшее и более простое решение этой проблемы

Как определить, является ли клиент сенсорным устройством

Саймон Драгсбек
источник
0

Это может помочь увидеть ваш CSS, поскольку это звучит как довольно странная проблема. Но в любом случае, если это происходит, а все остальное в порядке, вы можете попробовать переключить эффект наведения на javascript (вы также можете использовать jquery). Просто привяжите к событию mouseover или, еще лучше, mouseenter и включите свой элемент при срабатывании события.

Ознакомьтесь с последним примером здесь: http://api.jquery.com/mouseover/ , вы можете использовать что-то подобное, чтобы регистрировать, когда событие срабатывает, и брать его оттуда!

Балах
источник
Ничего особенного в CSS; см. мое редактирование. И я уже пробовал mouseenter; нет кубиков. Нажатие перемещает «невидимый курсор мыши», поэтому он срабатывает mouseenterи mousemovemouseleaveкогда вы касаетесь в другом месте).
Джо Уайт
0

Если вам нравится использовать JavaScript, вы можете использовать Modernizr на своей странице. Когда страница загружается, браузер без сенсорного экрана будет иметь класс '.no-touch', добавленный к тегу html, но для браузера с сенсорным экраном тег html будет иметь класс '.touch', добавленный к тегу html. .

Тогда это просто случай проверки, есть ли у тега html класс no-touch, прежде чем принимать решение о добавлении ваших слушателей mouseenter и mouseleave.

if($('html').hasClass('no-touch')){
    $('.box').on("mouseenter", function(event){
            $(this).css('background-color','#0000ff')
    });
    $('.box').on("mouseleave", function(event){
            $(this).css('background-color','')
    });
}

Для устройства с сенсорным экраном у событий не будет слушателей, поэтому вы не получите эффекта наведения при нажатии.

Станц
источник
Когда это можно сделать с помощью css, не используйте javascript (jquery), это пустая трата мощности компьютера
Саймон Драгсбек,
1
Еще проще: в вашем CSS вы можете определить отдельные правила для .touchи .no-touch. Переписать свой ответ в CSS вместе с Modernizer html.no-touch .box:hover {background-color: "#0000ff"}и ничего не определять для html.touch .box:hoverдолжно сработать, поскольку OP только пытается избежать мобильных :hovers.
Walter Roman
0

В недавнем проекте я решил эту проблему с помощью функции делегированных событий jQuery. Он ищет определенные элементы с помощью селектора jQuery и добавляет / удаляет класс CSS для этих элементов, когда указатель мыши находится над элементом. Кажется, он работает хорошо, насколько мне удалось его протестировать, включая IE10 на ноутбуке с сенсорным экраном под управлением Windows 8.

$(document).ready(
    function()
    {
        // insert your own selector here: maybe '.hoverable'?
        var selector = 'button, .hotspot';

        $('body')
            .on('mouseover', selector, function(){ $(this).addClass('mouseover');    })
            .on('mouseout',  selector, function(){ $(this).removeClass('mouseover'); })
            .on('click',     selector, function(){ $(this).removeClass('mouseover'); });
    }
);

edit: это решение, конечно, требует, чтобы вы изменили свой CSS, чтобы удалить селекторы «: hover», и заранее продумать, какие элементы вы хотите «парить».

Если на вашей странице очень много элементов (например, несколько тысяч), это может стать немного медленным, потому что это решение улавливает события трех типов на всех элементах на странице, а затем делает свое дело, если селектор совпадает. Я назвал класс CSS «mouseover» вместо «hover», потому что я не хотел, чтобы читатели CSS читали «: hover» там, где я написал «.hover».

toon81
источник
0

Вот мое решение: http://jsfiddle.net/agamemnus/g56aw709/ - код ниже.

Все, что нужно сделать, это преобразовать их ": hover" в ".hover" ... вот и все! Большая разница между этим и остальным в том, что это также будет работать с неособыми селекторами элементов, такими как .my_class > *:hover {.

handle_css_hover_effects ()

function handle_css_hover_effects (init) {
 var init = init || {}
 var handle_touch_events = init.handle_touch_events || true
 var handle_mouse_events = init.handle_mouse_events || true
 var hover_class         = init.hover_class         || "hover"
 var delay_preferences   = init.delay_preferences   || {touch: {add: 500, remove: 500}}
 function default_handler (curobj, input_type, op) {
  var hovered_element_selector = "*" + ((op == "add") ? ":" : ("." + hover_class))
  var hovered_elements = Array.prototype.slice.call(document.body.querySelectorAll(hovered_element_selector))
  var modified_list = []
  while (true) {
   if ((curobj == null) || (curobj == document.documentElement)) break
   if (hovered_elements.indexOf(curobj) != -1) modified_list.push (curobj)
   curobj = curobj.parentNode
  }
  function do_hover_change () {modified_list.forEach (function (curobj) {curobj.classList[op](hover_class)})}
  if ((!delay_preferences[input_type]) || (!delay_preferences[input_type][op])) {
   do_hover_change ()
  } else {
   setTimeout (do_hover_change, delay_preferences[input_type][op])
  }
 }

 if (handle_mouse_events) {
  document.body.addEventListener ('mouseover' , function (evt) {var curobj = evt.target; default_handler (curobj, "mouse", "add")})
  document.body.addEventListener ('mouseout'  , function (evt) {var curobj = evt.target; default_handler (curobj, "mouse", "remove")})
  document.body.addEventListener ('click'     , function (evt) {var curobj = evt.target; default_handler (curobj, "mouse", "remove")})
 }

 if (handle_touch_events) {
  document.body.addEventListener ('touchstart', function (evt) {var curobj = evt.target; default_handler (curobj, "touch", "add")})
  document.body.addEventListener ('touchend'  , function (evt) {var curobj = evt.target; default_handler (curobj, "touch", "remove")})
  document.body.addEventListener ('touchmove',  function (evt) {
   var curobj = evt.target
   var hovered_elements = Array.prototype.slice.call(document.body.querySelectorAll("*:hover"))
   var lastobj = null
   evt = evt.changedTouches[0]
   var elements_at_point = get_elements_at_point (evt.pageX, evt.pageY)
   // Get the last element that isn't at the current point but is still hovered over, and remove only its hover attribute.
   while (true) {
    if ((curobj == null) || (curobj == document.documentElement)) break
    if ((hovered_elements.indexOf(curobj) != -1) && (elements_at_point.indexOf(curobj) == -1)) lastobj = curobj
    curobj = curobj.parentNode
   }
   if (lastobj == null) return
   if ((!delay_preferences.touch) || (!delay_preferences.touch.remove)) {
    lastobj.classList.remove(hover_class)
   } else {
    setTimeout (function () {lastobj.classList.remove(hover_class)}, delay_preferences.touch.remove)
   }

   function get_elements_at_point (x, y) {
    var el_list = [], pe_list = []
    while (true) {
     var curobj = document.elementFromPoint(x, y)
     if ((curobj == null) || (curobj == document.documentElement)) break
     el_list.push (curobj); pe_list.push (curobj.style.pointerEvents)
     curobj.style.pointerEvents = "none"
    }
    el_list.forEach (function (current_element, i) {current_element.style.pointerEvents = pe_list[i]})
    return el_list
   }
  })
 }
}
Agamemnus
источник
0

Включите Modernizr на свою страницу и вместо этого установите состояния наведения, например:

html.no-touchevents .box:hover {
    background: blue;
}
Джонатан Поттер
источник
0

Здравствуйте, человек из будущего, вы, вероятно, захотите использовать запрос pointerи / или hoverмедиа. handheldЗапрос СМИ осуждались.

/* device is using a mouse or similar */
@media (pointer: fine) {
  a:hover {
    background: red;
  }
}
оланод
источник
-1

Попробуйте это простое решение jquery 2019 года, хотя оно уже давно существует;

  1. добавьте этот плагин в заголовок:

    src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"

  2. добавьте это в js:

    $("*").on("touchend", function(e) { $(this).focus(); }); //applies to all elements

  3. Предлагаются следующие варианты:

    $(":input, :checkbox,").on("touchend", function(e) {(this).focus);}); //specify elements
    
    $("*").on("click, touchend", function(e) { $(this).focus(); });  //include click event`
    
    css: body { cursor: pointer; } //touch anywhere to end a focus`

Ноты

  • поместите плагин перед bootstrap.js, если применимо, чтобы не повлиять на всплывающие подсказки
  • Проверено только на iphone XR ios 12.1.12 и ipad 3 ios 9.3.5 с использованием Safari или Chrome.

Ссылки:

https://code.jquery.com/ui/

https://api.jquery.com/category/selectors/jquery-selector-extensions/

Даррен
источник