CSS 支持悬停的设备的媒体查询
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/40532204/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Media query for devices supporting hover
提问by moogal
I'd like to provide separate behaviour for browsers supporting hover (e.g. desktop browsers) and ones which don't (e.g. touchscreen devices). Specifically I want to declare a hover state on browsers that support it, but not for browsers that don't, so as to avoid having mobile browsers emulate it with extra taps, as this breaks other interactions on the page - by not defining a hover state for those browsers this is avoided.
我想为支持悬停的浏览器(例如桌面浏览器)和不支持的浏览器(例如触摸屏设备)提供单独的行为。具体来说,我想在支持它的浏览器上声明一个悬停状态,但不是对于不支持它的浏览器,以避免移动浏览器通过额外的点击来模拟它,因为这会破坏页面上的其他交互 - 通过不定义悬停这些浏览器的状态是避免的。
I've read up on the Interaction Media Queriesfeature and it looks like it should do the trick. I'd be able to do something like:
我已经阅读了交互媒体查询功能,看起来它应该可以解决问题。我可以做这样的事情:
@media (hover: none) {
/* behaviour for touch browsers */
}
According to CanIUseit is available on all the browsers I need to support except IE11 and Firefox.
根据CanIUse,它可用于我需要支持的所有浏览器,但 IE11 和 Firefox 除外。
So I wondered if I could do it the other way around - since the main touch devices all support it, then negate it:
所以我想知道我是否可以反过来做 - 因为主要的触摸设备都支持它,然后否定它:
@media not (hover: none) {
/* behaviour for desktop browsers */
}
However, this doesn't seem to work at all.
但是,这似乎根本不起作用。
Pseudocode example of what I'm trying to do:
我正在尝试做的伪代码示例:
.myelement {
/* some styling */
/* note: no hover state here */
}
@media(this device supports hover) {
.myelement:hover {
/* more styling */
}
}
So, is there a way to make this work in the way intended, or am I down the wrong track?
那么,有没有办法按照预期的方式进行这项工作,还是我走错了路?
采纳答案by moogal
Thanks to Dekel's comments I solved this by running the logic in JS and applying a class instead:
感谢 Dekel 的评论,我通过在 JS 中运行逻辑并应用一个类来解决这个问题:
e.g.
例如
const canHover = !(matchMedia('(hover: none)').matches);
if(canHover) {
document.body.classList.add('can-hover');
}
Then in the stylesheet:
然后在样式表中:
.myElement {
background: blue;
}
.can-hover .myElement:hover {
background: red;
}
I've tested this on desktop Chrome, Safari and Firefox, and iOS Safari and it works as expected.
我已经在桌面 Chrome、Safari 和 Firefox 以及 iOS Safari 上对此进行了测试,它按预期工作。
回答by artin
not
should prefix media type (screen, print, all, etc) and not media feature (hover, point, etc).
not
应该为媒体类型(屏幕、打印、全部等)而不是媒体功能(悬停、点等)添加前缀。
Wrong:
错误的:
@media not (hover: none)
Correct:
正确的:
@media not all and (hover: none)
Yes, its unintuitive and weird. Source (see comments).
是的,它既不直观又奇怪。来源(见评论)。
So you do not need javascript to alternate result of media query.
所以你不需要 javascript 来替代媒体查询的结果。
回答by Dekel
From the specs:
从规格:
none
Indicates that the primary pointing system can't hover, or there is no pointing system. Examples include touchscreens and screens that use a drawing stylus.
Pointing systems that can hover, but for which doing so is inconvenient and not part of the normal way they are used, also match this value.For example, a touchscreen where a long press is treated as hovering would match hover: none.
none
表示主定点系统无法悬停,或者没有定点系统。示例包括触摸屏和使用绘图笔的屏幕。
可以悬停但不方便且不属于正常使用方式的指点系统也匹配此值。例如,长按被视为悬停的触摸屏将匹配悬停:无。
If your browser (mobile/touch) support long-press to simulate hover, the usage of hover: none
will not work. What you can do is just use a default value and override it (with default css precedence):
如果您的浏览器(移动/触摸)支持长按模拟悬停,hover: none
则无法使用。您可以做的只是使用默认值并覆盖它(使用默认 css 优先级):
body {
background: red;
}
@media (hover: hover) {
body {
background: blue;
}
}
Desktop will have blue
background and mobile/touch will have red
background
桌面将有blue
背景,移动/触摸将有red
背景
Check the following example:
https://jsfiddle.net/mcy60pvt/1/
检查以下示例:https:
//jsfiddle.net/mcy60pvt/1/
To check the long-press option of the mobile you can use this example:
https://jsfiddle.net/mcy60pvt/3/
要检查手机的长按选项,您可以使用此示例:https:
//jsfiddle.net/mcy60pvt/3/
In the above example the green block has :hover
definition for both desktop and mobile, however for desktop the background will change to yellow
and for mobile (with long-press) it will change to white
.
在上面的示例中,绿色块:hover
定义了桌面和移动设备,但是对于桌面设备,背景将更改为 ,yellow
而对于移动设备(长按),它将更改为white
。
Here is the css for the last example:
这是最后一个示例的 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;
}
}
In this example - browsers that don't support :hover
will view the hover mebox with green background, and while "hover" (touch/long-press) - the background will change to white.
在这个例子中 - 不支持的浏览器:hover
将查看带有绿色背景的悬停框,当“悬停”(触摸/长按)时 - 背景将变为白色。
update
更新
As for the added pseudo code:
至于添加的伪代码:
.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 */
}
}
回答by Fabian von Ellerts
You can use this Sass mixin to style the hover, it will use the recommended substitute :active
for touch devices. Works on all modern browsers and IE11.
你可以使用这个 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;
}
}
回答by Calsal
According to Artin′s answerwe can address only devices that support hover with pure css, with @media not all and (hover: none)
. It looks weird but it works.
根据Artin 的回答,我们只能解决支持使用纯 css 悬停的设备,使用@media not all and (hover: none)
. 它看起来很奇怪,但它有效。
I made a Sass mixin out of this for easier use:
为了更容易使用,我做了一个 Sass mixin:
@mixin hover-supported {
@media not all and (hover: none) {
&:hover {
@content;
}
}
}
The following would change background-color of .container
from red to blue on hover for devices that support hover, no change for touch devices:
.container
对于支持悬停的设备,以下将在悬停时将背景颜色从红色更改为蓝色,而触摸设备没有更改:
.container {
background-color: red;
@include hover-supported() {
background-color: blue;
}
}
回答by EoghanM
To support Firefox (see https://bugzilla.mozilla.org/show_bug.cgi?id=1035774), you need to potentially write some rules twice. Note, although not specified in the question I've added pointer: coarse
on the assumption that the purpose of these rules is to target mobile screens:
要支持 Firefox(请参阅https://bugzilla.mozilla.org/show_bug.cgi?id=1035774),您可能需要编写一些规则两次。请注意,虽然在我添加的问题中没有指定,但pointer: coarse
假设这些规则的目的是针对移动屏幕:
/* BEGIN devices that DON'T pinch/zoom */
/* If https://bugzilla.mozilla.org/show_bug.cgi?id=1035774
is fixed then we can wrap this section in a ...
@media not all and (pointer: coarse) and (hover: none) {
.. and do away with the 'NEGATE' items below */
.myelement {
/* some styling that you want to be desktop only (style as an anchor on desktop) */
font-size: 14px;
text-decoration: underline;
border: none;
}
/* END devices that DON'T pinch/zoom */
/* BEGIN devices that DO pinch/zoom */
@media (pointer: coarse) and (hover: none) {
.myelement {
/* style as a large button on mobile */
font-size: inherit; /* maintain e.g. larger mobile font size */
text-decoration: none; /* NEGATE */
border: 1px solid grey;
}
.myelement:hover {
/* hover-only styling */
}
}
/* END devices that DO pinch/zoom */
The combination of (pointer: coarse) and (hover: none)
should become more useful to target mobile devices as mobile screens become larger and we lose the correlation between pixel dimensions and mobile vs. desktop (already the case when you wish to distinguish between tablet and desktop)
(pointer: coarse) and (hover: none)
随着移动屏幕变得更大,并且我们失去了像素尺寸与移动设备与桌面设备之间的相关性(当您希望区分平板电脑和桌面设备时已经是这种情况),组合应该对定位移动设备更有用。