Force IE to recompute styles?

2019-07-20 20:47发布

问题:

I have built a javascript/css dependency manager similar to http://code.google.com/p/jingo/.

It allows me to do something like this:

Loader.DependsOn(['/scripts/jqueryui.js', '/scripts/jquery.js'])
      .Css('/css/jquery.css')
      .Execute(function() { //Insert script here});

Loader will dynamically load both the script and the css before executing (if they haven't been loaded already).

Everything is working, except in IE. The style sheets are loaded by appending a link to the head of the document. However, before doing this, the loader looks to see if the requested css file is itself dependent on another module. If it is, it will figure out where in the order of CSS files it should be inserted. In all browsers except IE, if I insert it at the beginning of the list, any other stylesheets after will override it's styles (intended behavior). In IE, however, although it is inserted at the beginning, IE treats it as if it were at the end.

Is there a way to force IE to recompute styles?

UPDATED WITH TEST CASE:

Create two styles sheets, sheet1.css, sheet2.css

sheet1.css

.testdiv
{
    width:200px;
    height:200px;
    background-color:#c7c7c7;
}

sheet2.css

.testdiv
{
    width:400px;
    height:400px;
}

markup:

<html>
    <head>
        <link href="style1.css" rel="stylesheet" "type="text/css" />
    </head>
    <body>
        <div class="testdiv">
        </div>
    </body>
</html>
<script type="text/javascript" language="javascript>
     setTimeout(function() {

        var link = document.createElement('link');
        link.href = 'sheet2.css';
        link.rel = 'stylesheet';
        link.type = 'text/css';
        var head = document.head || document.getElementsByTagName('head')[0];
        head.insertBefore(link, head.children[0]);

        setTimeout(function () {
            //suggestion from Simon West
            document.body.className = document.body.className;
        }, 3000);

    }, 3000);    
</script>

What should happen:

Gray box 200px by 200px. After 3 seconds, it's still there. No change.

What happens on IE8

Gray box 200px by 200px. After 3 seconds, it grows to 400px by 400px.

What happens on Safari (windows) -

Gray box 200px by 200px. After 3 seconds, it's still there. No change.

This occurs with or without @Simon West's suggestion.

回答1:

<html>
<head>
    <link href='sheet1.css' rel='stylesheet' type='text/css'>
</head>
<body>
    <div class='testdiv'></div>
    <script type='text/javascript'>
setTimeout(function() {
    var link = document.createElement('link');
    link.href = 'sheet2.css';
    link.rel = 'stylesheet';
    link.type = 'text/css';
    var head = document.getElementsByTagName('head')[0];
    head.insertBefore(link, head.children[0]);

    var docElem = document.documentElement,
        docElemNext = docElem.nextSibling;
    document.removeChild(docElem); // this will clear document.styleSheets
    document.insertBefore(docElem, docElemNext);
}, 500);
    </script>
</body>
</html>


回答2:

The following JS snippet should force a reflow/repaint of the entire page.

document.body.className = document.body.className;