This is my userscript to change the color of visited links. It is assumed to be able to work with any website.
// ==UserScript==
// @name Change the color of visited links
// @description -
// @match *://*/*
// ==/UserScript==
function style(css) {
let head, style;
head = document.getElementsByTagName('head')[0];
if (!head) return;
style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = css.replace(/;/g, '!important;');
head.appendChild(style);
}
function links(anylink, link, visited, hover, active) {
style(`
${anylink} { outline: solid 1px; }
${link} { color: blue; }
${visited} { color: fuchsia; }
${hover} { color: red; }
${active} { color: yellow; }
`);
}
links('a:any-link , a:any-link *',
'a:link , a:link *',
'a:visited , a:visited *',
'a:hover , a:hover *',
'a:active , a:active *'
);
The problem is that on some websites some links belong to shadow DOM elements, and by this reason they are not affected by the script. How this can be fixed?
temporary screenshot, see comments
You can access the shadow DOM with document.querySelector(selector).shadowRoot
From there all you need to find the first head
using querySelectorAll
or default to the element itself, and inject the CSS there.
// setup example
const host = document.querySelector("#host");
const shadow = host.attachShadow({
mode: "open"
});
const span = document.createElement("span");
span.innerHTML = "I'm in the shadow DOM <a href='#'>link</a>";
shadow.appendChild(span);
function addToHeadOrSelf(elem, css) {
var head
if (elem.getElementsByTagName) {
head = elem.getElementsByTagName('head')[0];
}
if (elem.querySelectorAll) {
head = elem.querySelectorAll('head')[0]
}
if (!head) {
head = elem
}
style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = css.replace(/;/g, '!important;');
head.appendChild(style);
}
function style(css) {
addToHeadOrSelf(document, css)
var elementsWithShadowRoot = findElementsWithShadowRoot()
elementsWithShadowRoot.forEach(function(elem) {
addToHeadOrSelf(elem.shadowRoot, css)
})
}
function findElementsWithShadowRoot() {
function hasShadowRoot(element) {
return element.shadowRoot !== null;
}
function traverseTree(node) {
if (hasShadowRoot(node)) {
elementsWithShadowRoot.push(node);
}
const children = node.children || [];
for (let i = 0; i < children.length; i++) {
traverseTree(children[i]);
}
}
const elementsWithShadowRoot = [];
traverseTree(document.body);
return elementsWithShadowRoot;
}
function links(anylink, link, visited, hover, active) {
style(`
${anylink} { outline: solid 1px; }
${link} { color: blue; }
${visited} { color: fuchsia; }
${hover} { color: red; }
${active} { color: yellow; }
`);
}
links('a:any-link , a:any-link *',
'a:link , a:link *',
'a:visited , a:visited *',
'a:hover , a:hover *',
'a:active , a:active *'
);
<div id="host"></div>
<span>I'm not in the shadow DOM <a href='#'>link</a></span>
<br />