Як видалити / ігнорувати: наведіть курсор CSS на сенсорні пристрої


141

Я хочу ігнорувати всі :hoverCSS-декларації, якщо користувач відвідує наш веб-сайт через сенсорний пристрій. Оскільки :hoverCSS не має сенсу, і це може навіть турбувати, якщо планшет запускає його при натисканні / натисканні, оскільки тоді він може триматися, поки елемент не втратить фокус. Якщо чесно, я не знаю, чому сенсорні пристрої відчувають потребу спрацьовувати :hoverв першу чергу - але це реальність, тому ця проблема є і реальністю.

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

Отже, (як) я можу видалити / ігнорувати всі CSS- :hoverдекларації одразу (не знаючи кожного) для сенсорних пристроїв після того, як вони оголосили їх?



1
Мені подобається це за допомогою PHP-рішення, де я виявляю, чи переглядаючий пристрій мобільний чи ні, і використовую правильну таблицю стилів з різними змінами, заснованими на цьому. Однак це не відповідає на ваше запитання. Ви потенційно можете використовувати @media-запити, але це не гарантовано, що вони працюють, навіть коли телефони та планшети мають повну роздільну здатність hd.
TomFirth

Відповіді:


171

tl; dr використовувати це: https://jsfiddle.net/57tmy8j3/

Якщо вас цікавить, чому або які інші варіанти існують, читайте далі.

Quick'n'dirty - delete: наведіть курсор стилів за допомогою JS

Ви можете видалити всі правила CSS, що містять :hoverJavascript. Це має перевагу в тому, що не потрібно торкатися CSS та бути сумісним навіть із старими браузерами.

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

if (hasTouch()) { // remove all the :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 або iPad Pro, що шкодить UX.

Тільки CSS - використовуйте медіа-запити

Розмістіть у @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. Обидва несумісні із змішаними пристроями миші та сенсорного пристрою .

Найбільш надійний - виявляйте дотик за допомогою JS та додайте CSS: правила наведення курсора

Цей метод потребує попереднього встановлення всіх правил наведення body.hasHover. (або назва вашого класу)

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

hasHoverКлас може бути доданий з допомогою hasTouch()з першого прикладу:

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

Однак це може мати ті ж недоліки із змішаними сенсорними пристроями, що і попередні приклади, що підводить нас до остаточного рішення. Увімкніть наведення ефектів під час переміщення курсору миші, відключіть ефекти наведення курсора кожного разу, коли буде виявлено дотик.

function watchForHover() {
  // lastTouchTime is used for ignoring emulated mousemove events
  let lastTouchTime = 0

  function enableHover() {
    if (new Date() - lastTouchTime < 500) return
    document.body.classList.add('hasHover')
  }

  function disableHover() {
    document.body.classList.remove('hasHover')
  }

  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/57tmy8j3/
Спадщина (для використання зі старими браузерами): https://jsfiddle.net/dkz17jc5/19/


Дякую! Лише один коментар: чи не було б краще спочатку перевірити, чи document.styleSheetsіснує, а не використовувати try/catch?
Саймон Ферндрігер

1
Я використовував про try/catchвсяк випадок, коли з’явиться якась дивна помилка, яка може зірвати сценарій, наприклад, deleteRule не працює через політику того самого походження або невмілу підтримку IE (відредагував коментар, щоб це відобразити). Але так, у більшості випадків достатньо простої перевірки.
клинок

1
Варто зазначити, що настільні браузери, включаючи Firefox, не призведуть до "notouch". Вони повідомляють про розуміння подій на дотик.
Гаррі Б

3
Це рішення не працює для змішаних пристроїв, де наведення курсору працює для миші, але не для сенсорних подій
nbar

2
@Haneev це правильно для більшості випадків, хоча не для вашого конкретного. Здійснення роботи вашого правила додало б багато складності коду, що зробить відповідь важче зрозуміти. Я б запропонував або розділити правила, або використовувати 2-е рішення, яке все-таки є більш надійним. Однак ви можете запропонувати зміни, якщо ви можете вдосконалити перше рішення, не ускладнюючи його.
лезо

43

Адаптація вказівника до порятунку!

Оскільки це не було доторкано до певного часу, ви можете використовувати:

a:link {
   color: red;
}

a:hover {
   color:blue;
}

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

Дивіться цю демонстрацію як у веб-переглядачі, так і в браузері телефону . Підтримується сучасними сенсорними пристроями .

Примітка . Майте на увазі, що оскільки основним входом (можливостями) ПК на поверхневому ПК є миша, то в кінцевому підсумку це буде синя посилання, навіть якщо це окремий (планшетний) екран. Браузери завжди (повинні) завжди за замовчуванням максимально точні можливості введення даних.


Дякую, це було б зручно! Однак я спробував це з Chrome у мобільному режимі, але це не вийшло - коли я його "постукав", він все одно став синім ...
Simon Ferndriger

1
@SimonFerndriger Це лише обмеження розробників Chrome. Спробуйте відкрити посилання на фактичному пристрої, який стосується лише дотику.
Jason T Featheringham

1
Працює на iPad Chrome / Safari порівняно з OS X Chrome / Safari. Дякую! Нарешті, вишукане рішення, яке ви хочете отримати для такого невеликого візуального питання.
rakaloof

3
Я просто спробував це на своєму фактичному iPhone 6S під керуванням iOS 11, і посилання вийшло синім кольором.
Лукас Петро

1
Також спробували це з Nexus 5X під керуванням Android 8.1.0 та Chrome 68.0.3440.91. Посилання стало синім.
Тревін Евері

12

Я зіткнувся з тією ж проблемою (в моєму випадку з мобільними браузерами Samsung), і тому я натрапив на це питання.

Завдяки відповіді Калсала я знайшов те, що, на мою думку, виключає практично всі браузери настільних ПК, оскільки це, здається, розпізнається мобільними браузерами, які я спробував (див. Скріншот із складеної таблиці: таблиця виявлення функцій вказівника CSS ).

Веб-документи MDN заявляють, що це

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

.

Я виявив, що вказівник: грубо - це те, що невідомо всім браузерам настільних ПК у доданій таблиці, але відомо всім мобільним браузерам в одній таблиці. Це здається найбільш ефективним вибором, оскільки всі інші значення ключових слів вказівника дають непослідовні результати.

Отже, ви можете побудувати медіа-запит на зразок Calsal описаний але трохи змінений. Для виключення всіх сенсорних пристроїв використовується зворотна логіка.

Сас-мікс:

@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 настільним ПК.


Дякую @DmitriPavlutin, згідно таблиці (коли вона була складена), це повинно бути, але я можу поглянути інший погляд.
ПрограмістПер

@DmitriPavlutin Ви справді правильні. Оновить відповідь
ПрограмістPer

1
Ви маєте на увазі, що він не працює на Firefox Desktop, якщо він використовується виключно сенсорним пристроєм? Це чудово працює з усім, що я спробував.
FuzzeeLowgeek

@FuzzeeLowgeek Звучить добре! Востаннє я перевіряв 2018-08-23, тож якщо ви зможете це підтвердити точно, можливо, я можу оновити відповідь ще раз?
ПрограмістPer

9

Відповідно до відповіді Джейсона, ми можемо адресувати лише ті пристрої, які не підтримують наведенні чистих запитів css media. Ми також можемо адресувати лише ті пристрої, які підтримують наведення курсора, як відповідь moogal у подібному питанні @media not all and (hover: none). Це виглядає дивно, але це працює.

Я зробив Sass mixin з цього для легшого використання:

@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 */
}

Я люблю mixins. Ось так я використовую курсор миші лише для цільових пристроїв, які підтримують його:

@mixin on-hover {
    @media (hover: hover) and (pointer: fine) {
        &:hover {
            @content;
        }
    }
}

button {
    @include on-hover {
        color: blue;
    }
}

це зовсім не працює. у вас є наведення: жодного в медіа-запиті щодо підтримуваної сумішшю, що підтримується? вам потрібен вказівник: грубо, як за іншою відповіддю тут.
Allan Nienhuis

Ви навіть пробували це чи просто говорите, що це не працює, тому що це виглядає дивно? Ось чому я написав "Це виглядає дивно" .. І це працює для мене без вказівника: грубо.
Calsal

Я мав деякі непослідовні результати з CSS-підходом до цього на моєму OnePlus 5T (і в Chrome, і в Firefix). Це працювало чудово на iOS, але я не міг змусити його працювати на OnePlus. Я ретельно перевірив, використовуючи будь-який вказівник та наведення курсора
Зет

6

Зараз я маю справу з подібною проблемою.

У мене одразу виникають два основні варіанти: (1) перевірка ряду користувача або (2) підтримка окремих мобільних сторінок за допомогою іншої URL-адреси та надання користувачам вибору того, що їм краще.

  1. Якщо ви можете використовувати мову інтернет-канальної стрічки, наприклад PHP або Ruby, ви можете перевірити рядок користувача пристрою, який запитує сторінку, і просто подавати той же вміст, але <link rel="mobile.css" />замість звичайного стилю.

Рядки користувачів містять ідентифікаційну інформацію про браузер, рендерінг, операційну систему тощо. Ви вирішуватимете, які пристрої "сенсорні" та нетипові. Можливо, ви зможете знайти цю інформацію десь доступну і відобразити її у своїй системі.

A. Якщо вам дозволяється ігнорувати старі браузери , вам потрібно просто додати єдине правило до звичайного немобільного css, а саме: EDIT : Erk. Провівши кілька експериментів, я виявив, що наведене нижче правило також вимикає можливість слідувати посиланнями у веб-браузерах, окрім того, що лише вимикає естетичні ефекти - див. Http://jsfiddle.net/3nkcdeao/
Як таке, у вас буде бути трохи вибірковішим щодо того, як ви змінюєте правила для мобільного випадку, ніж те, що я показую тут, але це може бути корисною відправною точкою:

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

Як сторонне позначення, вимкнення подій-подій на батьківщині, а потім явне включення їх до дитини в даний час призводить до того, що будь-які ефекти наведення на батьків знову стануть активними, якщо входить дочірній елемент :hover.
Побачити http://jsfiddle.net/38Lookhp/5/

B. Якщо ви підтримуєте застарілі веб-рендери, вам доведеться зробити трохи більше роботи в порядку видалення будь-яких правил, які встановлювали спеціальні стилі протягом :hover. Щоб заощадити час кожного, ви можете просто хочете побудувати автоматизоване копіювання + SED команди , яка запускається на стандартних таблицях стилів для створення мобільних версій ING. Це дозволить вам просто написати / оновити стандартний код і очистити будь-які стильові правила, які використовуються :hoverдля мобільної версії ваших сторінок.

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

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

  1. (II) Ви можете насправді поєднати перші два і (якщо ви підозрюєте, що користувач перейшов на неправильну версію сторінки), ви можете запропонувати їм переключитися в / з дисплея мобільного типу або просто мати десь посилання, яке дозволяє користувачам переходити вперед і назад. Як уже зазначалося, @media запити також можуть бути корисними для визначення того, що використовується для відвідування.

  2. (III) Якщо ви вирішили отримати jQuery рішення, коли дізнаєтесь, які пристрої "сенсорні", а які ні, може виявити, що на пристроях із сенсорним екраном наведення курсора не буде проігноровано .


pointer-events- це дивовижно! Це саме те, що я шукав, велике спасибі!
Саймон Фендрігер

1
@SimonFerndriger Ну, я сподіваюся, що корисно йти вперед. Не забудьте зауважити, що на сьогоднішній день <a>посилання можуть бути недоступними pointer-events:none. При будь-якій удачі це пізніше зміниться - або CSS 3.x або 4.0+ матиме pointer-events:navigation-onlyабо подібне.
SeldomNeedy

6

спробуйте це:

@media (hover:<s>on-demand</s>) {
    button:hover {
        background-color: #color-when-NOT-touch-device;
    }
}

ОНОВЛЕННЯ: на жаль, W3C видалив цю властивість із специфікацій ( https://github.com/w3c/csswg-drafts/commit/2078b46218f7462735bb0b5107c9a3e84fb4c4b1 ).


Це справді вирішило б проблему. Я ніколи про це не чув. У якій версії браузера це має працювати?
Саймон Ферндрігер

3
@SimonFerndriger caniuse.com/#feat=css-media-interaction і ще деяка інформація: dev.opera.com/articles/media-features
Скептик

Добре ... Він не має широкої підтримки браузера.
Джакомо Паїта

Круто! Дякую за таке зручне рішення. Сподіваюся, він буде доданий до стандартів W3C.
GProst

радий, що можу допомогти ^^
Маруен Мірі

5

Ви можете використовувати Modernizr JS (див. Також цю відповідь StackOverflow ) або зробити власну функцію 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;
}

Це також запропонував @blade - проте використання htmlтегу замість bodyтегу може трохи полегшити його читання. Це власне рішення, яке я зараз використовую. В будь-якому випадку, дякую Вам.
Simon Ferndriger

1

Для мене це було корисно: посилання

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");
                    }
                }
            }
        }
    }
}

1

Це також можливе вирішення, але вам доведеться пройти свій 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>

Джерело

Ps Але слід пам’ятати, на ринок з'являється все більше сенсорних пристроїв, які одночасно підтримують введення миші.


0

Це, можливо, ще не є ідеальним рішенням (і це з jQuery), але, можливо, це напрямок / концепція, над якою працювати: а як зробити це навпаки? Що означає деактивацію:: навести курсор css за замовчуванням та активувати їх, якщо подія переміщення миші виявлена ​​десь у документі. Звичайно, це не працює, якщо хтось деактивував 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");
});

1
Одна з проблем полягає в тому, що це також .mousemove () при натисканні на щось на сенсорних пристроях.
lars at upstruct

1
І ви, ймовірно, спровокуєте цю подію безперервно, тим самим впливаючи на продуктивність. Якщо це спрацює, то краще вам скористатися$('body').one.('mousemove', ...)
Саймон Ферндрігер

0

Спробуйте це (у цьому прикладі я використовую фон і колір фону):

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;
}

0

Брудний спосіб ... Не елегантний, але найпростіший спосіб, який може вас врятувати.

Видаліть усе, що характеризує наведення вказівника.

.your-class:hover:before {
  color: blue;
  background: linear-gradient(to bottom, rgba(231,56,39,0) 0%, #aaaaaa 100%);
}

@media all and (min-width:320px) and (max-width: 960px) {
    .your-class:hover:before {
    color: black;
    background: transparent;
  }
}

0

Якщо ваша проблема полягає в тому, коли ви торкаєтесь / торкаєтесь андроїда та цілого дива, покритого синім прозорим кольором! Тоді вам потрібно просто змінити

Курсор: Вказівник; ДО КУРСОРУ: ЗАМОВЛЕННЯ;

використовуйте mediaQuery для приховування в мобільному телефоні / планшеті.

Це працює для мене.


-1

Спробуйте це просте рішення jquery 2019, хоча його вже минуло;

  1. додайте цей плагін до голови:

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

  2. додайте це до js:

    $ ("*"). on ("touchchend", функція (e) {$ (this) .фокус ();}); // стосується всіх елементів

  3. деякі запропоновані варіанти цього:

    $ (": введення,: прапорець"). on ("touchchend", функція (e) {(this) .фокус);}); // вкажіть елементи

    $ ("*"). on ("клацніть, торкніться", функція (e) {$ (це) .фокусувати ();}); // включити подію натискання

    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/


2
У 2019 році вам не потрібно використовувати jQuery - WebAPI досить потужний і підтримує всі основні функції.
акме

Я ... jQuery у 2019 році? Як щодо Flash? Хехехе.
rema.io
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.