Подтвердить что ты не робот

Как удалить/игнорировать: навести стиль css на сенсорных устройствах

Я хочу игнорировать все объявления :hover CSS, если пользователь посещает наш веб-сайт с помощью сенсорного устройства. Поскольку CSS :hover не имеет смысла, и это может даже беспокоить, если планшет запускает его при нажатии/нажатии, потому что тогда он может придерживаться, пока элемент не теряет фокус. Честно говоря, я не знаю, почему сенсорные устройства чувствуют необходимость запускать :hover на первом месте - но это реальность, поэтому эта проблема также является реальностью.

a:hover {
   color:blue;
   border-color:green;
   // etc. > ignore all at once for touch devices
}

Итак, (как) я могу удалить/игнорировать все объявления CSS :hover сразу (без необходимости знать каждый) для сенсорных устройств после их объявления?

4b9b3361

Ответ 1

Существует несколько решений для этой проблемы.

Quick'n'dirty - удалить: стили наведения с использованием JS

Вы можете удалить все правила CSS, содержащие :hover, используя Javascript. Это имеет то преимущество, что вам не нужно прикасаться к CSS и быть совместимым даже со старыми браузерами.

function hasTouch() {
    return 'ontouchstart' in document.documentElement
           || navigator.maxTouchPoints > 0
           || navigator.msMaxTouchPoints > 0;
}

if (hasTouch()) { // remove all :hover stylesheets
    try { // prevent exception on browsers not supporting DOM styleSheets properly
        for (var si in document.styleSheets) {
            var styleSheet = document.styleSheets[si];
            if (!styleSheet.rules) continue;

            for (var ri = styleSheet.rules.length - 1; ri >= 0; ri--) {
                if (!styleSheet.rules[ri].selectorText) continue;

                if (styleSheet.rules[ri].selectorText.match(':hover')) {
                    styleSheet.deleteRule(ri);
                }
            }
        }
    } catch (ex) {}
}

Ограничения: таблицы стилей должны размещаться в одном домене (это означает отсутствие CDN). Отключает зависания на смешанных мышь и сенсорные устройства, такие как Surface, что повредит UX.

CSS-only - использование медиа-запросов

Поместите все свои правила: hover в блок @media:

@media (hover: hover) {
    a:hover { color: blue; }
}

или, наоборот, переопределить все правила наведения (совместимые со старыми браузерами):

a:hover { color: blue; }

@media (hover: none) {
    a:hover { color: inherit; }
}

Ограничения: работает только с iOS 9.0+, Chrome для Android или Android 5.0+ при использовании WebView. hover: hover ломает эффекты зависания на старых браузерах, hover: none требует переопределения всех ранее определенных правил CSS. Оба являются несовместимыми со смешанными устройствами мыши и touch.

Самый надежный - использовать специальный класс CSS и обнаруживать прикосновение через JS

Этот метод требует добавления всех правил наведения с помощью body.hasHover. (или имя класса по вашему выбору)

body.hasHover a:hover { color: blue; }

Класс hasHover может быть добавлен с помощью hasTouch() из первого примера:

if (!hasTouch()) {
    document.body.className += ' hasHover';
}

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

function watchForHover() {
    var hasHoverClass = false;
    var container = document.body;
    var lastTouchTime = 0;

    function enableHover() {
        // filter emulated events coming from touch events
        if (new Date() - lastTouchTime < 500) return;
        if (hasHoverClass) return;

        container.className += ' hasHover';
        hasHoverClass = true;
    }

    function disableHover() {
        if (!hasHoverClass) return;

        container.className = container.className.replace(' hasHover', '');
        hasHoverClass = false;
    }

    function updateLastTouchTime() {
        lastTouchTime = new Date();
    }

    document.addEventListener('touchstart', updateLastTouchTime, true);
    document.addEventListener('touchstart', disableHover, true);
    document.addEventListener('mousemove', enableHover, true);

    enableHover();
}

watchForHover();

Это должно работать в основном в любом браузере и включать/отключать стили наведения по мере необходимости. Попробуйте здесь: https://jsfiddle.net/dkz17jc5/19/

Ответ 2

Адаптация указателя на помощь!

Поскольку это не было затронуто через некоторое время, вы можете использовать:

a:link {
   color: red;
}

a:hover {
   color:blue;
}

@media (hover: none) {
   a:link {
      color: red;
   }
}

Смотрите демонстрацию в браузере вашего браузера и в браузере телефона. Поддерживается современными сенсорными устройствами.

Примечание. Имейте в виду, что поскольку основной вход (возможность) Surface PC является мышью, он станет синей связью, даже если это отдельный экран (планшет). Браузеры будут (должны) всегда устанавливать по умолчанию самые точные возможности ввода.

Ответ 3

В настоящее время я имею дело с аналогичной проблемой.

Есть сразу два основных варианта: (1) проверка пользовательской строки или (2) сохранение отдельных мобильных страниц с использованием другого URL-адреса и выбор пользователями того, что лучше для них.

  • Если вы можете использовать язык с каналом на канале, например PHP или Ruby, вы можете проверить строку пользователя устройства, запрашивающего страницу, и просто обслуживать один и тот же контент, но с помощью a <link rel="mobile.css" /> вместо обычного стиля.

Пользовательские строки имеют идентификационную информацию о браузере, рендерере, операционной системе и т.д. Вам решать, какие устройства "касаются" и "не касаются". Возможно, вы сможете найти эту информацию где-то и перевести ее в свою систему.

A. Если вам разрешено игнорировать старые браузеры, вам просто нужно добавить одно правило к нормальному, не мобильному css, а именно: EDIT: Erk. После некоторых экспериментов я обнаружил, что приведенное ниже правило также отключает возможность отслеживать ссылки в webkit-браузерах в дополнение к простому отключению эстетических эффектов - см. http://jsfiddle.net/3nkcdeao/
Таким образом, вы должны быть немного более избирательными относительно того, как вы изменяете правила для мобильного дела, чем то, что я показываю здесь, но это может быть полезной отправной точкой:

* { 
    pointer-events: none !important; /* only use !important if you have to */
}

Как побочный элемент, отключение указателей-событий родителя и последующее их явное включение в дочерний объект в настоящее время заставляет все зависающие эффекты на родительском элементе снова активироваться, если дочерний элемент входит в :hover.
См. http://jsfiddle.net/38Lookhp/5/

В. Если вы поддерживаете устаревшие веб-рендереры, вам придется немного поработать над тем, чтобы удалить любые правила, которые устанавливают специальные стили во время :hover. Чтобы сэкономить время, вы можете просто создать автоматическую копию + sed ing, которую вы запускаете в своих стандартных таблицах стилей для создания мобильные версии. Это позволит вам просто написать/обновить стандартный код и скрыть все правила стиля, которые используют :hover для мобильной версии ваших страниц.

  1. (I) Кроме того, просто сообщите своим пользователям, что у вас есть m.website.com для мобильных устройств в дополнение к вашему веб-сайту. Хотя субдомен является наиболее распространенным способом, вы также можете иметь некоторую другую предсказуемую модификацию данного URL-адреса, чтобы позволить мобильным пользователям получать доступ к измененным страницам. На этом этапе вы захотите убедиться, что им не нужно изменять URL-адрес каждый раз, когда они переходят на другую часть сайта.

Снова здесь вы можете просто добавить дополнительное правило или два в таблицы стилей или сделать что-то более сложное, используя sed или аналогичную полезность. Было бы, наверное, проще всего применить: не к вашим правилам стиля, например div:not(.disruptive):hover {..., в которые вы добавили бы class="disruptive" к элементам, которые раздражают вещи для мобильных пользователей, используя js или язык сервера, вместо того, чтобы перебирать CSS.

  1. (II) Вы можете комбинировать первые два и (если вы подозреваете, что пользователь побродил по неправильной версии страницы), вы можете предположить, что они переключаются в/из дисплея мобильного типа или просто есть ссылка где-то, что позволяет пользователям набрасываться вперед и назад. Как уже было сказано, запросы @media также могут быть полезными при определении того, что используется для посещения.

  2. (III) Если вы решили использовать jQuery-решение, когда знаете, какие устройства "касаются", а какие нет, вы можете найти CSS hover not being игнорируются на сенсорных устройствах.

Ответ 5

Я столкнулся с той же проблемой (в моем случае с мобильными браузерами Samsung) и поэтому наткнулся на этот вопрос.

Благодаря ответу Calsal я нашел то, что, как мне кажется, исключит практически все настольные браузеры, потому что оно, кажется, распознается мобильными браузерами, которые я пробовал (см. Скриншот из скомпилированной таблицы: таблица обнаружения функций указателя CSS).

MDN веб-документы утверждают, что

Функция CSS @media указателя может использоваться для применения стилей в зависимости от того, является ли основной механизм ввода пользователя указательным устройством, и если да, то насколько он точен

,

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

Следовательно, вы могли бы создать медиа-запрос, как описано Calsal, но слегка измененный. Он использует обратную логику, чтобы исключить все сенсорные устройства.

Sass mixin:

@mixin hover-supported {    
    /* 
     * https://developer.mozilla.org/en-US/docs/Web/CSS/@media/pointer 
     * coarse: The primary input mechanism includes a pointing device of limited accuracy.
     */
    @media not all and (pointer: coarse) {
        &:hover {
            @content;
        }
    }
}

a {
    color:green;
    border-color:blue;

    @include hover-supported() {
        color:blue;
        border-color:green;
    }
}

Скомпилированный CSS:

a {
  color: green;
  border-color: blue;
}
@media not all and (pointer: coarse) {
  a:hover {
    color: blue;
    border-color: green;
  }
}

Это также описано в этой сущности, которую я создал после исследования проблемы. Codepen для эмпирических исследований.

ОБНОВЛЕНИЕ: На момент написания этого обновления, 2018-08-23 и указанного @DmitriPavlutin, эта техника, похоже, больше не работает с настольным компьютером Firefox.

Ответ 6

Вы можете использовать Modernizr JS (см. также этот fooobar.com/questions/3094/...) или создать пользовательскую функцию JS:

function is_touch_device() {
 return 'ontouchstart' in window        // works on most browsers 
  || navigator.maxTouchPoints;       // works on IE10/11 and Surface
};

if ( is_touch_device() ) {
  $('html').addClass('touch');
} else {
  $('html').addClass('no-touch');
} 

до определить поддержку сенсорного события в браузере, а затем назначить регулярное свойство CSS, пройдя элемент с классом html.no-touch, например:

html.touch a {
    width: 480px;
}

/* FOR THE DESKTOP, SET THE HOVER STATE */
html.no-touch a:hover {
   width: auto;
   color:blue;
   border-color:green;
}

Ответ 7

Это также возможное обходное решение, но вам придется пройти через свой css и добавить класс .no-touch перед стилями наведения.

JavaScript:

if (!("ontouchstart" in document.documentElement)) {
document.documentElement.className += " no-touch";
}

Пример CSS:

<style>
p span {
    display: none;
}

.no-touch p:hover span {
    display: inline;
}
</style>
<p><a href="/">Tap me</a><span>You tapped!</span></p>

Источник

P.s. Но мы должны помнить, что на рынок поступают все больше и больше сенсорных устройств, которые одновременно поддерживают поддержку мыши.

Ответ 8

Это может быть еще не идеальное решение (и его с jQuery), но, возможно, это направление/концепция, над которой нужно работать: как насчет того, чтобы делать это наоборот? Это означает дезактивацию состояний: hover css по умолчанию и активировать их, если событие mousemove обнаружено в любом месте документа. Конечно, это не работает, если кто-то отключил js. Что еще может против этого делать так?

Может быть, так:

CSS

/* will only work if html has class "mousedetected" */
html.mousedetected a:hover {
   color:blue;
   border-color:green;
}

JQuery

/* adds "mousedetected" class to html element if mouse moves (which should never happen on touch-only devices shouldn’t it?) */
$("body").mousemove( function() {
    $("html").addClass("mousedetected");
});

Ответ 9

Согласно ответу Джейсона, мы можем адресовать только устройства, которые не поддерживают hover, с чисто медиа-запросами CSS. Мы также можем обращаться только к устройствам, которые поддерживают hover, например, к ответу moogal на аналогичный вопрос, с @media not all and (hover: none). Это выглядит странно, но это работает.

Из этого я сделал миксин Sass для более легкого использования:

@mixin hover-supported {
    @media not all and (hover: none) {
        &:hover {
            @content;
        }
    }
}

Обновление 2019-05-15: я рекомендую эту статью из Medium, которая охватывает все различные устройства, на которые мы можем ориентироваться с помощью CSS. По сути, это смесь этих правил мультимедиа, объединяющая их для определенных целей:

@media (hover: hover) {
    /* Device that can hover (desktops) */
}
@media (hover: none) {
    /* Device that can not hover with ease */
}
@media (pointer: coarse) {
    /* Device with limited pointing accuracy (touch) */
}
@media (pointer: fine) {
    /* Device with accurate pointing (desktop, stylus-based) */
}
@media (pointer: none) {
    /* Device with no pointing */
}

Пример для конкретных целей:

@media (hover: none) and (pointer: coarse) {
    /* Smartphones and touchscreens */
}

@media (hover: hover) and (pointer: fine) {
    /* Desktops with mouse */
}

Я люблю миксины, вот как я их использую:

@mixin is-touch {
    @media (hover: none) and (pointer: coarse) {
        @content;
    }
}

Ответ 10

Мне было полезно: ссылка

function hoverTouchUnstick() {
    // Check if the device supports touch events
    if('ontouchstart' in document.documentElement) {
        // Loop through each stylesheet
        for(var sheetI = document.styleSheets.length - 1; sheetI >= 0; sheetI--) {
            var sheet = document.styleSheets[sheetI];
            // Verify if cssRules exists in sheet
            if(sheet.cssRules) {
                // Loop through each rule in sheet
                for(var ruleI = sheet.cssRules.length - 1; ruleI >= 0; ruleI--) {
                    var rule = sheet.cssRules[ruleI];
                    // Verify rule has selector text
                    if(rule.selectorText) {
                        // Replace hover psuedo-class with active psuedo-class
                        rule.selectorText = rule.selectorText.replace(":hover", ":active");
                    }
                }
            }
        }
    }
}

Ответ 11

Попробуйте это (я использую background и background-color в этом примере):

var ClickEventType = ((document.ontouchstart !== null) ? 'click' : 'touchstart');

if (ClickEventType == 'touchstart') {
            $('a').each(function() { // save original..
                var back_color = $(this).css('background-color');
                var background = $(this).css('background');
                $(this).attr('data-back_color', back_color);
                $(this).attr('data-background', background);
            });

            $('a').on('touchend', function(e) { // overwrite with original style..
                var background = $(this).attr('data-background');
                var back_color = $(this).attr('data-back_color');
                if (back_color != undefined) {
                    $(this).css({'background-color': back_color});
                }
                if (background != undefined) {
                    $(this).css({'background': background});
                }
            }).on('touchstart', function(e) { // clear added stlye="" elements..
                $(this).css({'background': '', 'background-color': ''});
            });
}

CSS:

a {
    -webkit-touch-callout: none;
    -webkit-tap-highlight-color: transparent;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

Ответ 12

Это можно решить с помощью sass/scss и медиа-запроса с требуемой точкой останова.

.myclass {
    background-color: blue;
    &:hover {
        @media screen and (max-width: 320px) {
            background-color: red;
        }
    }
}

Ответ 13

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

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

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

  2. добавить это к JS:

    $ ("*"). on ("touchend", function (e) {$ (this).focus();}); //применяется ко всем элементам

  3. некоторые предлагаемые варианты этого:

    $ (": input,: checkbox,"). on ("touchend", function (e) {(this).focus);}); //указать элементы

    $ ("*"). on ("click, touchend", function (e) {$ (this).focus();}); // включить событие клика

    css: body {курсор: указатель; }//коснитесь где-нибудь, чтобы закончить фокус

Заметки

  • поместите плагин перед 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/