additions…
…web design…
min/max – making IE/win work, with IE-expressions…
IE-expressions are basic javascript turned into Microsoft-proprietary, CSS-like, arguments and/or calculations. Such IE-expressions may be used as last resorts when Internet Explorer 6 simply can't do what other browsers can, when served W3C-standardized CSS.
We can make IE6 simulate min/max-width based on 'px' or 'em', or both.
Some may prefer to add regular javascript solutions as means to work around Internet Explorer's shortcomings. Some don't like proprietary solutions in otherwise W3C-standardized CSS, while others think of IE-expressions as behavior which belong in the behavior layer = javascript.
I use IE-expressions to simulate proper CSS handling in a browser that otherwise can't handle much, thus I have no problems with having such simulations in my stylesheets. Javascript is fine too, but I see the addition of extra files as “overkill” in most cases.
The results are basically the same – apart from that most IE-expressions needed as workarounds seems to make Internet Explorer act a bit faster than their “pure javascript counterparts”. The reason (although I can't point to facts that confirms this) may be that an expression is applied “in synk” with the CSS rendering, while regular javascript is applied before, or after, and separated from all CSS-based rendering.
Quirks & Strict mode = “dual mode”…
IE-expressions should work regardless of what mode our DocType Declaration, or lack of same, makes IE6 run in. However, since IE6 handles slightly different javascript-versions, or rather different elements/element-names, depending on mode, I've added the argument needed to switch between versions. That will make the IE-expressions work flawless.
The more compact IE-expressions also found below, are also found to work flawless – without actually switching mode. They are not tested as thoroughly as the full-sized (complex) ones though.
However – and this is important: differences between Quirks mode and Strict mode box models can't be handled by these IE-expressions. All such differences must be dealt with as part of the regular, or hacked, CSS. Alternatively: separate IE-expressions must be used for IE5.0, 5.5 vs. IE6, with different values that'll suit the layout and mode-induced differences in these IE-versions.
min-width and max-width in one…
In order to make the 'min/max-width' simulation act on one single element – without the need for extra elements in the source-code, I have added in the 'min-width' part as an alternative in the 'max-width' one.
Such a combined IE-expression may look like a “mouthfull” of “if-then-else” nesting, but it isn't really complicating things, and the result is perfectly stable.
What we get is an ordinary 3-state expression with "min-width state", "fluid state" and "max-width state", with added "mode selection". Two complete variants are exemplified and described below, with a few compact versions added for good measure.
pixel-based min/max-width expression…
A working min/max seems to be the most needed workaround for IE6 (and older versions).
CSS for standard compliant browsers: #wrapper {width: 99%; max-width: 1200px; min-width: 550px;} CSS for MSIE/win: * html div#wrapper {width: 760px /* fallback value */; width:expression(((document.compatMode && document.compatMode=='CSS1Compat') ? document.documentElement.clientWidth : document.body.clientWidth) > 1218 ? "1200px" : (((document.compatMode && document.compatMode=='CSS1Compat') ? document.documentElement.clientWidth : document.body.clientWidth) < 570 ? "552px" : "99.7%")); }
Demo: this very page - and the entire site-section.
This is the simple “works every time” type of solution, that only needs correct values for each layout in order to work almost as smooth as the real thing in most Internet Explorer set-ups.
Read the above as follows: “if window-width is larger than 1218(px), then fix 'width' to "1200px", else check if window-width is smaller than 570(px), and if so fix 'width' to "552px", else make 'width' "99.7%"”.
Also, because of the "fallback" before the expression: “if javascript isn't awailable or active, then fix 'width' to 760px”
The values above are chosen to suit this very page/layout. They can of course be changed to suit any page/layout. I won't go further into the details here, as it should be easy for everyone to plug in their own values, test them, and adjust until smooth transition has been achieved.
compact px-based min/max-width expression:
* html body #wrapper {width:expression( (document.documentElement.offsetWidth) >1230 * (parseInt(document.body.currentStyle.fontSize) / parseInt(document.body.currentStyle.fontSize))? "1200px" : ((document.documentElement.offsetWidth) < 580? "552px" : "99%")); }
Demo: Conditional Liquid layout.
Here I make use of 'offsetWidth' which provides fairly mode-independent values. I check font-size as a mean to avoid freezing in quirks mode, but this solution doesn't rely on actual font-size in IE, so it will work fine even if one is declared on body. Update [ 25.sep.2007 ] : The use of font-size keywords on body will prevent this compact version from working though, since 'offsetWidth' can't extract an actual number from keywords.
px/em-based min/max-width expression…
Scaling layouts seems to become popular, so a working min/max workaround for IE6 (and older versions) under those conditions, might be just what the client ordered.
CSS for standard compliant browsers: #wrapper {width: 99%; max-width: 60em; min-width: 552px;} CSS for MSIE/win: * html body #wrapper {width: 60em /* fallback value */; width:expression(((document.compatMode && document.compatMode=='CSS1Compat') ? document.documentElement.clientWidth : document.body.clientWidth)>(970/12) * parseInt(document.body.currentStyle.fontSize)? "60em" : (((document.compatMode && document.compatMode=='CSS1Compat') ? document.documentElement.clientWidth : document.body.clientWidth) < 558 ? "552px" : "99%")); }
Demo: Conditional Elastic layout.
This IE-expression extracts the User-preference/default for font-size from the browser, Internet Explorer, itself, and use it as base for 'max-width' calculations. Thus messing with those preferences/defaults is bound to lead to failure. There's really no room for error. Read more about this further down.
compact px/em-based min/max-width expression:
* html body #wrapper {width:expression( (document.documentElement.offsetWidth) >(1020/12) * parseInt(document.body.currentStyle.fontSize)? "60em" : ((document.documentElement.offsetWidth) < 600? "554px" : "96%")); }
Demo: Conditional Elastic layout.
Here I again make use of 'offsetWidth', which provides fairly mode-independent values. User-preference is extracted from the browser, so no font-size must be declared on html or body.
compact em/em-based min/max-width expression:
* html #wrapper {width:expression( (document.documentElement.offsetWidth) >(1020/12) * parseInt(document.body.currentStyle.fontSize)? "60em" : ((document.documentElement.offsetWidth) <(600/12) * parseInt(document.body.currentStyle.fontSize)? "35em" : "96%")); }
Demo: Conditional Elastic layout.
Here I once again make use of 'offsetWidth'. User-preference is extracted from the browser, so no font-size must be declared on html or body.
how does 'max-width' in 'em' work:
It is easy to lose track of calculations and units, so I'll try to walk slowly through the central parts of the IE-expression that are responsible for the 'max-width in em' simulation.
The '#wrapper' element is the element we apply 'min/max width' to. The IE-expression acts on that very same element, and will lock, or "fix", width on #wrapper if the browser's window-width is above or below certain "trigger-point" values.
Now, IE6 can only reveal its own window-width in pixels (px), so we have to add in a 'font-size dependent' calculation that'll result in a pixel-value. IE6's default font-size is in points (pt), so in order to give IE the correct "trigger-point" we'll have to divide 'the actual width in px' by 'the "normal" (or "medium") font-size default in pt', and multiply that by 'the actual font-size default in pt'.
the 'max-width' calculation...
[...].clientWidth)>(970/12) * parseInt(document.body.currentStyle.fontSize)? "60em"[...]
Read the above as “if browser-window is wider than ((970/12) × 'browsers own font-size'), then the exact width of #wrapper should be 60em”. This will be true whatever the browsers own font-size happens to be.
It should be obvious that at "normal" (or "medium") font-size default (12pt) the result will be a "trigger-point" at exactly 970px window-width. One step up – "larger" (14pt), will "trigger" at 1131px, and one more step up – "largest" (16pt), will "trigger" at 1293px window-width. The two steps below "normal" (or "medium") – "smaller" (10pt) and "smallest" (9pt), will "trigger" at 808px and 727px, respectively.
If our given start-value is correct– here 970, then IE6 will at most be +/-1px off from the real 'max-width' "trigger-points" in other browsers, and I think that's close enough for comfort.
Important about declaring font-size:
When working with these em based min/max-expressions, there must not be any font-size declared on, or inherited onto, the 'body' element.
This part of the IE-expression above...
parseInt(document.body.currentStyle.fontSize)
...will parse whatever font-size the author declare on html and/or body, instead of the browser's own default value (somewhere between 9 and 16pt) that's needed for the IE-expression to work.
It should be pretty obvious that any declared font-size on html and/or body will not only return the wrong value to the IE-expression, it will also return a "fixed" value that is unaffected by whatever font-size option the User chooses.
So this...
body {font-size: 62.5%;}
...will give a value of '62.5' ≈ 62pt to the IE-expression, and this...
html {font-size: 100%;} body {font-size: .76em;}
...will be parsed as '.76' ≈ 0pt.
In short: any autor-declared font-size on body, means complete failure in IE6.
More about declaring font-size:
We also have to be extremely careful with what font-size value to declare on, or inherit onto, #wrapper itself. In fact; the only safe value/unit is...
#wrapper {font-size: 100%;}
...in order to keep the basic 'pixel/point×point' calculation line up with the 'em' value we want IE6 to land on once it reaches the "trigger-point". We can then declare font-sizes of any values in '%' or 'em' further in, without disturbing the calculation.
Of course, one may use a not 100% font-size value on #wrapper, and compensate for that with new values in the IE-expression. It may work just fine, but has at best made the calculation “interesting” for no good reason at all. Might be a nice exersize for bored web designers – but nothing else.
how to calibrate 'max-width' in 'em':
We need a "trigger-point" and a "max-width" for the element. These two values must be calculated and/or found through trial and error.
First, we choose an em-value for that "max-width". That's normally the same value as we give to browsers that understand the proper 'min/max-width' properties, so here I've set it to "60em".
[...].clientWidth)>(970/12) * parseInt(document.body.currentStyle.fontSize)? "60em"[...]
Next we adjust the window-width in IE6, and try to figure out how many pixels "60em" + margins and paddings on #wrapper and body and whatever elements we may have added outside #wrapper adds up to. You can see that I have used the value of '970' – which is the exact "trigger-point" in 'px' at "normal" (or "medium") font-size.
This "trigger-point" value can be calculated, but taking IE6's own buggy calculations into account, I usually prefer to find the exact value by trial and error and make sure there's a smooth transition between "fluid state" and "max-width".
We also have to take into account what percentage-value we choose for the "fluid state" between min-width and max-width, as it doesn't always pay off to make that "100%" given IE/win's pretty erratic calculations.
Looking at the very end of the complete IE-expression above, you can see that I have chosen "99%" as "fluid state" value, and I have to mix the missing 1% into my "trigger-point". The reason for this is of course that the browser window is always "100%" wide – regardless of the actual window-width. Margins and paddings on body and/or other elements outside #wrapper, and maybe even on #wrapper itself, makes it a bit less clear what those "99%" are calculated from.
Ideally: #wrapper should be the outermost element, first element inside body, but that isn't and
doesn't always have to be the case for the 'min/max-width' simulating IE-expression to work just
fine. Having extra elements outside of #wrapper just complicates things a bit for the designer.
See more min/max-width in IE6 for an expansion on that.
conclusion – so far…
After some extensive testing, I have to conclude that these IE-expressions are working just fine – as long as the designer knows what he/she is doing.
There's only one reason to do anything for IE6, and that is to prevent that old bugger from holding
us back even longer.
We usually have to make whatever we create work in all major browsers, in order to satisfy clients and visitors
– and we can't avoid IE6 for the time being.
I do use IE-expressons to fix IE7 too – when necessary, as its CSS support is not up to much when compared to other major browsers.
I'll expand on how to use the IE-expressions above, and how they work, as soon as I have sorted out what's most problematic for the average web designer. That way I hope to avoid releasing another set of perfect but useless solutions that only a few can get their heads around and make proper use of.
I have added an article describing more min/max-width in IE6, in case the solutions above aren't cutting it in your case. A solution to prevent too small text in IE/win, is also included.
I'll be back with more updates if I see the need.
sincerely
Hageland 10.jul.2006
last rev: 15.feb.2009
additions…