:active pseudo-class doesn't work in mobile safari

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

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

在您的 < a > 标记中添加 ontouch 启动的事件处理程序,这将使 CSS 神奇地工作。

<a ontouchstart="">Click me</a>

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

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

还有,如果你只是使用: active,添加一个: link,即使你没有设置样式。

<body ontouchstart="">
...
</body>

只应用一次,相对于每个按钮元素,似乎可以修复页面上的所有按钮。或者,您可以使用这个名为“ 快捷键”的小型 JS 库。它可以加速触摸设备上的点击事件,也可以解决这个问题。

<!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>
//hover for ios
-webkit-tap-highlight-color: #ccc;

这对我来说很有用,添加到您想要突出显示的元素的 CSS 中

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

You can also use the -webkit-tap-highlight-color CSS property in combination with setting a touch event to configure buttons to behave similar to the desktop. 在 iOS 上,鼠标事件发送得如此之快,以至于从未接收到 down 或 active 状态。 Therefore, the :active pseudo state is triggered only when there is a touch event set on the HTML element—for example, when ontouchstart is set on the element as follows:

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

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

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

在我看来,这种行为是有缺陷的,而且可能要追溯到“移动”网络基本上不存在的时代(看看链接页面上的截图就知道我的意思了) ,一切都是以鼠标为导向的。值得注意的是,其他较新的移动浏览器,比如 Android,在触摸屏上显示“ : active”伪状态的效果还不错,没有任何像 iOS 那样的缺陷。

(附注: 如果你想在 iOS 上使用自己的自定义样式,你也可以使用 -webkit-tap-highlight-color CSS 属性禁用 iOS 使用的代替 :active伪状态的默认灰色半透明框,如上面的链接页面所解释的。)


经过一些实验,预期的解决方案设置 ontouchstart事件的 <body>元素,所有触摸事件,然后气泡不完全工作。如果页面加载时元素在 viewport 中是可见的,那么它可以正常工作,但是向下滚动并点击一个不在 viewport 中的元素时,没有会像应该的那样触发 :active伪状态。所以

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

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

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

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


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

这个问题没有百分之百的关联, 但是你也可以使用 css 兄弟黑客技术来实现这一点

超文本标示语言

<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;
}
}

As of Dec 8, 2016, the accepted answer (<body ontouchstart="">...</body>) does not work for me on Safari 10 (iPhone 5s): That hack only works for those elements that were visible on page load.

不过,他补充称:

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

head的工作方式我想,与缺点,现在所有的触摸事件在滚动也触发 :active伪状态的接触元素。(如果这对您来说是个问题,您可以考虑 “战斗机”的:hover解决方案。)

我发布了一个工具,可以帮你解决这个问题。

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

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

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

诚实,有益的反馈和贡献非常感谢!

一个解决方案是依靠 :target而不是 :active:

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

该样式将被触发时,锚定的目标是当前的网址,这是健壮的,即使在移动。缺点是您需要另一个链接来清除 URL 中的锚。完整的例子:

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

For those who don't want to use the ontouchstart, you can use this code

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

我尝试了 这个答案和它的变种,但似乎没有一个可靠的工作(我不喜欢依靠’魔术’的东西喜欢这样)。所以我做了以下的改动,这在所有平台上都能完美运行,不仅仅是苹果:

  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');
    });
    

This was a bit tedious, but now I have a solution that is less vulnerable to breakage between Apple OS versions. (And who needs something like this breaking?)