【问题标题】::active pseudo-class doesn't work in mobile safari:active 伪类在移动 Safari 中不起作用
【发布时间】:2011-04-22 13:13:20
【问题描述】:

在 iPhone/iPad/iPod 上的 Webkit 中,当您点击元素时,不会触发为 <a> 标签指定 :active 伪类的样式。我怎样才能让它触发?示例代码:

<style> 
a:active { 
    background-color: red;
}
</style>
<!-- snip -->
<a href="#">Click me</a>

【问题讨论】:

    标签: iphone css webkit mobile-safari pseudo-class


    【解决方案1】:
    <body ontouchstart="">
        ...
    </body>
    

    只应用一次,而不是每个按钮元素似乎都修复了页面上的所有按钮。或者,您可以使用这个名为“Fastclick”的小型 JS 库。它加快了触摸设备上的点击事件并解决了这个问题。

    【讨论】:

    • 仅添加ontouchstart 而不添加="" 还不够吗? (HTML5)
    • 对于任何未来的读者,我在这里发布了一个演示:http://jsbin.com/EjiWILe/3/。检查您的 iOS 设备上的功能。
    • 你能解释一下为什么你对body应用了一个空的监听器吗?它是如何工作的?
    • 我使用的是 :focus,这也适用。感谢魔术。
    • 我正在使用这种方法在 iOS 9.1 和 9.3 上冻结页面......这些版本有一个 js 错误,但在这些操作系统上仍有 0.5% 的用户
    【解决方案2】:

    正如其他答案所述,iOS Safari 不会触发 :active 伪类,除非将触摸事件附加到元素,但到目前为止,这种行为是“神奇的”。我在Safari Developer Library 上看到了这个解释它的小简介(强调我的):

    您还可以将-webkit-tap-highlight-color CSS 属性与设置触摸事件结合使用,以配置按钮的行为类似于桌面。 在 iOS 上,鼠标事件发送得非常快,以至于永远不会收到按下或活动状态。因此,:active 伪状态仅在 HTML 元素上设置了触摸事件时才会触发——例如例如,当在元素上设置 ontouchstart 时,如下所示:

    <button class="action" ontouchstart=""
            style="-webkit-tap-highlight-color: rgba(0,0,0,0);">
        Testing Touch on iOS
    </button>
    

    现在,当在 iOS 上点击并按住按钮时,按钮会变为指定的颜色,而不会出现周围的透明灰色。

    换句话说,设置ontouchstart 事件(即使它是空的)就是明确告诉浏览器对触摸事件做出反应。

    在我看来,这是有缺陷的行为,并且可能可以追溯到“移动”网络基本上不存在的时候(看看链接页面上的那些屏幕截图,看看我的意思),一切都是鼠标导向的。有趣的是,其他较新的移动浏览器,例如 Android 上的,在触摸时显示 `:active' 伪状态很好,没有像 iOS 所需的任何 hack。

    (旁注:如果您想在 iOS 上使用自己的自定义样式,您还可以使用 -webkit-tap-highlight-color CSS 属性禁用 iOS 使用的默认灰色半透明框来代替 :active 伪状态,如上面同一链接页面中所述。)


    经过一些实验,在 all 触摸事件然后冒泡的 &lt;body&gt; 元素上设置 ontouchstart 事件的预期解决方案不能完全工作。如果页面加载时元素在视口中可见,那么它可以正常工作,但是向下滚动并点击视口外的元素不会触发:active类似的伪状态应该。所以,而不是

    <!DOCTYPE html>
    <html><body ontouchstart></body></html>
    

    将事件附加到所有元素,而不是依赖事件冒泡到正文(使用 jQuery):

    $('body *').on('touchstart', function (){});
    

    但是,我不知道这对性能的影响,所以要小心。


    编辑:此解决方案存在一个严重缺陷:即使在滚动页面时触摸元素也会激活:active 伪状态。灵敏度太强了。 Android 通过在显示状态之前引入一个非常小的延迟来解决这个问题,如果页面滚动则会取消该延迟。鉴于此,我建议仅在选择元素上使用它。就我而言,我正在开发一个用于该领域的网络应用程序,它基本上是一个用于导航页面和提交操作的按钮列表。因为在某些情况下整个页面几乎都是按钮,所以这对我不起作用。但是,您可以设置 :hover 伪状态来代替它。禁用默认的灰色框后,效果很好。

    【讨论】:

    • 很好地解释了为什么,而不仅仅是如何!谢谢!
    • 赞成给予开发者理解,而不仅仅是“魔法”食谱。这比其他的信息丰富得多;谢谢你为我们写这篇文章。
    • 赞成详细解释+警告。这应该是正确的答案。
    【解决方案3】:

    【讨论】:

    • 对不起,这是旧答案,但为什么这行得通?我不介意“神奇地”作为一个原因,但如果你能解释它为什么起作用,我很乐意阅读更多细节。
    • @mhulse 我也很想知道原因。
    • 哈!我们在同一条船上。我会尝试做一些研究并在这里发回关于此事的(半)官方文档的链接。我喜欢这种技术,我只是想知道为什么?
    【解决方案4】:

    This 为我工作:

    document.addEventListener("touchstart", function() {},false);
    

    注意:如果您使用此技巧,还值得删除默认的点击高亮颜色 Mobile Safari 使用以下 CSS 规则应用。

    html {
        -webkit-tap-highlight-color: rgba(0,0,0,0);
    }
    

    【讨论】:

      【解决方案5】:

      截至 2016 年 12 月 8 日,已接受的答案 (&lt;body ontouchstart=""&gt;...&lt;/body&gt;) 在 Safari 10 (iPhone 5s) 上对我不起作用:该 hack 仅适用于在页面加载时可见的那些元素。

      但是,添加:

      <script type='application/javascript'>
        document.addEventListener("touchstart", function() {}, false);
      </script>
      

      head 确实按我想要的方式工作,缺点是现在滚动期间的所有触摸事件也会触发触摸元素上的 :active 伪状态。 (如果这对您来说是个问题,您可以考虑使用FighterJet's:hover 解决方法。)

      【讨论】:

        【解决方案6】:
        //hover for ios
        -webkit-tap-highlight-color: #ccc;
        

        这对我有用,添加到你想要突出显示的元素上的 CSS

        【讨论】:

          【解决方案7】:

          你是使用所有的伪类还是只使用一个?如果您至少使用两个,请确保它们的顺序正确,否则它们都会损坏:

          a:link
          a:visited
          a:hover
          a:active
          

          ..按这个顺序。此外,如果您只是使用 :active,请添加:链接,即使您没有对其进行样式设置。

          【讨论】:

          • 关于在设置伪类样式时顺序很重要的重要提示。
          【解决方案8】:

          不想使用ontouchstart的可以使用这段代码

          <script>
           document.addEventListener("touchstart", function(){}, true);
          </script>
          

          【讨论】:

            【解决方案9】:

            我已经发布了一个可以为你解决这个问题的工具。

            表面上问题看起来很简单,但实际上需要对触摸和点击行为进行相当广泛的自定义,包括超时功能以及诸如“滚动链接列表时会发生什么”或“按下时会发生什么”之类的事情链接,然后将鼠标/手指从活动区域移开”

            这应该可以一次性解决所有问题:https://www.npmjs.com/package/active-touch

            您需要将 :active 样式分配给 .active 类,或者选择您自己的类名。默认情况下,该脚本将适用于所有链接元素,但您可以使用自己的选择器数组覆盖它。

            非常感谢诚实、有用的反馈和贡献!

            【讨论】:

            • 该库为每个链接元素添加了 9 个(非被动)事件侦听器,但不调用 removeEventListener - 我认为这对于单页应用程序来说是一个大缺陷
            • 谢谢瑞恩。我已经一年多没有支持或使用此代码了;我会把它拿下来。经过一番思考和实验后,我改变了应用的设计,而不是试图强迫浏览器没有考虑或考虑过的交互。
            【解决方案10】:

            我尝试了this answer 及其变体,但似乎没有一个能可靠地工作(而且我不喜欢依靠“魔法”来处理这类事情)。所以我改为执行以下操作,它在所有平台上都能完美运行,而不仅仅是 Apple:

            1. 将使用:active 的css 声明重命名为.active
            2. 列出所有受影响的元素并添加pointerdown/mousedown/touchstart 事件处理程序以应用.active 类和pointerup/mouseup/touchend 事件处理程序以将其删除。使用 jQuery:

              let controlActivationEvents = window.PointerEvent ? "pointerdown" : "touchstart mousedown";
              let controlDeactivationEvents = window.PointerEvent ? "pointerup pointerleave" : "touchend mouseup mouseleave";
              
              let clickableThings = '<comma separated list of selectors>';
              $(clickableThings).on(controlActivationEvents,function (e) {
                  $(this).addClass('active');
              }).on(controlDeactivationEvents, function (e) {
                  $(this).removeClass('active');
              });
              

            这有点乏味,但现在我有一个解决方案,它不太容易受到 Apple OS 版本之间的破坏。 (谁需要这样的破坏?)

            【讨论】:

            • 我认为它确实提供了问题的答案。似乎没有可靠的方法让 :active 伪类在移动 Safari 上工作。但这可以使用我给出的解决方案可靠地模拟。我已经在我的应用程序中完成了这项工作,它在所有平台上都能完美运行。我已经通过澄清的方式添加了代码。
            【解决方案11】:

            一种解决方案是依赖:target 而不是:active

            <style> 
            a:target { 
                background-color: red;
            }
            </style>
            <!-- snip -->
            <a id="click-me" href="#click-me">Click me</a>
            

            当锚点被当前 url 定位时,样式将被触发,即使在移动设备上也很健壮。缺点是您需要另一个链接来清除 url 中的锚点。完整示例:

            a:target { 
                background-color: red;
            }
            <a id="click-me" href="#click-me">Click me</a>
            <a id="clear" href="#">Clear</a>

            【讨论】:

              【解决方案12】:

              没有 100% 与此问题相关, 但你也可以使用 css 兄弟 hack 来实现这一点

              HTML

              <input tabindex="0" type="checkbox" id="145"/>
              <label for="145"> info</label>
              <span> sea</span>
              

              SCSS

              input {
                  &:checked + label {
                    background-color: red;
                  }
                }
              

              如果你想使用纯 html/css 工具提示

              span {
                display: none;
              }
              input {
                  &:checked ~ span {
                    display: block;
                  }
                }
              

              【讨论】:

                【解决方案13】:
                <!DOCTYPE html>
                
                <html lang="en">
                
                <head>
                <meta charset="utf-8">
                
                <title></title>
                
                <style>
                        a{color: red;}
                        a:hover{color: blue;}
                </style>
                </head>
                
                <body>
                
                        <div class="main" role="main">
                                <a href="#">Hover</a>
                        </div>
                
                </body>
                </html>
                

                【讨论】:

                • 根据常见问题解答,不允许签名和自我宣传。
                猜你喜欢
                • 2018-03-08
                • 2021-08-12
                • 2019-11-15
                • 1970-01-01
                • 2013-01-17
                • 1970-01-01
                • 1970-01-01
                • 2014-01-30
                • 1970-01-01
                相关资源
                最近更新 更多