Beware of Margins or Padding when Using the min-width Hack for IE
Published Sunday, September 14, 2008 @ 7:01 am • 15 Responses
While we all watch as Internet Explorer 6 dies a slow, painful death, many unfortunate designers and developers continue to find themselves dealing with IE6’s lack of support for simple things like minimum and maximum widths. Fortunately, there are solutions to this problem, primarily in the form of CSS expressions such as this:
/* set the minimum width for IE 6 */
#target_element {
width: expression((document.body.clientWidth < 335)? "333px" : "auto"); /* min-width for IE6 */
min-width: 333px; /* min-width for all standards-compliant browsers */
}
Although ugly, invalid, and resource-intensive, this technique works well at setting min-width properties for IE6. But beware! There is a catch. Chris Herdt recently wrote in with an important discovery:
…inclusion of any padding or margin on the element that has the fix applied will cause IE6 to crash…
After checking out Chris’ online demonstration of the behavior, I returned to the lab and began running a few tests. In addition to verifying and understanding Chris’ demonstration, I also wanted to know the following:
- Does this issue affect older (pre-6) versions of Internet Explorer?
- Is this issue seen in similar hacks such as max-width or max-height?
- What are some workarounds?
First of all, this issue seems only confined to Internet Explorer version 6. Although I didn’t test on IE4 or IE3 (why bother?), IE5 did not crash when put to the test. So, for all practical purposes, IE6 seems to be the only browser affected by this issue.
As for related CSS expressions, such as max-width and max-height, the addition of margins and/or padding does not seem to have such an effect. Only when using the CSS min-width expression (i.e., hack) on IE6 will the addition of margins and/or padding crash the browser.
To explore a couple possible workarounds for this bug, let’s first review the mechanism by which the min-width expression operates. Here it is again (so you don’t have to scroll up):
/* set the minimum width for IE 6 */
#target_element {
width: expression((document.body.clientWidth < 335)? "333px" : "auto"); /* min-width for IE6 */
min-width: 333px; /* min-width for all standards-compliant browsers */
}
The element for which we are applying the min-width property is typically a div. Here, we see that the ID of such an element is #target_element, surprisingly enough. So we have this division, and we want it to remain at least 332 pixels wide, regardless of how the browser is resized. 1. To accomplish this in Internet Explorer, we must use the JavaScript expression seen in the example; however, to accomplish the same thing in all modern browsers (e.g., Safari, Opera, Firefox, IE7, et al), we need only specify a value for the min-width property (i.e., the second declaration in our example). On a side note, this sort of browser-wrangling is exactly one of the reasons why people are so excited about the inevitable death of Internet Explorer 6.
So this is all fine and well and good, right? Well yes, it certainly works, but only until you try adding a bit of horizontal margin or padding to the target element, as seen in this example:
/* set the minimum width for IE 6 */
#target_element {
width: expression((document.body.clientWidth < 335)? "333px" : "auto"); /* min-width for IE6 */
min-width: 333px; /* min-width for all standards-compliant browsers */
margin-right: 1px; /* say goodnight, IE6! */
}
That little margin-right declaration will crash IE6 in a bad way. In fact, any of the following horizontally effective declarations will crash IE6, regardless of their values:
margin-right: 1px;margin-left: 1px;margin: 0 1px 0 1px;padding-right: 1px;padding-left: 1px;padding: 0 1px 0 1px;
This brings us to an easy workaround for this issue: don’t add horizontal (left and/or right) padding or margins to the target element of a min-width expression. You can add all the vertical (top and/or bottom) padding and margins that you need, but stay away from teh horizontal stuff!
If you do need to apply space between the target element and its parent, consider using Chris’ workaround:
…I applied padding to the body instead of the content div and then just changed the expression to document.body.clientWidth - [padding values] < [desired minimum width +1].
Simply apply the padding (or margins) to the parent of the target element and subtract the difference from the CSS expression:
/* first apply the padding to the parent element */
#parent_element {
padding-right: 33px;
padding-left: 33px;
/* sum equals 66px */
}
/* then set the minimum width for IE6 accordingly */
#target_element {
width: expression((document.body.clientWidth - 66 < 335)? "333px" : "auto"); /* min-width for IE6 */
min-width: 333px; /* min-width for all standards-compliant browsers */
}
Of course, there are probably other workarounds to consider as well. Perhaps there is a way to configure the layout that doesn’t even require the min-width property? I don’t know, but I do know one thing: if you are still required to design for Internet Explorer 6, you have my deepest sympathy.
Special thanks to Chris Herdt for discovering this issue and bringing it to my attention. With several articles now on the topic of using the CSS min-width expression, it is important to share any pertinent information that may affect its implementation. Hopefully, this article will prove helpful to those encountering issues with the technique.
Footnote
- 1 When using the
min-widthexpression, always increase the value of your desired minimum width by (at least) 1 pixel. This is necessary to prevent Internet Explorer crashing, this time for a completely different reason. For more information, check out this comment. ↑
About this article
Related articles
- CSS Hackz Series: Minimum Width, Maximum Width for Internet Explorer 6
- Maximum and Minimum Height and Width in Internet Explorer
- CSS Hack Dumpster
- Obsessive CSS Code Formatting: Opening and Closing Brackets
- Obsessive CSS Code Formatting: Indentation and Spacing
- Perishable Press CSS Hackz Series Summary
- Absolutely Centered Layout
Dialogue
15 Responses Jump to comment form
September 15, 2008 at 12:34 am
Simply forget about IE behaviour :)
I’m joking, but I enjoy people seeing their browser crashing and saying: “this site has something wrong” or “this site has a bug”. :D
By the way… hey Perishable, I’ve got problems sending posts with Firefox on this blog. I always have to use Opera or Internet Explorer (for my sadness) :D
September 16, 2008 at 1:23 am
I get a FORBIDDEN error page if I submit a post via Firefox.
I’ve got no security extensin, but now I’m actually behind a (fu**ing) ISA server :)
September 17, 2008 at 11:11 pm
I’m not the admin of ISA server.
I’m in my customer’ office! :)
I have no idea about what these buddies have done with their server :D
September 18, 2008 at 9:00 pm
Made the script simpler you can just call it like:
widthg: expression(IE6MinWidth(this,500));
And let it do the calculations for you. Makes writing the custom IE6 crap easier if you have to do it.
October 11, 2008 at 4:19 pm
Dealing with margins/padding in IE is one of the banes of my existence. I get hired by government departments to make their Internet Explorer only websites compatible with FireFox … it’s painful. Thanks for a great article.
October 22, 2008 at 10:37 am
If you use this: window.onload = checkAvailableWidth;window.onresize = checkAvailableWidth;function checkAvailableWidth(){var html = document.getElement("html");html.style.width = (document.body.clientWidth > 900)? "900px" : "auto";} then the problem should go away, along with having a much less resource-intensive way of solving IE6’s min and max problem. Javascript, of course.
October 22, 2008 at 11:23 am
Wow, I made that script and totally forgot about the 1 pixel difference; thanks.
Share your thoughts..
← Previous post • Next post →
« Series Summary: Obsessive CSS Code Formatting • Evil Incarnate, but Easily Blocked »
1 • Joshua Richardson
September 14, 2008 at 3:51 pm
If you re-write the expression to take into account IE6’s box model then you can still use min-width s with IE6.
I.e. using a javascript function:
function IE6MinWidth( size, border, padding, margin ){if (document.documentElement.clientWidth > (size+border+padding+margin+1)){return "auto";}else{return size+"px";}}Then change your expression to something like:
width: expression(IE6MinWidth(400,3,5,10));Example page up at http://webcoders.com.au/minWidth.html