…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 : 
> 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 : 
* 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...
* parseInt(document.body.currentStyle.fontSize)?

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


...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%;} 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".

* parseInt(document.body.currentStyle.fontSize)?

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  georg; sign

Hageland 10.jul.2006
last rev: 15.feb.2009


it's always nice to be able to express oneself – even through Microsoft's software — Georg

addition to:

internal references…

external references…
feedback welcome.

Problems can best be found and solved in live implementations, and there's no way I can build the huge number of test cases necessary to find and eliminate every potential weakness for any of my solutions.

I am to some degree depending on feedback in order to improve solutions and/or what I have written about them.

Any improvement will eventually be reflected in the relevant articles.
— Georg
[gunlaugs at c2i dot net]

IE-expressions can make heavy demand on resources…

The reason IE-expressions are so fast, is that they are engaged to keep track of everything more or less continuously – same as the CSS we're replicating. Whatever the user do that may, or may not, affect the page, all parameters included in every single IE-expressions have to be checked and recalculated, and the action decided and implemented – even if no re-rendering takes place.

Of course, this constant updating isn't unconditionally true, but we are dealing with dynamically handled script-code here.

IE-expressions make heavy use of resources on the end-user's computer, and if that computer is low on resources to begin with, then extensive use of IE-expressions will certainly show.

I have performed practical testing of this effect on a fairly fast dual-processor computer with loads of memory, by having more than 3 dozen IE6 windows engaged simultaneously over a long period with various pages on my own site. Any re-rendering of my pages slowed down noticeably under such heavy load.

Disengaging all IE-expressions brought IE6 back to more normal speed – as expected. The speed-difference wasn't alarmingly large in practical terms though.

A similar test on a really old and slow computer running windows 98 and multi-windows of IE5.0, did of course result in real slowdown. Nothing compared to the delays caused by some of the regular Javascript alternatives at hand, but I didn't check the quality of those alternatives apart from that none of them could out-phase my IE-expressions.

I don't see the heavy demand on resources as a reason for not using IE-expressions to fix IE/win's lack of CSS support when necessary, but I'll put emphasis on the term when necessary. It is certainly not a good idea to overload that old bugger with continuously engaged IE-expressions or Javascript, just to get every last detail “perfectly right” all the time.

Regular Javascript can probably replace IE-expressions in most cases, but if one wants the same seamless CSS-like effects, then the use of computer-resources will be just as high or even higher. It is after all the same engine we're using, and a badly written script can use a lot of processingcycles and memory.

It is however much easier to optimize Javascript for reasonable rendering-compromises with less use of resources, if this becomes an issue. Only thorough testing can tell you what the best solution will be for each case.
— Georg

…2006 - 2009
last update: 15.feb.2009