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

如何修改UserScript使其对Shadow DOM中的链接样式生效?

解决UserScript无法修改Shadow DOM内已访问链接颜色的问题

你的UserScript无法影响Shadow DOM内的链接,核心原因是普通样式表无法穿透Shadow DOM的隔离边界——主文档的样式不会自动应用到Shadow内部,必须把样式直接注入到每个Shadow根的上下文里。

下面是修改后的完整脚本,同时支持普通DOM和Shadow DOM内的链接样式修改,还能处理页面动态生成的Shadow元素:

// ==UserScript==
// @name        Change the color of visited links (Shadow DOM Support)
// @description Modify link colors including those inside Shadow DOM
// @match       *://*/*
// @grant       none
// ==/UserScript==

// 通用样式注入函数,支持传入目标容器(主文档head或Shadow根)
function injectStyle(css, targetDoc = document) {
    const head = targetDoc.head || targetDoc.querySelector('head') || targetDoc.documentElement;
    if (!head) return;
    
    const style = targetDoc.createElement('style');
    style.type = 'text/css';
    style.textContent = css.replace(/;/g, '!important;');
    head.appendChild(style);
}

// 生成链接样式的CSS文本
function getLinkStyles(anylink, link, visited, hover, active) {
    return `
        ${anylink} { outline: solid 1px; }
        ${link}    { color: blue;    }
        ${visited} { color: fuchsia; }
        ${hover}   { color: red;     }
        ${active}  { color: yellow;  }
    `;
}

// 递归遍历所有Shadow DOM并注入样式
function injectIntoAllShadowRoots(css, currentDoc = document) {
    // 处理当前文档/Shadow根内的普通DOM
    injectStyle(css, currentDoc);
    
    // 遍历当前上下文里所有带Shadow根的元素
    currentDoc.querySelectorAll('*').forEach(el => {
        if (el.shadowRoot) {
            injectStyle(css, el.shadowRoot);
            // 递归处理Shadow内部的嵌套Shadow DOM
            injectIntoAllShadowRoots(css, el.shadowRoot);
        }
    });
}

// 监听DOM变化,处理动态添加的Shadow DOM
function setupDynamicShadowObserver(css) {
    const observer = new MutationObserver(mutations => {
        mutations.forEach(mutation => {
            mutation.addedNodes.forEach(node => {
                if (node.nodeType === Node.ELEMENT_NODE) {
                    // 检查当前新增节点是否有Shadow根
                    if (node.shadowRoot) {
                        injectStyle(css, node.shadowRoot);
                        injectIntoAllShadowRoots(css, node.shadowRoot);
                    }
                    // 检查子节点里的Shadow DOM
                    node.querySelectorAll('*').forEach(child => {
                        if (child.shadowRoot) {
                            injectStyle(css, child.shadowRoot);
                            injectIntoAllShadowRoots(css, child.shadowRoot);
                        }
                    });
                }
            });
        });
    });
    
    observer.observe(document.body, {
        childList: true,
        subtree: true
    });
}

// 初始化执行
const linkCSS = getLinkStyles(
    'a:any-link , a:any-link *',
    'a:link     , a:link     *',
    'a:visited  , a:visited  *',
    'a:hover    , a:hover    *',
    'a:active   , a:active   *'
);

injectIntoAllShadowRoots(linkCSS);
setupDynamicShadowObserver(linkCSS);

关键修改说明:

  • injectStyle函数:新增targetDoc参数,支持向Shadow根的文档上下文注入样式,不再局限于主文档的head。
  • injectIntoAllShadowRoots函数:递归遍历页面中所有已存在的Shadow DOM元素,把样式注入到每个Shadow根内部,包括嵌套的Shadow结构。
  • setupDynamicShadowObserver函数:使用MutationObserver监听DOM变化,处理页面后续动态生成的Shadow DOM元素,确保样式能覆盖到新增内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 00:12:36