如何修改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
相关产品推荐
相关产品推荐

