【问题标题】:Media query to detect if device is touchscreen媒体查询以检测设备是否为触摸屏
【发布时间】:2012-07-08 10:10:13
【问题描述】:

在不使用触摸屏设备的情况下,使用媒体查询实现某些事情的最安全方法是什么?如果没有办法,您是否建议使用 JavaScript 解决方案,例如 !window.Touch 或 Modernizr?

【问题讨论】:

标签: css touch media-queries


【解决方案1】:

如今,CSS 媒体查询可用于为具有特定交互功能的设备定义样式,它也是 widely supported

例如,hover 可用于测试用户的主要输入机制是否可以将鼠标悬停在元素上(在没有模拟的支持触摸的设备中这是不正确的)

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

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

上一个答案

我建议使用modernizr 并使用它的媒体查询功能。

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

但是,使用 CSS 时,也有类似的伪类,例如在 Firefox 中。您可以使用:-moz-system-metric(touch-enabled)。但这些功能并非适用于所有浏览器。

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

if (TouchEvent) {
   //...
}

尤其是 iPad:

if (Touch) {
    // ...
}

但是,这些不适用于 Android

Modernizr 提供特征检测能力,检测特征是 一种很好的编码方式,而不是基于浏览器的编码。

风格化触控元素

Modernizer 正是为此目的向 HTML 标记添加了类。在这种情况下,touchno-touch 可以通过在选择器前加上 .touch 来设置与触摸相关的方面的样式。例如.touch .your-container致谢:本·斯威本

【讨论】:

  • 我认为没有任何psedo 类适用于所有现代设备/浏览器是否正确?
  • Modernizr.touch 测试仅表明浏览器是否支持触摸事件,不一定反映触摸屏设备。例如,Palm Pre / WebOS(触摸)手机不支持触摸事件,因此无法通过此测试。
  • 只是补充一点,如果你无论如何都要包括现代化者; Modernizer 为这个确切的目的将类添加到 body 标记中。在这种情况下,touchno-touch,因此您可以通过在选择器前加上 .touch 来设置与触摸相关的方面。例如。 .touch .your-container
  • 对我来说,modernizr 似乎将 touch 类添加到 html 标签,而不是 body 标签。
  • 在 hover: none 查询中有一个 :hover 有意义吗?在那种情况下它什么也做不了,对吧?也许你想悬停:悬停?
【解决方案2】:

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

可能最好的方法是使用 Modernizr,甚至两者都使用(Modernizr 和 CSS,虽然我没有看过 Modernizr 所做的测试,但可能与 CSS 相同:) 比如:

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

但总而言之,这不被认为是可靠的。当您添加modernizr“触摸事件”测试时,它们会显示有关此问题的简短信息(带有几个链接)。这可能是一本好书,可以阅读以找到特定问题的最佳解决方案,然后对其进行测试...

无论如何,我只想说(hover:none) 不可靠(2022 年)。 :D

【讨论】:

    【解决方案3】:

    这会奏效。如果它不让我知道

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

    编辑:不再支持按需悬停

    【讨论】:

      【解决方案4】:

      截至 2013 年年中,CSS 解决方案似乎并未广泛使用。而是……

      1. Nicholas Zakas explains 当浏览器不支持触摸时,Modernizr 会应用 no-touch CSS 类。

      2. 或者用一段简单的代码在 JavaScript 中检测,让您实现自己的类似 Modernizr 的解决方案:

        <script>
            document.documentElement.className += 
            (("ontouchstart" in document.documentElement) ? ' touch' : ' no-touch');
        </script>
        

        然后你可以把你的 CSS 写成:

        .no-touch .myClass {
            ...
        }
        .touch .myClass {
            ...
        }
        

      【讨论】:

      • 第二个很不错。对我很有魅力!谢谢。
      • @bjb568 感谢建议的编辑,这是一个更现代的替代方案,但由于它仅适用于 IE 10 及更高版本,我认为最好暂时保留此版本。
      • 听起来那个类应该在 html 标签上;这意味着在使用 CSP 时默认禁用它。
      【解决方案5】:

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

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

      【讨论】:

      【解决方案6】:

      实际上有一个媒体查询:

      @media (hover: none) { … }
      

      除了 Firefox,它是 fairly well supported。 Safari 和 Chrome 是移动设备上最常见的浏览器,它可能就足够了,直到被广泛采用。

      【讨论】:

      • ... 并在接下来的几周内为 FF 提供支持。
      【解决方案7】:

      在 2017 年,来自第二个答案的 CSS 媒体查询仍然无法在 Firefox 上运行。我找到了一个解决方案:-moz-touch-enabled


      所以,这里是跨浏览器媒体查询:

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

      【讨论】:

      【解决方案8】:

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

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

      【讨论】:

        【解决方案9】:

        在所有浏览器全球支持 CSS4 之前,此解决方案将一直有效。当那一天到来时,只需使用 CSS4。但在那之前,这适用于当前的浏览器。

        browser-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 for :hover 您可以调用 body:not(.is-touch) the_rest_of_my_css:hover

        例如:

        button:hover
        

        变成:

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

        此解决方案避免使用现代化器,因为现代化器库是一个非常大的库。如果您要做的只是检测触摸屏,那么当最终编译源的大小是要求时,这将是最好的。

        【讨论】:

          【解决方案10】:

          CSS4 media query draft 中实际上有一个属性。

          “指针”媒体功能用于查询存在和 指点设备(例如鼠标)的准确性。如果一个设备有 多种输入机制,建议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 项目中找到了a ticket

          可以在Quirksmode 测试浏览器兼容性。这些是我的结果(2013 年 1 月 22 日):

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

          【讨论】:

          【解决方案11】:

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

          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>
          

          【讨论】:

          • AFAIK, window.touch && window.TouchEvent 仅适用于苹果设备。
          • @vsync Modernizr 是将所有对开发人员有用的测试放在托管库中的好方法,这样他们就不必每次需要测试特定功能(如触摸事件)时都使用 Google找到这个页面。仅供参考,有一个自定义的 Modernizr 构建,您可以使用所需的测试对其进行自定义。这是一种在项目之间始终以相同方式测试功能的好方法,您可以使用 JS 语法(即:Modernizr.touch)或 CSS 类(.touch .my-element {})。我认为这是对人类智力的侮辱,不承认我们可以在不每次都重新发明轮子的情况下做事。
          • 好吧,我已经参与了数百个项目,我从来不需要这样的东西,在大多数情况下,你只需要一组非常小的测试,我会说永远不会超过 5 个(在大多数情况下),所以只需找到这 5 个并将它们直接放入您的代码中,无需实际访问 Modernizer 网站,进行自定义构建,将其包含在您的页面中,或其他任何东西。开发人员不应该那么懒惰。 Web 开发人员应该始终拥有“我怎样才能使代码更轻量级?”的心态......恕我直言和多年的经验。现在的开发人员似乎喜欢包含大量脚本:/
          • 有人说懒。我说为什么要重新发明轮子?当出现新设备/版本/平台并且您的特殊情况需要更改时怎么办?您是否 a) 尝试自己编写特殊情况检测代码,并向后移植到您的自定义代码,在此过程中重新熟悉它,或者 b) 下载 Modernizr 的更新版本并将其放入?我知道我会做什么。 +1 给 GarciaWebDev。
          • @Sc0ttyD 我个人的偏好是在不依赖诸如 Modernizr 之类的库的情况下开始学习编写代码。有一天,您可能需要成为为新设备编码的人,并且您不想被卡住,因为没有库就无法做到这一点。更不用说,可能有很多人只是没有时间在工作中学习新图书馆。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-04-27
          • 1970-01-01
          • 2019-04-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-07-15
          相关资源
          最近更新 更多