Injected link stylesheet takes precedence over existing styles in IE7+
Asked Answered
P

1

6

There seems to be a bug in IE when cascading dynamic stylesheets. Does anyone know if there is a workaround? Consider this:

<head>
    <style>#test{background:red;}</style>
</head>
<body>
    <div id="test">test</div>
    <script>
        var link = document.createElement('link');
        var style = document.getElementsByTagName('style')[0];
        link.rel = 'stylesheet';
        link.href = 'test.css';
        style.parentNode.insertBefore(link, style);
    </script>
</body>

The injected 'test.css' contains #test{background:green}.

Even though we place the <link> before the <style> tag, IE7+ will override the styles with the injected stylesheet and apply green as background.

FF/Chrome do this the right way and lets the style tag take precedence over the injected link tag so the background stays red.

Propraetor answered 1/7, 2010 at 13:47 Comment(4)
style tags in the body are invalid (even though tolerated by all browsers). Still, I agree with you that what FF & co. do is the expected behaviour.Centimeter
yea, the same effect happens in the head. I just wanted to state a clear example.Propraetor
The dynamic link is missing a type property - hardly the root of the problem but should be fixed to exclude obscure bugs. Also, I would post a valid head based example for the same reason. Could it be that the dynamic element isn't created in IE at all? Do other styles embedded this way work? Which versions of IE does this apply to?Centimeter
The dynamic element is created since it actually overrides the styles. Corrected the code as you suggested if it makes more sense.Propraetor
U
2

I think the cause for this is the way IE defines insertBefore. In IE only you may pass only one parameter into the insertBefore method and it will behave the same as appendChild. I think what they do is insert it THEN move it. If they render at the point of insertion then it would be rendering properly.

The only work around I can think of is as follows (which isn't ideal):

    var link = document.createElement('link');
    var style = document.getElementsByTagName('style')[0];
    var newstyle = style.cloneNode(true);
    link.rel = 'stylesheet';
    link.href = 'test.css';
    style.parentNode.insertBefore(link, style);
    style.replaceNode(newstyle);
Umbra answered 2/7, 2010 at 14:57 Comment(1)
Yes, I did something similar in the end. I "touched" all link and style elements on the page after injection.Propraetor

© 2022 - 2024 — McMap. All rights reserved.