支持悬停的设备的媒体查询

moo*_*gal 29 css hover touch media-queries interaction-media-features

我想为支持悬停的浏览器(例如桌面浏览器)和不支持悬停的浏览器(例如触摸屏设备)提供单独的行为.具体来说,我想在支持它的浏览器上声明悬停状态,但不支持那些不支持浏览器的浏览器,以避免移动浏览器使用额外的点击模拟它,因为这会打破页面上的其他交互 - 通过不定义悬停这些浏览器的状态可以避免.

我已经阅读了" 交互媒体查询"功能,看起来它应该可以解决问题.我可以做类似的事情:

@media (hover: none) {
  /* behaviour for touch browsers */
}
Run Code Online (Sandbox Code Playgroud)

根据CanIUse,除了IE11和Firefox之外,它还支持我需要支持的所有浏览器.

所以我想知道我是否可以反过来做 - 因为主要的触控设备都支持它,然后否定它:

@media not (hover: none) {
  /* behaviour for desktop browsers */
}
Run Code Online (Sandbox Code Playgroud)

但是,这似乎根本不起作用.

我正在尝试做的伪代码示例:

.myelement {
  /* some styling */
  /* note: no hover state here */
}
@media(this device supports hover) {
  .myelement:hover {
    /* more styling */
  }
}
Run Code Online (Sandbox Code Playgroud)

那么,有没有办法让这项工作按照预期的方式进行,或者我是否走错了轨道?

art*_*tin 39

not 应该是媒体类型(屏幕,打印,所有等)的前缀,而不是媒体功能(悬停,点等).

错误:

@media not (hover: none)
Run Code Online (Sandbox Code Playgroud)

正确:

@media not all and (hover: none)
Run Code Online (Sandbox Code Playgroud)

是的,它不直观而且很奇怪.来源(见评论).

因此,您不需要javascript来替换媒体查询的结果.

  • 好戏!请注意,IE11似乎完全忽略了这条规则.使用另一个特定于IE的黑客,它似乎有以下作用(尽管它是变通方法的否定版本):`@ media not all和(hover:none),( - ms-high-contrast:none){` (4认同)
  • 既不是@media(hover:none)`也不是否定`@media不是全部而且(hover:none)`在Firefox中做任何事情.那个浏览器不支持hover https://bugzilla.mozilla.org/show_bug.cgi?id=1035774但是应该没有办法编写`not`这样如果'not`的主题未定义/无法识别然后它的计算结果为false(并且整个媒体查询的计算结果为true)? (3认同)
  • 愚蠢的问题,为什么不使用 `@media (hover) {...desktop styles...}` ? (3认同)
  • `not(hover:none)`不是,或者至少不再是错的.根据媒体查询4,这是正确的.任何浏览器都不支持它,令人沮丧.请参阅/sf/ask/1711917091/#24456052 (2认同)
  • 实际上,我不明白为什么所有人都试图否定可以通过关键字“hover”而不是“none”直接实现的条件。也许它现在已经实现,但不是在提出问题的时候实现的,请参阅[此处](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/hover)以获取更多信息! (2认同)

Dek*_*kel 14

从规格:

none

表示主指向系统无法悬停,或者没有指向系统.示例包括使用绘图笔的触摸屏和屏幕.
指向系统可以悬停,但这样做不方便且不是它们使用的正常方式的一部分,也匹配该值.

例如,长按被视为悬停的触摸屏将匹配hover:none.

如果您的浏览器(移动/触摸)支持长按以模拟悬停,则使用hover: none不起作用.您可以做的只是使用默认值并覆盖它(使用默认的css优先级):

body {
    background: red;
}

@media (hover: hover) {
  body {
    background: blue;
  }
}
Run Code Online (Sandbox Code Playgroud)

桌面将具有blue背景,移动/触摸将具有red背景

请查看以下示例:https:
//jsfiddle.net/mcy60pvt/1/

要检查移动设备的长按选项,您可以使用以下示例:https:
//jsfiddle.net/mcy60pvt/3/

在上面的示例中,绿色块具有:hover桌面和移动设备的定义,但是对于桌面设备,背景将更改为yellow移动设备(通过长按)将更改为white.

这是最后一个例子的css:

body {
    background: red;
}
div.do-hover {
  border: 1px solid black;
  width: 250px;
  height: 250px;
  background: green;
}
div.do-hover:hover {
  background: white;
}

@media (hover: hover) {
  body {
    background: blue;
  }
  div.do-hover:hover {
    background: yellow;
  }
}
Run Code Online (Sandbox Code Playgroud)

在此示例中 - 不支持的浏览器:hover将以绿色背景查看悬停我框,而在"悬停"(触摸/长按)时 - 背景将变为白色.

更新

至于添加的伪代码:

.myelement {
    /* some styling #1 */
    /* note: no hover state here */
}
@media(hover: hover) {
    .myelement {
        /* some styling that override #1 styling in case this browser suppot the hover*/
    }
    .myelement:hover {
        /* what to do when hover */
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 好的,所以这是一个不同的问题.这就像问"我如何在只支持css3的浏览器中使用css4技巧?" :)好吧,大多数情况下你不能.如果Firefox忽略了`hover:hover`定义 - 你真的没有用它做的事情(在纯css中).您可以使用javascript将类添加到`body`元素并使用基于该类的css(is-firefox,is-support-hover,is-mobile等...) (3认同)

moo*_*gal 7

感谢Dekel的评论,我通过在JS中运行逻辑并应用类来解决这个问题:

例如

const canHover = !(matchMedia('(hover: none)').matches);
if(canHover) {
  document.body.classList.add('can-hover');
}
Run Code Online (Sandbox Code Playgroud)

然后在样式表中:

.myElement {
  background: blue;
}
.can-hover .myElement:hover {
  background: red;
}
Run Code Online (Sandbox Code Playgroud)

我在台式机Chrome,Safari和Firefox以及iOS Safari上测试了它,它按预期工作.


Fab*_*rts 6

你可以使用这个 Sass mixin 来设置悬停的样式,它将使用推荐:active的触摸设备替代品。适用于所有现代浏览器和 IE11。

/**
 Hover styling for all devices and browsers
 */
@mixin hover() {
    @media (hover: none) {
        -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
        &:active {
            @content;
        }
    }

    @media (hover: hover), all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
        &:hover {
            @content;
        }
    }
}

.element {
    @include hover {
         background: red;
    }
}
Run Code Online (Sandbox Code Playgroud)