views:

54

answers:

4

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.

A: 

Try this:

.showCommentsRight .rightSide { display:block !important; width:50%; }
.showCommentsRight .leftSide { display:block !important; width:50%; }
Shuriken
IE doesn't understand `!important`.
Pekka
IE7 and higher should understand it. Since the issue here is with IE7, it's worth a shot.
keithjgrant
Doesn't work. I'm kind of glad, because I didn't want to leave any bang-important's in my code.As I said in the edit, this all works fine if the class is applied to a wrapping element by hand, ahead of time, rather than JS--so the inheritence is fine.
Simple As Could Be
Why not `.showCommentsRight .rightSide, .showCommentsRight .leftSide { display:block !important; width:50%; }` instead?
Eli Grey
Am I missing a subtlety here, Eli, or are you just talking about grouping the selectors? The rule doesn't achieve the desired effect so grouping it differently doesn't help. Although I'd agree that if this worked yours would be the simpler way to write it.
Simple As Could Be
I don't know where you heard IE doesn't understand `!important`. Even IE6 understands `!important`. I use `!important` to work around some of IE6's specificity quirks, as a matter of fact.
Christopher Parker
A: 

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.

Simple As Could Be
+1  A: 

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..

Stein G. Strindhaug
This is right on the button. I ended up using: if ($.browser.class == "msie7") { _$thingToRefresh.addClass("kickIE").removeClass("kickIE");}If there were a less resource intensive way to do it, I'd use it but I didn't find anything.
Simple As Could Be
A: 

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.

Christopher Parker