如何删除/忽略:在触摸设备上悬停css样式

Sim*_*ger 111 html css hover touch

:hover如果用户通过触摸设备访问我们的网站,我想忽略所有CSS声明.因为:hoverCSS没有意义,如果平板电脑在点击/点击时触发它,它甚至会令人不安,因为它可能会坚持直到元素失去焦点.说实话,我不知道为什么触摸设备:hover首先需要触发- 但这是现实,所以这个问题也是现实.

a:hover {
   color:blue;
   border-color:green;
   // etc. > ignore all at once for touch devices
}
Run Code Online (Sandbox Code Playgroud)

那么,(如何):hover在声明触摸设备之后,我可以一次性删除/忽略所有CSS 声明(不必知道每一个)吗?

bla*_*ade 135

这个问题有多种解决方案.

Quick'n'dirty - 删除:使用JS的悬停样式

您可以删除包含:hover使用Javascript的所有CSS规则.这样做的好处是不必触摸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) {}
}
Run Code Online (Sandbox Code Playgroud)

限制:样式表必须托管在同一个域上(这意味着没有CDN).禁用混合鼠标和触摸设备(如Surface)上的悬停,这会损害用户体验.

仅限CSS - 使用媒体查询

将所有:悬停规则放在一个@media块中:

@media (hover: hover) {
    a:hover { color: blue; }
}
Run Code Online (Sandbox Code Playgroud)

或者,覆盖所有悬停规则(与旧浏览器兼容):

a:hover { color: blue; }

@media (hover: none) {
    a:hover { color: inherit; }
}
Run Code Online (Sandbox Code Playgroud)

限制:在使用WebView时,仅适用于iOS 9.0 +,Chrome for Android或Android 5.0+.hover: hover打破旧浏览器上的悬停效果,hover: none需要覆盖所有先前定义的CSS规则.两者都与混合鼠标和触摸设备不兼容.

最强大的 - 使用特殊的CSS类并通过JS检测触摸

此方法需要预先添加所有悬停规则body.hasHover.(或您选择的班级名称)

body.hasHover a:hover { color: blue; }
Run Code Online (Sandbox Code Playgroud)

hasHover类可以使用加入hasTouch()从第一个例子:

if (!hasTouch()) {
    document.body.className += ' hasHover';
}
Run Code Online (Sandbox Code Playgroud)

然而,这与前面的例子中的混合触摸设备具有相同的问题,这使我们得到了最终的解决方案.移动鼠标光标时启用悬停效果,每当检测到触摸时禁用悬停效果.

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();
Run Code Online (Sandbox Code Playgroud)

这应该基本上在任何浏览器中工作,并根据需要启用/禁用悬停样式.试试这里:https://jsfiddle.net/dkz17jc5/19/

  • 此解决方案不适用于混合设备,其中悬停应适用于鼠标但不适用于触摸事件 (3认同)
  • @Haneev在大多数情况下都是正确的,尽管不是针对您的具体情况.使规则工作会增加代码的复杂性,这将使得答案更难理解.我会建议拆分规则或使用第二种解决方案,无论如何它都更加强大.但是,如果您可以改进第一个解决方案而不会使其太复杂,那么非常欢迎您建议编辑. (2认同)

Hải*_*Bùi 65

2020 解决方案 - 仅 CSS - 无 Javascript

媒体悬停媒体指针一起使用将帮助您解决此问题。在 chrome Web 和 android mobile 上测试。我知道这个老问题,但我没有找到任何这样的解决方案。

@media (hover: hover) and (pointer: fine) {
  a:hover { color: red; }
}
Run Code Online (Sandbox Code Playgroud)
<a href="#" >Some Link</a>
Run Code Online (Sandbox Code Playgroud)

  • IE 不支持仅供参考 (2认同)
  • 无法在 Firefox 84 上运行 (2认同)
  • 不适用于带触摸屏的笔记本电脑上的 Chrome 92。 (2认同)
  • 我认为这是可能的,因为指针:精细媒体查询评估的不是实际使用的指针,而是主指针 - 即鼠标。不过它在 iOS 上运行得很好。 (2认同)
  • @MaciejKrawczyk因为你的触摸屏将触发指针的“粗略”属性。指针有 2 个选项。细与粗。Fine = 主要输入机制包括精确的定点设备。粗略 = 主要输入机制包括精度有限的指点设备。AKA,鼠标 = 很好,但你的手指会很粗糙 (2认同)

Jas*_*ham 37

指针适应救援!

由于暂时没有触及,您可以使用:

a:link {
   color: red;
}

a:hover {
   color:blue;
}

@media (hover: none) {
   a:link {
      color: red;
   }
}
Run Code Online (Sandbox Code Playgroud)

在桌面浏览器和手机浏览器中查看此演示.由现代触摸设备支持.

注意:请记住,由于Surface PC的主要输入(功能)是鼠标,它最终将成为蓝色链接,即使它是一个分离的(平板电脑)屏幕.浏览器将(应该)始终默认为最精确的输入功能.

  • 我刚刚在运行iOS 11的iPhone 6S上试过这个,而且链接变成了蓝色. (3认同)

Cal*_*sal 14

根据Jason 的回答,我们只能解决不支持使用纯 css 媒体查询悬停的设备。我们还可以仅解决支持悬停的设备,例如moogal在类似问题中的回答,使用 @media not all and (hover: none). 它看起来很奇怪,但它有效。

为了更容易使用,我做了一个 Sass mixin:

@mixin hover-supported {
    @media not all and (hover: none) {
        &:hover {
            @content;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

2019 年 5 月 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 */
}
Run Code Online (Sandbox Code Playgroud)

特定目标的示例:

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

@media (hover: hover) and (pointer: fine) {
    /* Desktops with mouse */
}
Run Code Online (Sandbox Code Playgroud)

我喜欢 mixin,这就是我如何使用我的悬停 mixin 来只定位支持它的设备:

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

button {
    @include on-hover {
        color: blue;
    }
}
Run Code Online (Sandbox Code Playgroud)


Pro*_*Per 8

我遇到了同样的问题(在我的情况下与三星移动浏览器),因此我偶然发现了这个问题.

感谢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;
    }
}
Run Code Online (Sandbox Code Playgroud)

编译CSS:

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

我在研究问题后创建的这个要点中也有描述. Codepen用于实证研究.

更新:截至编写此更新,2018-08-23,并由@DmitriPavlutin指出这种技术似乎不再适用于Firefox桌面.


Sel*_*edy 7

我目前正在处理类似的问题.

我立即有两个主要选项:(1)用户字符串检查,或(2)使用不同的URL维护单独的移动页面,并让用户选择对他们更好的选项.

  1. 如果您能够使用互联网风管磁带语言(如PHP或Ruby),则可以检查请求页面的设备的用户字符串,并只使用相同的内容而<link rel="mobile.css" />不是正常样式.

用户字符串具有关于浏览器,渲染器,操作系统等的识别信息.由您来决定哪些设备是"触摸"而非非触摸.您可以在某处找到此信息并将其映射到您的系统中.

A.如果您被允许忽略旧浏览器,您只需要向普通的非移动css添加一条规则,即: EDIT:Erk.在做了一些实验之后,我发现下面的规则还禁用了在webkit浏览器中跟踪链接的能力,以及仅仅导致美学效果被禁用 - 请参阅http://jsfiddle.net/3nkcdeao/
因此,你将拥有对于你如何修改移动案例的规则比我在这里展示的更具选择性,但它可能是一个有用的起点:

* { 
    pointer-events: none !important; /* only use !important if you have to */
}
Run Code Online (Sandbox Code Playgroud)

作为旁注,禁用父项上的指针事件然后在子项上显式启用它们会导致父项上的任何悬停效果在子元素进入时再次变为活动状态:hover.
http://jsfiddle.net/38Lookhp/5/

B.如果你支持传统的网络渲染器,你将不得不做更多的工作,删除任何设置特殊样式的规则:hover.为了节省每个人的时间,您可能只想构建一个自动复制+ sed ing命令,您可以在标准样式表上运行该命令来创建移动版本.这样您就可以编写/更新标准代码并清除:hover用于移动版本页面的任何样式规则.

  1. (I)或者,只需让您的用户知道除了您的website.com之外,您还拥有适用于移动设备的m.website.com.尽管subdomaining是最常见的方式,但您还可以对给定URL进行其他可预测的修改,以允许移动用户访问已修改的页面.在那个阶段,您需要确保他们每次导航到网站的其他部分时都不必修改URL.

再次在这里,你可能只需要在样式表中添加一两个额外的规则,或者使用sed或类似的实用程序强制做一些稍微复杂的事情.它可能是最容易应用的:不是你的样式规则,比如div:not(.disruptive):hover {...你将class="disruptive"使用js或服务器语言添加到为移动用户做烦人事情的元素,而不是使用CSS.

  1. (II)你实际上可以合并前两个和(如果你怀疑用户已经徘徊到错误版本的页面)你可以建议他们切换到/移出移动式显示器,或者只是在某个地方有一个链接允许用户来回翻转.如前所述,@ media查询也可能用于确定用于访问的内容.

  2. (III)如果您知道哪些设备是"触摸"而哪些设备不是"触摸",那么您可能会发现jQuery解决方案,您可能会发现在触摸屏设备上不会忽略CSS悬停有用.


Mar*_*iri 6

试试这个:

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

更新:遗憾的是W3C已从规范中删除了此属性(https://github.com/w3c/csswg-drafts/commit/2078b46218f7462735bb0b5107c9a3e84fb4c4b1).

  • @SimonFerndriger http://caniuse.com/#feat=css-media-interaction以及更多信息:https://dev.opera.com/articles/media-features/ (3认同)

Gia*_*ita 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');
} 
Run Code Online (Sandbox Code Playgroud)

检测触摸的支持,在浏览器中的事件,然后分配一个普通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;
}
Run Code Online (Sandbox Code Playgroud)