I'm helping to debug a CSS issue where two identical selectors are loading in a different order between two identically configured servers. One rule gets loaded from a stylesheet defined in the page and another gets loaded by Javascript injecting the stylesheet file.
According to the cascade rules, as I read them, it should come down to the order in which the rules are specified. It appears as though the issue is a race condition, but it's not clear what the basis for the race condition is. In Chrome's network tab, the files are listed in the same order between the two servers; however, when you drill down to the element level in the Elements tab, the rule taking precedence on a given server is listed first.
What determines the order in which the CSS is "specified" between two elements when loaded like this?
If the selectors are identical, it comes down to order... order within the CSS and the DOM. So, the question is, where did you place the dynamically generated <link>
(or <style>
) in relation to the original <link>
(or <style>
)? The order within the DOM matters.
If you'd like to make sure that your dynamically created CSS gets evaluated first, add it to the top of the <head>
:
document.head.insertBefore(myLink, document.head.firstChild);
If you'd like it to be evaluated last, append it to the <body>
:
document.body.appendChild(myLink);
Whichever rule is evaluated last will be the one applied (barring use of !important
)
Here's an example:
<!DOCTYPE html>
<html>
<head>
<style>
p {
color: green;
}
</style>
</head>
<body>
<p>test</p>
<script>
(function() {
var red = document.createElement("style");
red.textContent = "p { color: red }";
// We'll add this to the top of head. You'll never even notice because it will
// be overridden by the existing green style.
document.head.insertBefore(red, document.head.firstChild);
var blue = document.createElement("style");
blue.textContent = "p { color: blue }";
// We'll add this to the end of the body after a three second delay. It will
// override the other styles.
setTimeout(function() {
document.body.appendChild(blue);
}, 3000);
})();
</script>
</body>
</html>