检测设备是否为触摸屏的媒体查询

在不使用触摸屏设备的情况下,使用媒体查询是最安全的方式吗?如果没有办法,你是否建议使用一个 JavaScript 解决方案,比如 !window.Touch或者 Modern izr?

125340 次浏览

现在,CSS 媒体查询可以用来定义具有特定交互功能的设备的样式,它的 得到广泛支持也是如此。

例如,hover 可以用来测试用户的主要输入机制是否可以悬停在元素上(在没有仿真的触摸设备中是不可能的)

@media (hover: none) {
a {
background: yellow;
}
}

其他交互式测试包括: 指针、任意指针、悬停和任意悬停

前一个答案

我建议使用 现代化并使用它的媒体查询特性。

if (Modernizr.touch){
// bind to touchstart, touchmove, etc. and watch `event.streamId`
} else {
// bind to normal click, mousemove, etc.
}

但是,使用 CSS,可以使用类似的伪类,例如 Firefox。你可以使用 : :-moz-system-meter (触摸启用)。但是这些特性并不适用于所有的浏览器。

对于 苹果设备,您可以简单地使用:

if (TouchEvent) {
//...
}

特别是 iPad:

if (Touch) {
// ...
}

但是,这些 不能在 Android 上工作

Modern izr 赋予了特征提取能力,而检测特征是 一个很好的编码方式,而不是基于浏览器的编码。

造型触摸元素

为了达到这个目的,Modizer 在 HTML 标签中添加了类。在这种情况下,touchno-touch,因此您可以通过在选择器前面加上。触摸。例如 .touch .your-container图片来源: Ben Swinburne

媒体类型不允许你检测触摸功能作为标准的一部分:

Http://www.w3.org/tr/css3-mediaqueries/

因此,没有办法通过 CSS 或媒体查询来实现 始终如一,您将不得不求助于 JavaScript。

不需要使用 Modernizr,你只需要使用普通的 JavaScript:

<script type="text/javascript">
var is_touch_device = 'ontouchstart' in document.documentElement;
if(is_touch_device) alert("touch is enabled!");
</script>

CSS4媒体查询草稿中实际上有一个属性。

“指针”媒体特性用于查询存在和 指向设备(如鼠标)的精度。如果设备具有 多个输入机制,建议 UA 报告 主电路的最小能力指针装置的特性 输入机制。此媒体查询采用以下值:

“没有”
- 该装置的输入机构不包括指向装置。

“粗糙”
- 该装置的输入机构包括一个精度有限的瞄准装置。

“很好”
- 该装置的输入机构包括一个精确的瞄准装置。

这将被用作:

/* Make radio buttons and check boxes larger if we have an inaccurate pointing device */
@media (pointer:coarse) {
input[type="checkbox"], input[type="radio"] {
min-width:30px;
min-height:40px;
background:transparent;
}
}

我还在 Chromium 项目中发现了与此相关的 罚单

浏览器的兼容性可在 古克斯莫德进行测试,以下是我的测试结果(2013年1月22日) :

  • Chrome/Win: 工作
  • Chrome/iOS: 不起作用
  • Safari/iOS6: 无法工作

这个解决方案将一直工作到所有浏览器都支持 CSS4为止。当那一天到来的时候,只需要使用 CSS4。但在此之前,这种方法适用于当前的浏览器。

浏览器-util. js

export const isMobile = {
android: () => navigator.userAgent.match(/Android/i),
blackberry: () => navigator.userAgent.match(/BlackBerry/i),
ios: () => navigator.userAgent.match(/iPhone|iPad|iPod/i),
opera: () => navigator.userAgent.match(/Opera Mini/i),
windows: () => navigator.userAgent.match(/IEMobile/i),
any: () => (isMobile.android() || isMobile.blackberry() ||
isMobile.ios() || isMobile.opera() || isMobile.windows())
};

上载:

老办法:

isMobile.any() ? document.getElementsByTagName("body")[0].className += 'is-touch' : null;

更新的方式:

isMobile.any() ? document.body.classList.add('is-touch') : null;

如果设备有触摸屏,上面的代码将把“ is-touch”类添加到 body 标记中。现在,在你的 web 应用程序的任何位置,你会有 css: hover,你可以调用 body:not(.is-touch) the_rest_of_my_css:hover

例如:

button:hover

变成:

body:not(.is-touch) button:hover

这个解决方案避免使用现代化器,因为现代化器库是一个非常大的库。如果所有您试图做的是检测触摸屏幕,这将是最好的时候,最终编译源码的大小是一个要求。

在2017年,从第二个问题回答的 CSS 媒体查询仍然不能在 Firefox 上工作。我找到了一个解决方案: - Moz 触摸-启动


下面是跨浏览器的媒体查询:

@media (-moz-touch-enabled: 1), (pointer:coarse) {
.something {
its: working;
}
}

使用 JS 或 jQuery 向主体添加类触摸屏

  //allowing mobile only css
var isMobile = ('ontouchstart' in document.documentElement && navigator.userAgent.match(/Mobi/));
if(isMobile){
jQuery("body").attr("class",'touchscreen');
}

实际上有一个媒体查询:

@media (hover: none) { … }

除了 Firefox,还有 支持率相当高。Safari 和 Chrome 作为移动设备上最常见的浏览器,在被更多人采用之前,它可能已经足够了。

我可以用这个解决这个问题

@media (hover:none), (hover:on-demand) {
Your class or ID{
attributes
}
}

这会有用的,如果它不让我知道的话

@media (hover: none) and (pointer: coarse) {
/* Touch screen device style goes here */
}

悬停: 当不支持悬停时,no 为真

指针: 粗 在输入精度有限时为 true。

如果所有你想做的是控制悬停,那么你不需要使用 指针

不再支持按需悬停

我相信用 CSS (2022年)查询触摸屏的更好方法是使用 (pointer:coarse),而使用 绝对没有(hover:none),或者一个组合,正如一些人建议的那样: (hover: none) and (pointer: coarse),因为 (hover:none)是不可靠的-有些设备模拟长按(触摸)盘旋所以 (hover:none)不会是真的。 我有这样一个问题,在一个真正的触摸设备(手机,而不是模拟) ,没有任何其他输入(鼠标或东西) ,这“有”一个悬停功能,我的媒体查询失败。

也许最好的方法是使用 Modern izr,或者两者都使用(Modern izr 和 CSS,虽然我没有看清楚 Modern izr 是做什么测试的,但可能和 CSS 是一样的:)像:

.modernizr-touch-class .my-class { // properties }
@media (pointer:coarse) { .my-class { // the same properties } }

但总的来说,这并不被认为是可靠的。当您添加 现代化“ Touch Events”测试时,它们会显示关于这个问题的简短信息(只有几个链接)。这可能是一个很好的阅读,找到一个特定问题的最佳解决方案,然后测试它..。

无论如何,我只想说 (hover:none)是不可靠的(在2022年)

截至2022年5月5日:

var isTouch = "maxTouchPoints" in window.navigator && window.navigator.maxTouchPoints > 1;
var isTouchTwo = "ontouchstart" in window;
var isTouchThree = window.matchMedia && window.matchMedia("(pointer:coarse)").matches;
var isDesktopIE = !!window.MSInputMethodContext && !!document.documentMode && !isTouchTwo;
var uaDataIsMobile = window.navigator.userAgentData && window.navigator.userAgentData.mobile;
var isDevice = typeof uaDataIsMobile === 'boolean' ? window.navigator.userAgentData.mobile || (isTouchTwo && isTouchThree) : ((/android|avantgo|blackberry|googlebot-mobile|iemobile|opera mini|kitkat|palmos|bolt|boost|cricket|docomo|fone|hiptop|mini|mobi|palm|iphone|ipod|phone|ipad|pie|tablet|silk|up\.browser|up\.link|playbook|webos|wos/i.test(window.navigator.userAgent.toLowerCase()) && !isDesktopIE) || window.navigator.platform === 'MacIntel' && isTouch);


console.log('1. '+isTouch+' 2. '+isTouchTwo+' 3. '+isTouchThree+' 4. '+/android|avantgo|blackberry|googlebot-mobile|iemobile|opera mini|kitkat|palmos|bolt|boost|cricket|docomo|fone|hiptop|mini|mobi|palm|iphone|ipod|phone|ipad|pie|tablet|silk|up\.browser|up\.link|playbook|webos|wos/i.test(window.navigator.userAgent.toLowerCase())+' 5. isDevice: '+isDevice)

纠正以下问题: a) IE11桌面 navigator.userAgent字符串声称是“平板电脑”; b) Safari 中的 iPadOS 用户代理与 MacOS Catalina 中的相同。(未经我测试,但它遵循这样的论证路线

引用

Https://developer.apple.com/forums/thread/119186

引用完毕

应该可以。我就指望它了。(参见 编辑。)

请注意,我的答案与 客户提示兼容。(我认为,未来的答案也应该是这样。)对于支持 navigator.userAgentData的浏览器,您不需要 navigator.userAgent

不好意思,绳子太长了,在 ES6里看起来更漂亮。

要执行媒体查询,只需附加基于真或假输出的样式表。

如何在 iOS13和 Up 中检测 iPad 和 iPad OS 版本?

if (navigator.maxTouchPoints > 1) {
// browser supports multi-touch
}

我以为是 > 0

我在不同的浏览器上尝试了不同的选项,发现需要同时使用鼠标悬停和指针-

@media (hover:none), (pointer:coarse){
.show_on_touch {display:inline}
}

没有告诉您不支持悬停,但是某些平台上的某些浏览器会撒谎。

指针: 粗糙告诉您没有精细的指针控制,因此它可能是基于手指的。