IE expressions ignore CSS media types

A client recently reported that there was a problem with their print stylesheet causing content to be cut off at the right margin. I had a look at it and couldn’t see a problem until I tried printing from Internet Explorer. There was a problem alright.

It was really puzzling since all the print CSS for that site does is basically hide parts that are irrelevant when printing. There shouldn’t be any conflicts with other style sheets either since the screen style sheets use a different media type. But I was wrong - in some cases IE will apply CSS that it shouldn’t.

The problem occurs when you use Microsoft’s proprietary CSS expressions. Any declarations that contain an expression will be applied when printing. Consider the following setup for loading the various CSS files:

  1. <style type="text/css" media="screen,projection">
  2. @import 'main.css';
  3. </style>
  4. <!--[if IE]>
  5. <link rel="stylesheet" href="ie.css" type="text/css" media="screen">
  6. <![endif]-->
  7. <link rel="stylesheet" href="print.css" media="print" type="text/css">

First, main.css is imported by all browsers and is used for the screen and projection media types. Next, conditional comments are used to send ie.css to Internet Explorer for Windows. Note the screen media type. Finally all browsers will load print.css when the media type matches print. All good so far.

Now, consider the common scenario of wanting to use max-width to make sure line length stays readable even in very wide browser windows. Since IE versions below 7 do not support that, a common workaround is to use an expression similar to this:

  1. #content { width:expression((document.documentElement.clientWidth > 1080) ? "1050px" : "auto"); }

This will be applied when the page is printed even though it shouldn’t be, and leads to content being cut off if the element’s width as calculated by the expression exceeds the width of the selected paper size. The expression in my example will set the width of #content to 1050 pixels when the window is wider than 1080 pixels. That is wider than an A4 size paper and the page is cut off. If the window is narrow enough to make the expression set the width of #content to “auto”, printing works fine. Very odd. Besides, only the rules in print.css should be used when printing, and this is respected by all other browsers I have tested.

The workaround I found is to override any declarations that use expressions. I prefer putting this in a file called ie-print.css. In this case, that file would contain the following:

  1. #content { width:auto !important; }

Note the use of !important. Just redeclaring the property in a stylesheet that loads after ie.css does not work. (Sidenote: This is the first time I’ve actually found a use for !important.)

I load the file by adding another link element inside the conditional comment:

  1. <style type="text/css" media="screen,projection">
  2. @import 'main.css';
  3. </style>
  4. <!--[if IE]>
  5. <link rel="stylesheet" href="ie.css" type="text/css" media="screen">
  6. <link rel="stylesheet" href="ie-print.css" type="text/css" media="print">
  7. <![endif]-->
  8. <link rel="stylesheet" href="print.css" media="print" type="text/css">

To sum it up: If you’re having problems with print style sheets in Internet Explorer for Windows, check your use of CSS expressions.

Posted on November 29, 2006 in Browsers, CSS

Comments

  1. November 29, 2006 by Bill Criswell

    That’s about the only time I’ve ever seen !important used at all.

  2. Thanks! Great tip!

    (Del.icio.us’ed)

  3. November 29, 2006 by Sascha

    I also ran into this strange “ie-expression-and-print” behavior. My workaround so far: I overwrite the element i gave the expression width an “display:inline;” in the print stylesheet.

  4. One way !important is useful is cases where you want to use a single class to override some style globally (global context, specific element)- e.g.

    .noborder {border:none !important;}
    

    Here it acts like a trump card because without the !important the specificity of another declaration would almost certainly be higher, however to increase the specificity of the style would limit it’s scope.

    Maybe not the very best semantics, but sometimes considerably easier than evaluating every single situation and styling for it in CSS.

  5. I am sure this would have caught me out on a current project that uses a jello layout and also requires a significantly different print stylesheet, had you not found and solved it for me! Thank you so much :-)

  6. Damn! Thats pretty lame…

    I often use important when dealing with IE (and not using conditional comments for whatever reason):

    height : auto !important; height : 1%; overflow : hidden; == hasLayout : true;

  7. I don’t use expressions very often, but as I understand it, they are a kind of hook for scripting through stylesheets. If you think of the max-width hack you used as a way of implementing some JavaScript from your stylesheet, then it makes sense that the changes to the page would be applied to the print version. They would be if JavaScript had been included from elsewhere. On the other hand, the fact that another style can override the expression doesn’t fit with that idea. In any case, this is yet another very strange IE 6 behavior, and a good one to know about. Thanks!

  8. I ran into this behavior too. I think I fixed it with an extra (redundant) @media block…

  9. I have used !important a lot - inside Firefox’s userContent.css and userChrome.css.

  10. Thanks for the tip! This might save some troubleshooting for me eventually.

    But I was wondering if the !important really is necessary or if it would be sufficient to increase the specificity of that #content selektor… e.g. to div#content (assuming that it really is a “div”-Element).

  11. @ Johan: I was wondering the same thing as you are … maybe the expression has more weight over a normal value(you never know with microsoft)? “body #content” also is more specific (advantage over div#content is that it can be any element).

    wbr

    B!

  12. @Bramus: The calculated specificity of “body #content” and “div#content” should be the same (0,1,0,1). But I think it really does not matter that much, since a content-container is most likely a “div”-element.

  13. that’s so bizarre. Even setting @media blocks within the stylesheet doesn’t seem to work.

    Johan, it seems IE overrides any other CSS declarations (even those with a higher specificity) with anything in an expression so the !important really is necessary.

    As a side note we tried this expression technique to get both min and max widths for IE for a new site. However, a complicated expression (i.e. both min and max) combined with negative margins to get a fluid/fixed layout seemed to crash IE.

    So we used a min-max JavaScript implementation we found on the web. The issue you describe also affects this pure JavaScript implementation. And the same fix resolves it!

    Obviously this only hits IE6 since IE7 understands min and max-widths.

  14. That’s a great tip, Roger! Thanks very much :)

  15. They’re called “dynamic properties”, not “expressions.” See the following articles for more information:

    About Dynamic Properties: http://msdn.microsoft.com/workshop/author/dhtml/overview/recalc.asp

    Be More Dynamic: http://msdn.microsoft.com/library/en-us/dndude/html/dude061198.asp

    Introduction to Dynamic Properties (IE): http://www.javascriptkit.com/dhtmltutors/dynproperty.shtml

  16. November 30, 2006 by zcorpan

    Old news. :-)

  17. November 30, 2006 by Roger Johansson (Author comment)

    Yep, I haven’t been able to find a workaround without using !important.

    They’re called “dynamic properties”, not “expressions.”

    Yeah I stumbled upon those documents while trying to figure this out. I’d never heard anyone call them anything but “expressions”, so I decided to keep calling them that.

    zcorpan: Well, what do you know. Seems like no matter what problem you have, somebody else has already found a solution ;-).

  18. I just saw some I.E. problems in case of www.cssremix.com I presume that they optimized for F.F…

  19. Interestingly enough, the ‘related posts’ section lists a post of yours (from 2005) where you link to the article zcorpan mentions :).

  20. December 1, 2006 by Roger Johansson (Author comment)

    Dylan: Heheh, yeah apparently I completely forgot about that. Oh well, two different descriptions of the problem won’t hurt.

  21. !important is nice for .png background declarations.

  22. @Simon,

    I found that an expression for min-/max-width is only reliable if you apply it to a (wrapper) div, that has no box model properties applied, horizontally that is. You must not declare these properties for its parent element(s) either (most probably the body). Quirks mode/Standards mode also plays a role.

  23. December 3, 2006 by Roger Johansson (Author comment)

    Daniel:

    In any case, this is yet another very strange IE 6 behavior, and a good one to know about.

    IE 7 behaves the same way, but it is less likely to cause problems since IE 7 has CSS support for min/max width/height and doesn’t need expression hacks.

    One difference between IE 6 and 7 is that 7 seems to prefer “document.body.clientWidth” over “document.documentElement.clientWidth”, even in standards mode. “document.body.clientWidth” doesn’t work properly in IE 6 when using standards mode.

    simon:

    However, a complicated expression (i.e. both min and max) combined with negative margins to get a fluid/fixed layout seemed to crash IE.

    I’ve seen even less complicated expressions crash IE, so I am a little bit wary of using them.

    Dylan: A clarification: the list of related posts is automatically generated, so I didn’t notice that my old article was there until you mentioned it.

    Klaus: Interesting - that may be the cause of some problems I have seen with min/max expressions.

  24. Nice article, much appreciated. I’ve been pulling my hair out trying to support IE 6-7, Opera, Safari, and FF across both Mac and PC. This helps!

  25. Thank you Roger!! I was having this exact same problem on my site last week and couldn’t figure it out. Well, I knew that it was using the max-width value but didn’t realize why. I ended up setting the width to a fixed pixel value, so thanks for pointing out that width: auto works we well :) :)

  26. FWIW, what you’re experiencing isn’t a bug. It’s an artifact of an expression being a hook via CSS and scripting. While the use of !important seems to fix it, you should be careful to test that its use isn’t breaking anything else for other browsers. What I’d suggest, instead, is to use another expression in your ie-print.css to “undo” the affects of the offending expression.

  27. January 7, 2007 by Roger Johansson (Author comment)

    Jeff:

    While the use of !important seems to fix it, you should be careful to test that its use isn’t breaking anything else for other browsers.

    I put that rule in a file that is only sent to IE (conditional comments), so it won’t affect other browsers. I also think I experimented with using another expression to undo the unwanted effects, but didn’t succeed. I may be wrong though.

  28. I’d be happy if everyone just stopped using IE and switched to an alternative browser.

  29. January 26, 2007 by Keeler

    This is interesting… I don’t think this is happening because of the use of expressions specifically. I’m having this same problem in IE6 however I’m not using any CSS expressions; the right margin just rolls off of the page. Still working on figuring out a remedy…

    (glad I found your article though! Props on tracking down the issue pertaining to the use of expressions.)

  30. July 6, 2007 by Ria Lloyd

    Thank you. I have just spend several hours wondering why my printed pages were too wide in IE, but worked perfectly in other browsers. I finally found your article and added the #content { width:auto !important; } to my style sheet and all is well now.

  31. This is freakin’ awesome. I spent half the day trying to figure out why the right margin cut off in only IE6. Then I realized it was only on websites using flexible width CSS layouts.. which led me right to your article. Thank you, thank you, thank you!

Comments are disabled for this post (read why), but if you have spotted an error or have additional info that you think should be in this post, feel free to contact me.