SimplGy
SimplGy

Reputation: 20437

When does IE7 recompute styles? Doesn't work reliably when a class is added to the body

I have an interesting problem here. I'm using a class on the element as a switch to drive a fair amount of layout behavior on my site.

If the class is applied, certain things happen, and if the class isn't applied, they don't happen. Javascript is used to apply and remove the class. The relevant CSS is roughly like this:

.rightSide { display:none; }
.showCommentsRight .rightSide { display:block; width:50%; }
.showCommentsRight .leftSide { display:block; width:50%; }

And the HTML:

<body class="showCommentsRight">
    <div class="container"></div>
        <div class="leftSide"></div>
        <div class="rightSide"></div>
    </div>
    <div class="container"></div>
        <div class="leftSide"></div>
        <div class="rightSide"></div>
    </div>
    <div class="container"></div>
        <div class="leftSide"></div>
        <div class="rightSide"></div>
    </div>
</body>

I've simplified things but this is essentially the method. The whole page changes layout (hiding the right side in three different areas) when the flag is set on the body. This works in Firefox and IE8. It does not work in IE8 in compatibility mode. What is fascinating is that if you sit there and refresh the page, the results can vary. It will pick a different section's right side to show. Sometimes it will show only the top section's right side, sometimes it will show the middle.

I have tried:
- a validator (to look for malformed html)
- double checked my css formatting, and...
- making sure my IE7 hack sheet wasn't having an effect.
- putting the flag class on a different, non-body wrapper element (still has the same odd behavior)

So my question is:
- Is there a way that this behavior can be made reliable?
- When does IE7 decide to re-do styling?

Thanks everyone.

Upvotes: 8

Views: 1158

Answers (5)

Mike Flynn
Mike Flynn

Reputation: 24325

Here is my two cents. An issue with expando object was happening, so the following worked for me with a settimout delay. My issue was the background image wasn't appearing when I inserted some HTML.

    app.viewModel.modules.updateSpeech = function (element) {
        if ($('html').hasClass('IE7')) {
            var cssClass = $(element).attr('class') || element['class'];
            if (cssClass)
                setTimeout(function() { $(element).removeClass(cssClass).addClass(cssClass); }, 0);
        }
    };

Upvotes: 0

Christopher Parker
Christopher Parker

Reputation: 4621

It seems like you're running into either an IE6/IE7 reflow/repaint issue or IE6/IE7 layout issue.

See http://www.phpied.com/rendering-repaint-reflowrelayout-restyle/ for a detailed and informative analysis of what triggers reflow, repaint, etc. Also see http://www.satzansatz.de/cssd/onhavinglayout.html to find out what causes an element in IE to "have layout".

You could trigger both "having layout" and a reflow by setting height: 1%;. This is known as the Holly hack, named after the first person to document it, Holly Bergevin.

Upvotes: 0

Stein G. Strindhaug
Stein G. Strindhaug

Reputation: 5119

Sounds a bit like a problem I've had with ie7, where the DOM is updated but the pixels on screen is not (sometimes hovering the mouse over it triggers redraw). I found a dirty hack that worked in my case (spesudo-javascript):

//Just after changing the css class:
if(isIe7()){
    addAnEmptyDivAboveTheChangedElement();
    removeTheEmptyDivFromTheDom();
}

For some reason this brutal hack of adding and removing an element (it might even work if you add and remove it anywhere) causes ie7 to repaint the document. It may cause a flicker though and it's an expensive hack since it forces a full repaint in an already slow browser, that's why i only does so if I'm sure it's ie7 (to not slow every other browser just because ie7 is stupid).

Can't promise it will work, though... When I tried to find a solution to my problem I found lots of different hacks that didn't work. Fixing ie7's inconsistencies with javascript is pretty much trial and error woodoo. :)

PS: I see toggling display is allready suggested, it might work, or as in my case, it did not. I had to actually remove the element from the dom tree to make it work..

Upvotes: 2

SimplGy
SimplGy

Reputation: 20437

Close to a solution here, maybe someone else can bring it the last bit of the way.

The page behaves as expected if:
- If the style is assigned to the body by hand instead of using javascript.
(not an acceptable solution, but worth noting)
- If the elements that IE7 isn't updating (the .rightSide's) are manually pants-kicked with something like $(".rightSide").hide().show();

That second solution is darn close to workable, except that I actually am looking for show hide behavior out of my flag, so I'd want a less intrusive thing to change that will make IE refresh the styles.

Upvotes: 0

Shuriken
Shuriken

Reputation: 701

Try this:

.showCommentsRight .rightSide { display:block !important; width:50%; }
.showCommentsRight .leftSide { display:block !important; width:50%; }

Upvotes: 0

Related Questions