CSS中是否有类似于`pointer-events:hoverOnly`的东西?

157

最近在玩CSS中的pointer-events属性。

我有一个div,我希望它对所有鼠标事件都是不可见的,除了:hover

所以所有的点击命令都通过div传递到下面的元素,但是div仍然可以报告鼠标是否在其上方。

有人能告诉我这是否可行吗?

HTML:

<div class="layer" style="z-index:20; pointer-events:none;">Top layer</div>
<div class="layer" style="z-index:10;">Bottom layer</div>

CSS:

.layer {
    position:absolute;
    top:0px;
    left:0px;
    height:400px;
    width:400px;
}

2
只是一个提醒,pointer-events在IE中支持不太好(http://caniuse.com/pointer-events)。 - Vucko
2
听起来你需要 JavaScript。 - Pete
同意Pete的观点,我知道这是在特别询问CSS,但我也遇到了同样的问题,对我来说最简单的解决方案就是让子元素使用JavaScript向父元素发起点击事件。https://dev59.com/pJTfa4cB1Zd3GeqPWtx2 - Jerry Sha
虽然这不是一个解决方案,但如果有帮助的话:如果父元素跟踪鼠标位置和悬停事件,它的子元素仍然可以接受触摸。我想在一个元素上跟踪触摸,而在另一个元素上跟踪悬停,将触摸处理程序div放在悬停div内部会有所帮助。 - Fernando Rojo
8个回答

160

只需悬停即可。非常简单。无需 JS... 还可以防止链接默认操作。

a:hover {
 color: red;
}
a:active {
 pointer-events: none;
}
<a href="www.google.com">Link here</a>

编辑: 在IE11及以上版本中支持 http://caniuse.com/#search=pointer-events


37
这确实“起作用”,但是它不允许点击下面的元素(至少在该元素是YouTube视频时不行)- 这可能是任何人首先需要这种行为的唯一原因。 - Simon_Weaver
2
@PriyanshuJain,你认为如果用户点击按钮会发生什么? - Свободен Роб
2
@Simon_Weaver 这么说只有因为要点击YouTube视频或者更普遍地说,点击元素下方的某些东西才需要这个功能是非常短视的。很可能有人想要这种行为是为了使一个通常可点击的元素变得不可点击。 - claudekennilol
3
@claudekennilol,问题字面上说“所以所有的点击命令都通过div传递到下面的一个”。这正是他们想要的!我只是提到YouTube作为我测试过的例子。听起来原始提问者希望pointer-events像事件过滤器一样起作用,但我认为它做不到。无论如何,这是5年前的事情了 - 我希望你找到了解决今天让你看到这个问题的任何问题的解决方案。 - Simon_Weaver
2
@Simon_Weaver 你说得完全正确,这个解决方案并不是我想要的。我觉得其他人在批评你之前没有阅读我的问题,这是短视的。 - Jimmery
显示剩余9条评论

29

借鉴Xanco的答案,但没有那个丑陋的jQuery。

片段:注意DIVs是反向排列的。

.layer {
  position: absolute;
  top: 0px;
  left: 0px;
  height: 400px;
  width: 400px;
}

#bottomlayer {
  z-index: 10
}

#toplayer {
  z-index: 20;
  pointer-events: none;
  background-color: white;
  display: none
}

#bottomlayer:hover~#toplayer {
  display: block
}
<div id="bottomlayer" class="layer">Bottom layer</div>
<div id="toplayer" class="layer">Top layer</div>


4
抱歉,我仍然在使用不太好看的jQuery。但是因为你提供了一种只使用CSS的解决方案,所以我会点赞的! - Jimmery
这很棒 - 只是顺便说一下,如果底层包含一个iframe,则无法正常工作: jsfiddle.net/ReZ9M/82 - Simon_Weaver
5
这怎么解决问题?原帖问的是如何通过初始可见元素来执行点击命令。但在你的解决方案中,他们并没有这样做,注意到“顶层”文本无法被选中... - Trever Thompson

15

我认为仅通过CSS无法实现您的目标。不过,正如其他贡献者所提到的那样,使用JQuery很容易实现。以下是我的实现:

HTML

<div
  id="toplayer"
  class="layer"
  style="
    z-index: 20;
    pointer-events: none;
    background-color: white;
    display: none;
  "
>
  Top layer
</div>
<div id="bottomlayer" class="layer" style="z-index: 10">Bottom layer</div>

CSS(不变)

.layer {
    position:absolute;
    top:0px;
    left:0px;
    height:400px;
    width:400px;
}

jQuery

$(document).ready(function(){
    $("#bottomlayer").hover(
        function() {
            $("#toplayer").css("display", "block");
        },
        function() {
            $("#toplayer").css("display", "none");
        }
    );
});

这是 JSFiddle 的链接:http://www.jsfiddle.net/ReZ9M


9

您还可以检测不同元素的悬停状态并对其子元素应用样式,或者使用其他CSS选择器,例如相邻的子元素等。

这取决于您的具体情况。

在父元素的悬停状态下。我是这样做的:

.child {
    pointer-events: none;
    background-color: white;
}

.parent:hover > .child {
    background-color: black;
}

1
应该选择纯CSS + 如果需要,保持指针事件继续传递。 - sab

2

只使用纯 CSS,不需要 jQuery

div:hover {pointer-events: none}
div {pointer-events: auto}

非常感谢您的回复,能否在您的答案中添加一个演示(例如代码片段或在CodePen或JSFiddle中的链接)?您知道这种方法的兼容性如何吗?这是一种新的CSS3功能吗?如果这个方法有效,我一定会给您打勾 :) - Jimmery
抱歉,我无法创建演示。但是在我的逻辑中,它肯定可以在所有浏览器上运行(因为我没有ie,所以不确定ie是否支持)。而且,它支持从css1开始 :) - Bariq Dharmawan
https://caniuse.com/#feat=pointer-events - 在IE 11之外的任何IE版本中都无法工作...如果您在https://codepen.io/上创建了一个有效的演示,我将为您进行测试,如果它可以正常工作,我将授予您正确的答案 - 对不起,我不能授予理论代码 - 只有有效的演示。 - Jimmery
@brillout 能否添加一小段代码片段?因为它对我很有效。 - Bariq Dharmawan

2

以下是您要求的纯CSS解决方案(透明度属性仅用于说明需要进行转换):

.hoverOnly:hover {
    pointer-events: none;
    opacity: 0.1;
    transition-delay: 0s;
}
.hoverOnly {
    transition: ,5s all;
    opacity: 0.75;
    transition-delay: 2s;
}

功能:

当鼠标进入该框时,会触发:hover状态。然而,在该状态下,指针事件被禁用。

但是,如果您不设置过渡定时器,当鼠标移动时,div将取消悬停状态;当鼠标在元素内移动时,悬停状态会闪烁。可以使用上面的代码和不透明度属性来感知这一点。

将延迟设置为退出悬停状态可以解决这个问题。2s值可以调整以适应您的需求。

过渡调整由patad制作:此答案


当我尝试这个解决方案时,该元素仅停留在“悬停”状态。 - Flimm
转换值应该是一个点而不是逗号,这里有一个拼写错误。 - withintheruins14

1
我使用等大小的父容器的伪元素:hover来模拟对叠加层的悬停效果,然后将叠加层的pointer-events设置为none,以便将点击事件传递到下方的元素。

let button = document.getElementById('woohoo-button');
button.onclick = () => console.log('woohoo!');

let overlay = document.getElementById('overlay');
overlay.onclick = () => console.log(`Better change my pointer-events property back to 'none'`);
#container {
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  background-color: green;
  width: 300px;
  height: 300px;
}

#overlay {
  background-color: black;
  width: 100%;
  height: 100%;
  opacity: 0;
  z-index: 1;
  /* Pass through clicks */
  pointer-events: none;
}


/* 
   Set overlay hover style based on
   :hover pseudo-element of its  
   container
*/
#container:hover #overlay {
  opacity: 0.5;
}

#woohoo-button {
  position: absolute;
  width: 100px;
  height: 100px;
  background-color: red;
}
<div id="container">
  <div id="overlay"></div>
  <button id="woohoo-button">
    Click Me
  </button>
</div>


1

基于鼠标位置

此功能检查鼠标位置和元素边界框,并检查它们是否重叠

function onHover(E,callback){
    window.addEventListener('mousemove',e=>{
        let R = E.getBoundingClientRect(); // get the element real dimentions 
        let x = e.pageX; // mouse x position 
        let y = e.pageY; // mouse y position 
        
        // check if mouse is within the the element box
        if(
            x > R.x && x < (R.x + R.width) 
         && y > R.y && y < (R.y + R.height)
        ){
            callback(true)
        }else{
            callback(false)
        }
    })
}

如何使用
let E = document.querySelector('.layer'); // get the element that needs hover effect 
onHover(E,isHovering=>{
    if(isHovering){
        E.style.color='red';//red for example to indicate hover state 
    }else{
        E.style.color='black'; //black to indicate normal state 
    }
})

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