The techniques presented here are alternatives to the Tantek �elik Hack, Simplified Box Model Hack, and modified SBMH. As with these three the following alternates are meant to provide IE5.x/Win a width
(and/or height
) value of its own to compensate for its erroneous implementation of the CSS Box Model.
The workarounds exploit the various forms of comment bugs found in IE (both for Windows and the Mac) to hide declarations from one or another version of IE. Techniques 2 and 3 in addition employ the !important
declaration.
In the syntax sections below the term "whitespace" is mentioned a number of times. Whitespace is used here in the same sense as in the CSS Specifications. A whitespace may be a blank space, a tab, or a carriage return.
All techniques presented here are valid CSS.
You may wish to test your browser's response to the hacks. You may also want to see a comparison of how all box model hacks fare in your browser.
Technique 1
Syntax
<selector> { /* specify borders and paddings if any */ width: <content width + paddings + borders>; width/* */:/**/<content width>; width: /**/<content width>; /* other declarations may appear anywhere in this rule */ }
The three width declarations above must be specified in the order shown or some browsers will not receive the proper value.
Declaration | Critical | Non Significant |
---|---|---|
width/* */:/**/<value>; |
|
|
width: /**/<value>; |
|
|
How It Works
The first width declaration is for IE5.x/Win. This is the only declaration among the three that it will recognize. The value specified herein must be the sum of left and right paddings, left and right borders, and content width.
The second width declaration is hidden from IE5.x/Mac and IE5.x/Win. It is recognized by browsers (including IE6) which do not have these particular comment bugs. The value specified herein should be the content width of the block.
It is important to understand that IE5.0/Win ignores a declaration such as width/* */: <value>
, as well as the declaration immediately following it. IE5.x/Mac on the other hand ignores only the declaration where the comment is found. Because of this peculiar behavior both the second and third width
declarations above are hidden from IE5.0/Win. This behavior is imperative since the hack hinges on it.
The third width declaration is hidden from IE5.5/Win but because of the comment hack in the second declaration it is also hidden from IE5.0/Win. It is, however, recognized by IE5.x/Mac and other browsers that do not have this particular form of comment bug. The value specified herein should be the content width of the block.
Example
The two blocks below should both be 500px wide. IE5.x/Win, however, will display the first one with a total width of only 400px. The second block contains the hack which should supply IE5.x/Win its own width value while supplying other browsers another value.
Without the hack:
With the hack:
Test your browser's reactions to the hack.
Technique 2
Syntax
<selector> { /* specify borders and paddings if any */ width: <content width> !important; width: <content width + paddings + borders>; width/**/:/**/<content width>; /* other declarations may appear anywhere in this rule */ }
The three width declarations above must be specified in the order shown or some browsers will not receive the proper value.
Declaration | Critical | Non Significant |
---|---|---|
width/**/:/**/<value>; |
|
|
How It Works
The first width declaration is for browsers that understand the !important rule and get the CSS box model correctly. This declaration is necessary because the third width declaration is hidden from IE5.x/Mac.
Declarations with !important
are recognized but not given any importance by all IE/Win so when the property is redeclared (in the same rule) IE/win will apply that value instead (which is not the case with browsers that properly implement !important
).
The second width declaration is understood by all browsers but is intended for IE5.x/win only because in other browsers the other width declarations should override this value.
IE5.0/win and IE5.x/mac ignore a declaration when a comment comes right after the property. IE5.5/win meanwhile ignores a declaration when a comment comes right before or right after the value. The third width declaration will, therefore, be ignored by IE5.x/Win and IE5.x/Mac. IE6/Win has no problem recognizing it and since it does not implement !important
it will pick up this width value. See the discussion on comment bugs for further details.
How Browsers Will React to the Hack
- Browsers that implement the CSS box model correctly and ...
- do not have either the property+comment bug or the comment+value bug and ...
- properly implement
!important
(e.g. Mozilla, Opera 5 & 6)Will apply width that has an
!important
rule and disregard all other width declarations within the rule. - do not implement
!important
(e.g. IE6/win)Will read all the width declarations but apply only the last one.
- properly implement
- have either the property+comment bug or the comment+value bug and ...
- properly implement
!important
(e.g. IE5.x/mac)Will apply width that has an
!important
rule. The declaration that has the comments will be hidden from them. - do not implement
!important
(e.g. ???)Will get the width value meant only for IE5.x/Win.
- properly implement
- do not have either the property+comment bug or the comment+value bug and ...
- Browsers that erroneously implement the CSS box model: IE5.x/win
Will read the width that has an
!important
rule. Will then read the second width declaration and apply the value since it does not implement!imporant
. Will ignore the last width declaration because of the comment hack.
Example
The two blocks below should both be 500px wide. IE5.x/Win, however, will display the first one with a total width of only 400px. The second block contains the hack which should supply IE5.x/Win its own width value while supplying other browsers another value.
Without the hack:
With the hack:
Test your browser's reactions to the hack.
Technique 3
Syntax
<selector> { /* specify borders and paddings if any */ width: <content width> !important; width /**/:<content width + paddings + borders>; /* other declarations may appear anywhere in this rule */ }
The two width declarations above must be specified in the order shown or some browsers will not receive the proper value.
Declaration | Critical | Non Significant |
---|---|---|
width /**/: <value>; |
|
|
How It Works
The first width declaration is for browsers that understand the !important
and get the CSS box model correctly.
Declarations with !important
are recognized but not given any importance by all IE/Win so when the property is redeclared (in the same rule) IE/win will apply that value instead. Because of this IE5.x/Win will apply the value in the second width declaration.
The last width declaration has a property followed by whitespace followed by a comment. This effectively hides the declaration from IE6 but not from other IE versions (both Windows and for the Mac). It is necessary to hide this width value from IE6 because it does not implement !important
but gets the CSS box model correctly. See the discussion on comment bugs for further details.
How Browsers Will React to the Hack
- Browsers that implement the CSS box model correctly and ...
- do not have the property+whitespace+comment bug and ...
- properly implement
!important
(e.g. Mozilla, Opera 5 & 6)Will apply width that has an
!important
declaration, disregarding all other width declarations within the rule. - do not implement
!important
(e.g. ???)Will get the width value meant for IE5.x/Win.
- properly implement
- have the property+whitespace+comment comment bug and ...
- properly implement
!important
(e.g. ???)Will apply width that has an
!important
declaration. The width declaration with the comment hack will be hidden from them. - do not implement
!important
(e.g. IE6)Will apply width that has an
!important
declaration. The width declaration with the comment hack will be hidden from them.
- properly implement
- do not have the property+whitespace+comment bug and ...
- Browsers that erroneously implement the CSS box model: IE5.x/win
Will read the width that has an
!important
declaration. Will then read the second width declaration and apply that value since it does not implement!imporant
. The property+whitespace+comment bug is not found in IE5.x/Win.
Example
The two blocks below should both be 500px wide. IE5.x/Win, however, will display the first one with a total width of only 400px. The second block contains the hack which should supply IE5.x/Win its own width value while supplying other browsers another value.
Without the hack:
With the hack:
Test your browser's reactions to the hack.
Comparison of the Various Box Model Hacks
All box model hacks have their drawbacks.
The Tantek Hack is, to understate it, homely and is not easily comprehensible. A more important point, however, is that it requires a "be nice to Opera 5" child selector rule to serve that browser the correct width
value because just like IE5.x/Win it is fooled by character escapes. In addition, character escapes will cause NS4.x to ignore the entire style sheet (yes, NS4.x will disregard all the CSS rules).
As with the Tantek Hack the character escape technique of the SBMH does not sit well with Opera 5 and NS4.x. Opera 5 dumps the entire rule where the escape is found, while NS4.x ignores the entire stylesheet. This means that at least two (maybe even three), nearly identical, rules with the same selector must be specified: one with an unescaped width
and another with a character escaped width
. Although using escapes is a simple and elegant solution, the necessity of specifying several rules defeats its initial simplicity.
The alternate box model hacks obviate the need for "be nice to Opera 5" rules since there are no character escapes to worry about. Hence, only one rule set is necessary. However, these alternates too have liabilities. The reliance of techniques 2 and 3 on !important
puts an additional burden on the web author. One characteristic of !important
is that when a simple type selector (specificity = 1) has an !important
declaration in one of its properties all elements matched by that selector will take on that value, regardless of the specificity of the succeeding selectors. For example, given:
div {width: 400px !important;} div#someblock {width 600px;}
div#someblock
which has a specificity of 101 will have a width
of 400px and not 600px. In fact all div
's will have a width of 400px. The only way for div#someblock
to receive the value of 600px value is to declare it as !important
in order to override its default width
of 400px.
Therefore, techniques 2 and 3 are best employed when the selector has a moderate to high specificity. This will avoid any possible clashes between various block elements, and also help preclude the use of !important
to override previously set widths
that have been declared as !important
.
All 3 alternates, moreover, are very meticulous about where whitespace should and should not be found. As evidenced by the tables of syntax details, it is critical to have and not have whitespace in the correct places. Failure to implement the exact syntax will lead to not so pretty results on screen.
Finally, in fairness to the Tantek Hack, those comment riddled declarations are creatures only their mother (or should I say father) could love and understand.