在触摸设备上,CSS hover+click/touch会出现奇怪的行为

3
我知道标题太过笼统,我找不到一个具体的标题。
这是一个示例 https://jsfiddle.net/Exlord/1soagsL5/ HTML
<ul>
  <li>item1</li>
  <li>item1</li>
  <li>item with submenu &gt;
    <ul>
      <li>item1</li>
      <li>item1</li>
    </ul>
  </li>
  <li>item1</li>
  <li id='clickable'>item1</li>
</ul>

JavaScript

var el = document.getElementById('clickable');
el.addEventListener('click', function(e) {
  console.log(e.target);
}, false);

CSS

ul {
  list-style: none;
  margin: 0;
  padding: 0;
  width: 200px;
  max-width: 100%;
}

li {
  background: gray;
  padding: 5px;
  border: solid 1px black;
  position: relative;
}

li:hover > ul {
  display: block;
}

@media all and (min-width: 481px) {
  ul ul {
    display: none;
    position: absolute;
    left: 100%;
    top: 0;
  }
}

@media all and (max-width: 480px) {
  ul ul {
    display: none;
  }
}

尝试一下,这是一个非常简单的菜单,将鼠标悬停在中间的带子菜单的项目上,将显示一个简单的子菜单,使用简单的CSS :hover

点击最后一个项目,它有一个点击事件,它会正确触发。

现在在Chrome的移动设备模拟器中打开并模拟触摸。

点击/触摸带子菜单的项目,子菜单将在父元素内打开。这是期望的行为。

现在点击/触摸最后一个元素。点击事件将不会触发。

如何仅使用CSS的hover来修复这个问题?

更新:据我所知,问题在于第一次触摸时,最后一个悬停的元素(带有子菜单的li)变得未悬停,并且子菜单ul被隐藏,父级ul的高度缩小,而被触摸点下方的li元素向上移动,因此它不再在触摸点下方,并且无法被点击/触摸!!!

1个回答

0

我认为你已经自己找到了原因。点击目标似乎在事件到达元素之前移开了。

我看到的最简单的解决方案是使用一些补充的Javascript来在点击时打开和关闭子菜单。你已经在#clickable事件中使用了Javascript,所以再多一点不会有害,只要你保留:hover用于Javascript加载失败的情况。


原始答案

Touch devices do not have a hover state, due to the hardware interface. Browser makers chose a compromise to allow for sites which rely on it. Whenever a hover event/style is defined for an element the first tap will trigger that effect instead of the click. A second tap should, at least in most cases, trigger the original click event.

For your particular case you don't have a ul within the li#clickable, but the :hover is still detected and the browser behaves as it was designed. Excluding your #clickable from the hover event will theoretically fix it (I am not able to test it myself at this time).

li:not(#clickable):hover > ul {
  display: block;
}

不行,那没起作用。我认为问题在于第一次触摸时,最后一个悬停的元素会变成非悬停状态,子菜单“ul”也会隐藏,而被触摸点覆盖的“li”元素会向上移动,因此它不再处于触摸点下方,无法被点击或触摸到!!! - Exlord
只是为了澄清,因为我在答案中没有这样说,意图是用我的代码片段替换您的li:hover > ul声明。保留两者都不会有任何变化。 - Gwellin
菜单本身实际上是由JS生成的,而不是静态HTML。我希望能够仅用CSS处理显示/隐藏,但目前为止,我只能为小屏幕添加JS解决方案。 - Exlord

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接