:active伪类在移动浏览器中不起作用


Answers:


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

只需应用一次,而不是每个按钮元素都可以修复页面上的所有按钮。另外,您可以使用这个名为' Fastclick '的小型JS库。它可以加快触摸设备上的点击事件,也可以解决此问题。


19
仅添加ontouchstart而不添加是否足够=""?(HTML5)
feklee,2012年

2
对于以后的读者,我在这里发布了一个演示:http : //jsbin.com/EjiWILe/3/。检查iOS设备上的功能。
mhulse 2013年

6
您能解释一下为什么对身体应用了一个空听众吗?如何运作?
Maurizio Battaghini 2014年

2
我正在使用:focus,这也适用。感谢魔术。
TecBrat 2015年

我正在使用此方法在iOS 9.1和9.3上冻结页面...那些版本有js错误,但这些OS上仍有0.5%的用户
Ruskin

55

正如其他答案所述,:active除非将touch事件附加到元素,否则iOS Safari不会触发伪类,但是到目前为止,这种行为是“神奇的”。我在Safari开发者库中遇到了这个小问题,对此做了解释(强调我的意思):

您还可以-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那样需要任何黑客手段。

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


经过一些实验后,在所有触摸事件然后冒泡ontouchstart<body>元素上设置事件的预期解决方案无法完全发挥作用。如果元素中视可见的页面加载时,那么它工作正常,但向下滚动和攻丝,这是视口拖出元素并没有引发像它应该伪状态。所以,代替:active

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

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

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

但是,我不知道这样做对性能的影响,因此请注意。


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


6
很好的解释了为什么而不是怎么做!谢谢!
coderfin

6
因给予开发人员理解而被赞誉,而不仅仅是“魔术”食谱。这比其他方法提供的信息无限多。感谢您为我们撰写本文。
user508633

赞成详细说明+注意事项。这应该是正确的答案。
鸭子大师

39

在<a>标记中为ontouchstart添加事件处理程序。这导致CSS神奇地工作。

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

3
抱歉,这是个旧答案,但是为什么这行得通呢?我不介意“魔术”为原因,但是如果您能解释一下它为什么起作用的话,我希望阅读更多详细信息。
mhulse

1
@mhulse我也很想知道为什么。
Jesse Rusak

哈!我们在同一条船上。我将尝试进行一些研究,并在此发布有关此问题的(半)官方文档的链接。我喜欢这种技术有效,我只是想知道为什么吗?
mhulse

7

对我有用:

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

注意:如果您使用此技巧,则还应删除默认的tap-highlight颜色,Mobile Safari使用以下CSS规则应用。

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

5

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

但是,添加:

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

这样head做确实不利于我想要的方式,但不利的是,现在滚动期间的所有触摸事件也会触发:active被触摸元素的伪状态。(如果这对您来说是个问题,您可以考虑使用FighterJet的 :hover解决方法。)


4
//hover for ios
-webkit-tap-highlight-color: #ccc;

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


3

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

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

..以该顺序。另外,如果您只是使用:active,即使没有设置样式,也请添加:link。


有关在设计伪类样式时顺序的重要提示。
brianarpie

1

我已经发布了一种工具,可以为您解决此问题。

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

这应该立即解决所有问题:https : //www.npmjs.com/package/active-touch

您需要将.active样式分配给.active类,或选择自己的类名称。默认情况下,脚本将与所有链接元素一起使用,但是您可以使用自己的选择器数组将其覆盖。

诚实,有益的反馈和贡献深表感谢!


2
该库为每个链接元素添加了9个(非被动)事件侦听器,但未调用removeEventListener-我认为这对于单页应用程序来说是一个很大的缺陷
Drenai

1
谢谢瑞安。我已经超过一年没有支持或使用此代码了;我把它记下来。经过一番思考和实验后,我更改了应用程序的设计,而不是试图强制浏览器不解释或考虑的交互。
dmitrizzle '18

1

对于那些不想使用ontouchstart的人,可以使用此代码

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

1

我尝试了这个答案及其变体,但似乎没有一个能可靠地工作(而且我不喜欢依靠“魔术”来完成此类工作)。因此,我改为执行以下操作,该操作在所有平台上都可以完美运行,而不仅仅是Apple:

  1. 更名为CSS声明所使用:active.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上运行。但这可以使用我给出的解决方案可靠地模拟。我已经在我的应用程序中完成了此操作,它在所有平台上均能完美运行。并且我已经通过澄清的方式添加了代码。
daffinm

0

一个解决方案是依靠: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>


-3

没有100%与该问题相关,但您也可以使用CSS同级黑客来实现此目的

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

-6
<!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>

1
根据常见问题解答,不允许签名和自我宣传。
LittleBobbyTables-Au Revoir 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.