Comment supprimer/ignorer: hover CSS style sur les appareils tactiles
je veux ignorer toutes les déclarations css :hover
si un utilisateur visite notre site web via un appareil tactile. Parce que le CSS :hover
n'a pas de sens, et il peut même être dérangeant si une tablette le déclenche sur click/tap parce qu'alors il pourrait coller jusqu'à ce que l'élément perd la mise au point. Pour être honnête, je ne sais pas pourquoi les appareils tactiles sentir la nécessité de déclencher :hover
en premier lieu - mais c'est la réalité, donc ce problème est la réalité.
a:hover {
color:blue;
border-color:green;
// etc. > ignore all at once for touch devices
}
Alors, comment puis-je supprimer/ignorer toutes les CSS :hover
déclarations à la fois (sans avoir à connaître chacun) pour les appareils tactiles d'après les avoir déclarés?
11 réponses
il existe plusieurs solutions à ce problème.
Quick n'dirty - supprimer :hover styles à l'aide de JS
vous pouvez supprimer toutes les règles CSS contenant :hover
en utilisant Javascript. Cela a l'avantage de ne pas avoir à toucher CSS et d'être compatible même avec les navigateurs plus anciens.
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) {}
}
Limitations: les feuilles de style doivent être hébergées sur le même domaine (ce qui signifie pas de CDNs). Désactiver plane sur une surface mixte souris & dispositifs tactiles comme une surface qui fait mal aux UX.
CSS-seulement - utiliser les media queries
placez toutes vos règles de vol stationnaire dans un @media
bloc:
@media (hover: hover) {
a:hover { color: blue; }
}
ou alternativement, outrepasser toutes vos règles de vol stationnaire (compatible avec les navigateurs plus anciens):
a:hover { color: blue; }
@media (hover: none) {
a:hover { color: inherit; }
}
Limitations: fonctionne uniquement sur iOS 9.0+, Chrome pour Android ou Android 5.0 + lors de l'utilisation WebView. hover: hover
casse les effets de vol stationnaire sur les navigateurs plus anciens, hover: none
doit passer outre à toutes les règles CSS définies précédemment. Les deux sont incompatible avec la souris mixte et les dispositifs tactiles .
le plus robuste - utiliser la classe spéciale CSS et détecter le toucher via JS
cette méthode doit précéder toutes les règles de vol stationnaire avec body.hasHover
. (ou un nom de classe de votre choix)
body.hasHover a:hover { color: blue; }
le hasHover
la classe peut être ajoutée en utilisant hasTouch()
du premier exemple:
if (!hasTouch()) {
document.body.className += ' hasHover';
}
cependant, cela a le même problème avec les dispositifs de toucher mixtes que les exemples précédents, ce qui nous amène à la solution ultime. Activez les effets de vol stationnaire chaque fois qu'un curseur de la souris est déplacé, désactivez les effets de vol stationnaire chaque fois qu'un contact est détecté.
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();
cela devrait fonctionner essentiellement dans n'importe quel navigateur et activer/désactiver les styles de vol stationnaire selon les besoins. Essayer ici: https://jsfiddle.net/dkz17jc5/19 /
adaptation de pointeur à la rescousse!
comme il n'a pas été touché depuis longtemps, vous pouvez utiliser:
a:link {
color: red;
}
a:hover {
color:blue;
}
@media (hover: none) {
a:link {
color: red;
}
}
voir cette démo dans votre navigateur de bureau et votre navigateur de téléphone . Pris en charge par dispositifs de toucher modernes .
Note : gardez à l'esprit que depuis L'entrée primaire D'un PC de Surface (capacité) est une souris, il finira par être un lien Bleu, même si c'est un écran détaché (tablette). Les navigateurs seront (devraient) toujours par défaut à la capacité d'entrée la plus précise.
je fais face à un problème similaire actuellement.
il y a deux principales options qui me viennent immédiatement à l'esprit: (1) Vérification de la chaîne de caractères de l'utilisateur, ou (2) maintien de pages mobiles séparées en utilisant une URL différente et en demandant aux utilisateurs de choisir ce qui est mieux pour eux.
- si vous êtes en mesure d'utiliser un langage Internet duct-tape tel que PHP ou Ruby, vous pouvez vérifier le chaîne de l'utilisateur de l'appareil la demande d'une page, et il suffit de servir le même contenu, mais avec un
<link rel="mobile.css" />
au lieu de le style normal.
Utilisateur chaînes d'informations sur l'identification du navigateur, moteur de rendu, système d'exploitation, etc. Ce serait à vous de décider quels appareils sont "touch" versus non-touch. Vous pourrez peut-être trouver ces renseignements quelque part et les intégrer à votre système.
A. Si vous êtes autorisé à ignorer Vieux navigateurs , vous avez juste à ajouter une règle unique à la normale, non-mobile css, à savoir: EDIT : Erk. Après avoir fait quelques expériences, j'ai découvert que la règle ci-dessous désactive également la possibilité de suivre les liens dans les navigateurs webkit en plus de juste causer des effets esthétiques à être désactivé - voir http://jsfiddle.net/3nkcdeao/
en tant que tel, vous devrez être un peu plus sélectif quant à la façon dont vous modifiez règles pour le mobile case que ce que je montre ici, mais il peut être un point de départ utile:
* {
pointer-events: none !important; /* only use !important if you have to */
}
en tant que pointeur latéral, désactivant les événements sur un parent et les rendant explicitement possibles sur un enfant, provoque actuellement des effets de hover sur le parent à redevenir actif si un élément enfant entre :hover
.
voir http://jsfiddle.net/38Lookhp/5 /
B. Si vous soutenez legacy web-renders, vous aurez à faire un peu plus de travail le long des lignes de supprimer toutes les règles qui établissent des styles spéciaux pendant :hover
. Pour gagner du temps, vous pouvez simplement construire une commande de copie automatisée + sed ing que vous exécutez sur vos feuilles de style standard pour créer les versions mobiles. Cela vous permettrait d'écrire/mettre à jour le code standard et effacer toutes les règles de style qui utilisent :hover
pour la version mobile de vos pages.
- (I) alternativement, il suffit de faire savoir à vos utilisateurs que vous avez un m.website.com pour les appareils mobiles en plus de votre website.com . Bien que le sous -domaining soit le moyen le plus courant, vous pouvez également avoir d'autres modifications prévisibles d'une URL donnée pour permettre aux utilisateurs mobiles d'accéder aux pages modifiées. À ce stade, vous voulez être sûr qu'ils n'ont pas à modifier L'URL chaque fois qu'ils naviguent vers une autre partie de le site.
encore une fois ici, vous pouvez être en mesure d'ajouter une ou deux règles supplémentaires aux feuilles de style OU être forcé de faire quelque chose un peu plus compliqué en utilisant sed ou une utilité similaire. Il serait probablement plus facile de l'appliquer :pas à vos règles de style comme div:not(.disruptive):hover {...
où vous ajouteriez class="disruptive"
aux éléments faisant des choses ennuyeuses pour les utilisateurs mobiles en utilisant js ou le langage serveur, au lieu de munging le CSS.
-
(II) vous pouvez en fait combiner les deux premiers et (si vous pensez qu'un utilisateur s'est égaré vers la mauvaise version d'une page) vous pouvez suggérer qu'ils basculent dans/hors de l'affichage de type mobile, ou tout simplement avoir un lien quelque part qui permet aux utilisateurs de flop d'aller-retour. Comme nous l'avons déjà dit, les questions sur @media pourraient aussi être utiles pour déterminer ce qui est utilisé pour visiter.
-
(III) Si vous êtes pour un solution jQuery une fois que vous savez quels appareils sont "touch" et lesquels ne le sont pas, vous trouverez peut-être que CSS hover n'est pas ignoré sur les appareils à écran tactile utile.
essayez ceci:
@media (hover:<s>on-demand</s>) {
button:hover {
background-color: #color-when-NOT-touch-device;
}
}
mise à jour: malheureusement W3C a supprimé cette propriété de la spécification ( https://github.com/w3c/csswg-drafts/commit/2078b46218f7462735bb0b5107c9a3e84fb4c4b1 ).
vous pouvez utiliser Modernizr JS( Voir Aussi ce réponse StackOverflow ), ou faire une fonction JS personnalisée:
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');
}
à détecter l'appui de la touche "1519120920 de l'événement" dans le navigateur, puis attribuer un 151920920 de la propriété", traversant l'élément avec la html.no-touch
de la classe, comme ceci:
html.touch a {
width: 480px;
}
/* FOR THE DESKTOP, SET THE HOVER STATE */
html.no-touch a:hover {
width: auto;
color:blue;
border-color:green;
}
j'ai rencontré le même problème (dans mon cas avec les navigateurs Samsung mobile) et donc je suis tombé sur cette question.
merci à réponse de Calsal j'ai trouvé quelque chose qui je crois va exclure pratiquement tous les navigateurs de bureau parce qu'il semble être reconnu par les navigateurs mobiles que j'ai essayé (voir capture d'écran d'une table compilée: CSS pointer feature detection table ).
MDN web docs state that
le pointeur css @media peut être utilisé pour appliquer des styles basés sur si l'utilisateur principal du mécanisme d'entrée est un dispositif de pointage, et dans l'affirmative, quelle est son exactitude?
.
ce que j'ai découvert est que pointeur: grossier est quelque chose qui est inconnu à tous les navigateurs de bureau dans la table jointe, mais connu de tous les navigateurs mobiles dans le même tableau. Cela semble être le choix le plus efficace parce que toutes les autres valeurs de mot-clé de pointeur donnent des résultats incohérents.
donc vous pouvez construire une requête média comme Calsal décrit mais légèrement modifié. Il utilise une logique inversée pour exclure tous les appareils tactiles.
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;
}
}
Compiled CSS:
a {
color: green;
border-color: blue;
}
@media not all and (pointer: coarse) {
a:hover {
color: blue;
border-color: green;
}
}
il est également décrit dans ce gist j'ai créé après des recherches sur le problème. Codepen pour la recherche empirique.
mise à JOUR : Au moment d'écrire cette mise à jour, 2018-08-23, et souligné par @DmitriPavlutin cette technique ne semble plus fonctionner avec Firefox desktop.
c'est aussi une solution possible, mais vous devrez passer par votre css et ajouter une classe .no-touch
avant vos styles de vol stationnaire.
Javascript:
if (!("ontouchstart" in document.documentElement)) {
document.documentElement.className += " no-touch";
}
exemple 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. Mais il ne faut pas oublier qu'il y a de plus en plus d'appareils tactiles sur le marché, qui prennent également en charge l'entrée des souris.
ce n'est peut-être pas encore une solution parfaite (et c'est avec jQuery) mais c'est peut-être une direction / concept sur lequel travailler: qu'en est-il de le faire dans l'autre sens? Ce qui signifie désactiver les États CSS hover par défaut et les activer si un événement mousemove est détecté n'importe où sur le document. Bien sûr, cela ne fonctionne pas si quelqu'un a désactivé js. Qu'est-ce qui pourrait dire d'autre contre le fait de le faire de cette façon?
peut-être comme ceci:
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");
});
il a été utile pour moi: lien
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");
}
}
}
}
}
}
Selon Jasons réponse nous pouvons aborder uniquement pour les appareils qui ne supportent pas de passer pur css media queries. Nous pouvons également traiter que les dispositifs qui prennent en charge le vol stationnaire, comme moogals réponse dans une question similaire, avec
@media not all and (hover: none)
. Il semble bizarre, mais ça fonctionne.
j'en ai fait un mélange Sass pour en faciliter l'utilisation:
@mixin hover-supported {
@media not all and (hover: none) {
&:hover {
@content;
}
}
}
ce qui suit changerait la couleur de fond de .container
du rouge au bleu en vol stationnaire pour les dispositifs qui le supportent et restent rouges pour les dispositifs tactiles:
.container {
background-color: red;
@include hover-supported() {
background-color: blue;
}
}
cela peut être résolu avec sass/scss et une requête multimédia avec le point de rupture désiré.
.myclass {
background-color: blue;
&:hover {
@media screen and (max-width: 320px) {
background-color: red;
}
}
}