如何在纯CSS中模拟鼠标悬停以激活CSS“:hover”?


82

我一直在尝试寻找mouseover在Chrome中进行模拟的代码,但是即使触发了“ mouseover”侦听器,也从未设置CSS“ hover”声明!

我也尝试过:

//Called within mouseover listener
theElement.classList.add("hover");

但是似乎没有什么可以将元素更改为其hover声明中声明的内容。

这可能吗?


6
@PSL我认为他想做的是:hover在元素上施加强制状态。
本杰明·格林鲍姆

1
@BenjaminGruenbaum是的,您是对的。我误解了。
PSL 2013年

1
这不是重复的。另一个问题是关于jQuery的。这个问题是关于纯JS的。
Chuck Le Butt 2014年

1
@Monk OQ包含jQuery标签。这是重复项。
JasonMArcher 2014年

1
@JasonMArcher问题(及其答案)是关于纯JS的。您是否认为他们更有可能误解了它。
Chuck Le Butt 2014年

Answers:


106

你不能 这不是一个值得信任的事件

由用户代理生成的事件,无论是由于用户交互还是由于DOM更改而直接产生的事件,都由用户代理信任,其特权不提供给脚本通过DocumentEvent.createEvent生成的事件。 (“事件”)方法,可以使用Event.initEvent()方法进行修改,也可以通过EventTarget.dispatchEvent()方法进行调度。受信任事件的isTrusted属性值为true,而不受信任事件的isTrusted属性值为false。

除click或DOMActivate事件外,大多数不受信任的事件都不应触发默认操作

您必须添加一个类,并在mouseover / mouseout事件上手动添加/删除该类。


4
@Tim,实际上并没有回答为什么。它只是改变了问题
Pacerier,2015年

7
@Pacerier这不是一个受信任的事件,因为它不是由用户启动的。我的回答在上面的引言中说得很。从字面上看,答案就是从此开始的。
本杰明·格伦鲍姆

1
@BenjaminGruenbaum,我引用的是“ click或DOMActivate事件除外”。“悬停”有什么特别之处,以至于不在此例外列表中?为什么允许我们称“焦点”而不是“悬停”?这些是我们必须回答的问题,回答其他任何问题都只会改变问题
Pacerier

1
我认为悬停(并与单击或鼠标上下拖动相结合)可能表现为或看起来像劫持用户系统(如果您忽略自动化案例),因此不理想地进行支持。单击我不能说,但是焦点将允许自动焦点到目标表单字段或网站设计者希望用户关注的元素,例如文本字段缺少或不正确的数据(例如,表单字段验证检查)。但这只是我的假设。
大卫

2
是的,听起来很荒谬,您可以使焦点看起来像是由用户交互引起的,而实际上并不是由用户交互引起的。在实践中-浏览器API会很乐意违反规范,而忽略焦点并单击是不受信任的事件(至少是Chrome)。尝试例如模拟对chrome扩展程序的扩展程序安装按钮的单击,看看会发生什么:)
Benjamin Gruenbaum 2015年

37

您可以像这样模拟mouseover事件:

的HTML

<div id="name">My Name</div>

的JavaScript

var element = document.getElementById('name');
element.addEventListener('mouseover', function() {
  console.log('Event triggered');
});

var event = new MouseEvent('mouseover', {
  'view': window,
  'bubbles': true,
  'cancelable': true
});

element.dispatchEvent(event);

谢谢,我需要的只是气泡!右键单击开发者控制台检查器中的元素,然后执行“在控制台中使用”(Firefox)或“存储为全局变量”(Chrome)。然后,您可以,例如, temp0.dispatchEvent(new MouseEvent('mouseover', {bubbles: true})) 对样式提示或仅在鼠标悬停时显示的其他内容非常有用。
丹尼斯·豪

这是太棒了。
rebelliard

1
@DenisHowe对于该用例,您应该:hov在devtools中检出样式检查器顶部的按钮。它使您可以激活要检查的元素上喜欢的任何伪类。
哈罗

17

背景

在尝试编写自动化测试时,我偶然发现了这个问题,以验证给定页面上的所有特定元素集都具有css为on悬停事件设置的css属性集。

尽管上面的答案可以完美地说明问题,但为什么不能简单地通过JS触发悬停事件,然后探究一些感兴趣的CSS值,却确实回答了最初的问题“如何在激活CSS的纯JavaScript中模拟鼠标悬停” :徘徊”?” 仅部分。

免责声明

这不是高效的解决方案。我们仅将其用于不关心性能的自动化测试。

simulateCssEvent = function(type){
    var id = 'simulatedStyle';

    var generateEvent = function(selector){
        var style = "";
        for (var i in document.styleSheets) {
            var rules = document.styleSheets[i].cssRules;
            for (var r in rules) {
                if(rules[r].cssText && rules[r].selectorText){
                    if(rules[r].selectorText.indexOf(selector) > -1){
                        var regex = new RegExp(selector,"g")
                        var text = rules[r].cssText.replace(regex,"");
                        style += text+"\n";
                    }
                }
            }
        }
        $("head").append("<style id="+id+">"+style+"</style>");
    };

    var stopEvent = function(){
        $("#"+id).remove();
    };

    switch(type) {
        case "hover":
            return generateEvent(":hover");
        case "stop":
            return stopEvent();
    }
}

说明

generateEvent读取所有css文件,然后用空字符串替换:hover并应用它。效果是,所有:hover样式都被应用。现在,您可以探查一下晃动的样式,并通过停止模拟将其设置回初始状态。

为什么我们通过从工作表中获取并执行element.css(...),而不是将感兴趣的元素应用于整个文档,而不是整个文档?

完成后,该样式将被内联应用,这将覆盖其他样式,而原始css悬停样式可能不会覆盖其他样式。

现在如何模拟单个元素的悬停?

这不是性能,所以最好不要。如果需要,可以使用element.is(selectorOfInterest)检查样式是否适用于您的元素,并且仅使用这些样式。

在茉莉花中,您现在可以例如执行:

describe("Simulate CSS Event", function() {
    it("Simulate Link Hover", function () {
      expect($("a").css("text-decoration")).toBe("none");
      simulateCssEvent('hover');
      expect($("a").css("text-decoration")).toBe("underline");
      simulateCssEvent('stop');
      expect($("a").css("text-decoration")).toBe("none");
    });
});

1
这个答案很好!不幸的是,由于Chrome限制了对跨域请求的访问,因此在带有其他主机提供的样式表的页面上的最新版本的Chrome上,此操作失败。请参阅我的答案以获取支持此方法的解决方案:)
FThompson

6

我最常做在这种情况下是使用JavaScript添加类..和将相同CSS:hover这一类

尝试使用

theElement.addEventListener('onmouseover', 
    function(){ theElement.className += ' hovered' });

或对于较旧的浏览器:

theElement.onmouseover = function(){theElement.className += ' hovered'};

当然,onmouseout当您离开元素时,您将不得不使用删除“悬停的”类...


尽管按照正确的方向或多或少,这将不会满足OP的要求。最好使用现代事件处理程序附件技术。
尖尖的

抱歉,被误解的问题
Yotam Omer 2013年

@Pointy这个问题要求使用纯JavaScript。否则如何附加事件?
Yotam Omer

2
还不够好?它是“纯” JavaScript,实际上它将附加一个函数作为事件的处理程序。在Internet Explorer中,将使用(几乎)等效项attachEvent()
Pointy 2013年

值得一提。IE9和10支持addEventListener,这是附加事件的最佳方法,attachEvent仅在IE8(及以下版本)中需要填充。Yotam,如果他onmouseover通过直接设置属性(而不是添加事件侦听器)来添加另一个处理程序,它将覆盖当前设置的事件。看到这个问题的区别。
本杰明·格林鲍姆

4

您可以使用pseudo:styler,该库可以将CSS伪类应用于元素。

(async () => {
  let styler = new PseudoStyler();
  await styler.loadDocumentStyles();
  document.getElementById('button').addEventListener('click', () => {
    const element = document.getElementById('test')
    styler.toggleStyle(element, ':hover');
  })
})();

免责声明:我是该库的合著者。我们对其进行了设计,以额外支持跨域样式表,尤其是在可能无法控制页面CSS规则的Chrome扩展程序中使用。


1
即使window.getComputedStyle(<youElement>)在设置伪样式后与之结合使用,这似乎实际上也相当不错。谢谢!
Daniel Veihelmann

2

我假设您要在dom操作之后检查CSS,但是一旦将鼠标移回devtools,该事件就不再在该html元素上处于活动状态。您可能希望在devtools中为JavaScript事件提供类似:hover选项的东西。那不存在,但是您可以模拟它。

  1. 打开您的devtools并单击它以将其激活。
  2. 在您感兴趣的元素上触发事件。
  3. 在不移动鼠标的情况下,使用ctrl + shift + p打开devtools命令面板,然后使用键盘选择“禁用javascript”。

由于禁用了javascript,因此没有机会再次修改元素。您可以转到devtools并检查css和html,就好像您正在对其进行悬停,单击或执行其他操作一样。完成后,再次转到命令面板,然后选择“启用javascript”。


整洁的技术,但是除非我误解了您的意图,否则devtools已经存在该技术!在Chrome / Chromium和Firefox的devtools中,:hov样式检查器的顶部都有一个按钮(“过滤器”输入框旁边)。点击:hov膨胀一系列复选框,每个标有一个伪类::active:focus:focus-within:hover,和:visited。选中这些框中的任何一个都会在要检查的元素上激活其各自的伪类。
哈罗
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.