You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shadow DOM中CSS :hover与cursor属性失效问题排查与解决

问题

开发浏览器插件时,通过Shadow DOM向任意网站插入组件,静态样式正常生效,但CSS的:hover选择器与cursor属性无法正常工作。鼠标悬停图标按钮时,既不显示深色背景也不切换为指针光标。

相关代码片段

内容脚本(创建Shadow DOM)

var inpagePopupHTML = "";
var insertStylesHTML = "";

// 从资源文件加载组件HTML(正常工作)
$.get(browser.runtime.getURL("/ui/mistake-popup.html"), function(data) {
  inpagePopupHTML = data;
});

// 从仅包含<style>的HTML文件加载样式(正常工作)
$.get(browser.runtime.getURL("/css/insert-styles.html"), function(data) {
  insertStylesHTML = data;
  document.body.innerHTML += data; // 插入到页面是因为样式同时作用于整个页面和组件
});

$("body").append('<div class="grammle--shadow" style="all: initial;"></div>'); // "all: initial" 阻止Shadow DOM继承页面样式
var shadow = document.querySelector(".grammle--shadow").attachShadow({ mode: "open" });
shadow.innerHTML += inpagePopupHTML;
shadow.innerHTML += insertStylesHTML; // 同样的CSS文件也放入Shadow DOM,因为包含组件样式

mistake-popup.html

<div class="grammle--popup grammle--popup--minimised">
  <div class="grammle--popup-text">
    <span class="grammle--popup-text-counter">0</span>
    <span class="grammle--popup-text-label">Fehler</span>
  </div>

  <div class="grammle--popup-icons">
    <span class="grammle--popup-icon" part="icon">
      <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-up" viewBox="0 0 16 16">
        <path fill-rule="evenodd" d="M7.646 4.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1-.708.708L8 5.707l-5.646 5.647a.5.5 0 0 1-.708-.708l6-6z"/>
      </svg>
    </span>

    <span class="grammle--popup-icon" part="icon">
      <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x-lg" viewBox="0 0 16 16">
        <path d="M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8 2.146 2.854Z"/>
      </svg>
    </span>
  </div>
</div>

insert-styles.html

<style>
:root {
    --grammle-dark-main-colour: #137768;
    --grammle-dark-main-colour-hover: #0f6a5d;
}
...

.grammle--popup-icon {
  cursor: pointer;
  padding: 4px;
  background-color: var(--grammle-dark-main-colour);
  border-radius: 3px;
}

.grammle--popup-icon:hover {
  background-color: var(--grammle-dark-main-colour-hover);
}

...
</style>

原因分析

核心问题在于Shadow DOM容器的style="all: initial;"设置:

  • all: initial会重置元素的所有CSS属性,其中包括将pointer-events重置为none,这会导致容器内的所有元素无法接收鼠标事件,:hover状态自然不会触发,cursor属性也无法生效。
  • 另外,同时将样式插入主文档和Shadow DOM的操作,虽不直接导致当前问题,但可能引发潜在的样式冲突。

修复方案

1. 恢复Shadow DOM容器的鼠标事件能力

保留all: initial的同时,手动指定pointer-events: auto以恢复鼠标事件接收:

$("body").append('<div class="grammle--shadow" style="all: initial; pointer-events: auto;"></div>');

或者直接移除all: initial——Shadow DOM本身自带样式隔离特性,不需要强制重置容器样式来隔离:

$("body").append('<div class="grammle--shadow"></div>');

2. 优化样式加载逻辑(可选)

拆分全局样式与组件样式,避免重复插入:

  • 将作用于主文档的全局样式单独放入global-styles.html,仅插入到主文档
  • 组件样式保留在insert-styles.html,仅放入Shadow DOM
// 加载全局样式到主文档
$.get(browser.runtime.getURL("/css/global-styles.html"), function(data) {
  document.body.innerHTML += data;
});

// 加载组件样式到Shadow DOM
Promise.all([
  $.get(browser.runtime.getURL("/ui/mistake-popup.html")),
  $.get(browser.runtime.getURL("/css/insert-styles.html"))
]).then(function([popupHTML, stylesHTML]) {
  $("body").append('<div class="grammle--shadow"></div>');
  var shadow = document.querySelector(".grammle--shadow").attachShadow({ mode: "open" });
  shadow.innerHTML = popupHTML + stylesHTML;
});

3. 修正异步加载顺序(必做)

原代码中$.get是异步操作,可能出现Shadow DOM已创建但内容/样式未加载完成的情况,用Promise.all确保资源加载完成后再创建Shadow DOM,避免内容缺失。


内容的提问来源于stack exchange,提问作者Pixelcode

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 19:20:47