Box Model Hack

From CSS Discuss

Jump to: navigation, search

A Css Hack .

Contents

Why does the CSS box model need a hack?

According to the W3C, an assigned 'width' (and 'height') of a box refers to the 'content area' of a box only. The padding, borders, and margins are then added to this value to arrive at the total box width. If the 'width' property is omitted, the total box width is the same as the 'content area' of the surrounding container element. All well and good. Unfortunately, all CSS enabled versions of IE before IE6/strict use a different box model. In that model, the padding and borders are counted as part of any assigned 'width' or 'height'. In the absence of borders and padding, the two models agree. However, if a box has an assigned "width', and if borders and/or padding are added, the standard box model causes the overall box width (between the outer border edges) to increase, while in IE's model the 'content area' gets squeezed by the same amount. This is a major problem for proper page layout. Consider the following CSS:

   {width:100px; padding:10px; border:10px;}

When viewed in a 'standards' browser the dimension from border edge to border edge will be '140px'. (100+10+10+10+10=140) Because IE5.x puts all these values inside the 'width', the border edge to border edge dimension will be '100px'.

Note: For technical reasons it sometimes would be desirable to employ the old IE box model. It has been bruited about that CSS-3 will feature a way to choose between the two models, but the current standard model will no doubt remain the default.


Enter the 'box model hack'. It seeks to supply IE5.x/win, and only that browser, with a fudged 'width' value (140px, in this case) so it will make a box of the same dimensions as a 'standards' browser.

The Hacks

Box-in-a-box

The name says it all. Just remove the padding/borders from the problem box, nest a second box inside the first, and put the padding/borders and the content within that nested box. End of problem. The only issue is that this is done within the HTML markup, rather than the CSS. Many people consider this to be bad practice, because years down the road, when a hack is finally cleaned from your code, a CSS hack is quickly removed, while markup hacks are scattered hither and yon. Plus it complicates the HTML, structurally speaking.


It looks like this if you are using two divs:

div { width: 100px; }
div .i { padding: 1em; }

<div>
 <div class="i">
  Text
 </div>
</div>

If used while you have two nestled elements anyway, then the only negative effect of this solution (a single extra div in the HTML) is a non-issue. The major benefit of this method is that it works just about everywhere.

NOTE: This hack has an additional bug. In IE a table placed inside the internal div with a 100% width will stretch the external div to the width of the external div plus the padding of the internal div.

Here is the code that shows the IE bug.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>

    <head>

        <title></title>

        <style type="text/css" media="all">
            div.FixedWidthBar {
                border: 1px solid #000000;
                width: 100px;
                background-color: #FF0000;
                color: #FFFFFF;
            }
            div.MarginContentArea {
                border: 1px solid #000000;
                width: 100px;
            }
            div.ContentArea {
                border: 1px solid #0000FF;
                padding: 10px;
            }
        </style>

    </head>

    <body>

        <div class="FixedWidthBar">100px</div>
        <div class="MarginContentArea">
            <div class="ContentArea">
                <table width="100%">
                    <tr>
                        <td>test</td>
                    </tr>
                </table>
            </div>
        </div>
    </body>

</html>

The Tantek Hack

Tantek Çelik's ingenious workaround for dealing with IE5's faulty interpretation of the box model. Relies on an Internet Explorer CSS parsing bug.

See http://www.tantek.com/CSS/Examples/boxmodelhack.html

The Simplified Box model Hack (SBMH)

This hack was first detailed in a superb post by Andrew Clover of the Css Discuss List . It also uses an escape character parsing bug, like the Tantek Hack, but is used directly on a property rather than between the property declarations.


The basic structure is this:

div {
width: 100px;
}
div {
\width: 140px; 
w\idth: 100px;
}

The top rule (line 1) is used by browsers like Op5 that get the box model correct, but choke on the escapes in the following rule. Op5 ignores those rules entirely.

The first 'escaped' property (line 5) will be used by IE5.x, and feeds that browser its 'fudged' value. The second escaped property (line 6) cannot be read by IE5.x, but is read and used by modern 'escape friendly' browsers like N6, Moz, Op6, and IE6.

Note: If Nav4 sees even one escape anywhere in the CSS, it will discard the entire sheet. So it is vital that this hack be hidden from that browser, by means of @import, or the Caio Hack . For a detailed explanation of the escape parsing bug see that Andrew Clover post.


Proper use of the escapes: The escape '\' that starts line 5 must always be directly against the first letter of the property name. IE5.x/win does not like escapes, but seems to ignore them when they are in this position.

Important! An escape must not precede any of the first six alphabetical characters: a, b, c, d, e, f, per the CSS spec on forward-compatible parsing. If this is done it will be seen as a 'hex code' and Bad Things Will Happen. This means that a property that begins with one of these letters cannot be hacked in this manner. For example, "height" can be hacked, but "font-family" can't be, since it starts with a character that is interpreted as the beginning of a hex code. Fortunately, neither "width" nor "height", the most important properties for this hack, are affected.

For line 6 (modern browsers) the escape must be within the property name, and the previous 'hex' rule applies.

A Modified SBMH (Tan hack)

Using the above example the basic syntax of the modified SBMH is as follows

div
{
  border: 10px;
  padding: 10px solid;
  width: 100px;
}

* html div
{
  width: 140px;
  w\idth: 100px;
}

The first rule contains all the necessary CSS for the box including borders, paddings, and width value for browsers that properly implement the CSS box model.

The second rule uses the Star Html Hack. Since html is the root element the selector " * html " shouldn't match any element in a valid html/xhtml document. But IE (for Windows and the Mac) seem to ignore the universal selector (asterisk) when it precedes "html". Same goes for the selector "* * body". Because of this peculiarity we can effectively hide an entire rule from all browsers except IE.

Line 10 is read by all IE versions. Line 11, however, as explained above in the section on the SBMH is hidden from IE5.x/Win because of the character escape. IE5/Mac and IE6/Win which implement the CSS box model correctly, therefore, properly get a width of 100px.

Because the star html selector does not match any actual element, browsers that are phobic to escapes such as NS4.x and Opera 5, will not even bother looking at the declaration block, and therefore are effectively shielded from escapes.


This is a very brief intro to the technique. A more comprehensive discussion is available at the Modified SBMH page. You may also want to how your browser reacts to the hack. Included in that page is a table summarizing the results of browser testing. As you can see testing on Mac browsers is urgently needed.

3 Alternate Box Model Hacks

The following techniques rely on the fact that all IE/Win (and, unfortunately, IE/Mac too) have various forms of comment bugs, i.e., depending on where the comment is placed one version or another of IE will ignore the declaration where the comment is found.

Here are the specific comment bugs that are put to good use in the hacks:

  • When a property is immediately followed by an empty comment (no whitespace inside), that declaration is hidden from IE5.0/Win and IE5/Mac.
  • When a property is immediately followed by a comment that contains at least one whitespace, that declaration is hidden from IE5.0/Win and IE5/Mac. In addition the next declaration is also hidden from IE5.0/Win.
  • When a comment immediately precedes a value that declaration is hidden from IE5.5/Win.
  • When a property is followed by at least one whitespace and which is then followed by a comment (comment must be before the colon) that declaration is hidden from IE6/Win.

As in the all the hacks above the three techniques below intend to serve IE5.x/Win the total width of the box, and supply the content width to other browsers.

Technique 1

Syntax:

div
{
  border: 10px solid;
  padding: 10px;
  width: 140px; 
  width/* */:/**/100px; 
  width: /**/100px;
}

Line 5 is read by all browsers. Line 6 is hidden from IE5.x/Win. But because there is whitespace inside the comment adjacent to width IE5.0/Win will also ignore the declaration that immediately follows. Therefore, line 7 is hidden from it as well. Line 7 is also hidden from IE5.5/Win because of the comment adjacent to the value. Lines 6 and 7 are not hidden from IE6/Win.

Technique 2

Syntax:

div
{
  border: 10px solid;
  padding: 10px;
  width: 100px !important;
  width: 140px;
  width/**/:/**/100px;
}

Line 5 is read by all browsers. But IE/Win does not implement !important so this width value will not override the other two. Line 7 is hidden from IE5.x/Win. Therefore, IE5.x/Win will apply the width value in line 6. IE6/Win meanwhile will read all the width values but apply only the last one (line 7)

Technique 3

Syntax:

div
{
  border: 10px solid;
  padding: 10px;
  width: 100px !important;
  width /**/:140px;
}

Line 5 is read by all browsers. But IE/Win does not implement !important so this value is not given any importance by that browser. Line 6 is hidden only from IE6/Win. Therefore, IE5.x/Win and any other browser that does not properly implement !important will get a width of 140px.

Important Note: The order of the various width declarations is crucial. They must appear as shown in each of the three techniques above, else the hacks will fail. However, other declarations (e.g. background-color, font-size, position, etc.) may appear before and after them.

As you may have already noticed these three techniques obviate the need for two rule sets, thus simplifying the style sheet.


This is a very brief intro to the techniques. A more comprehensive discussion is available at the Alternate Box Model Hacks page. You may also want to test how your browser reacts to the hacks. Included in that page is a table summarizing the results of browser testing.

What is the conclusion?

And what do we get when we summarise all this? I'm not quite sure... Anyone?

The Tantek Hack
This seems to be the one generally working, but it's awkward to enter. And it also affects IE4 and NS4 which doesn't need it.
SBMH
This works, but breaks fatally on NS4 effectively disabling the entire stylesheet. It also affects Op5 and Konqueror
SBMH (Tan hack)
This does also work, and does not break NS4. Drawback is you have to specify the width-property three times to make it work, and two of them within a separate rule. (For the novice-to-intermediate webmaster however, the Tan hack is decidedly complication-free, and it may even be extra nice to keep things clear and separate. If your page is not complex the added code bulk may be insubstantial.)
Alternate BMH, 1-3
Is this the ultimate solution? It does break the Konqueror on Linux, and What's the difference between these, and where do they not work? It seems like Technique 3 is a nice solution, but is it the ultimate solution? On NS4.8 all the boxes gets broken into small boxes around each word.
MS Proprietary Conditional Tags
may be at least as good and as simple as anything on this page. Worth considering for experts as well as novices. (Only does not work on "stand alone" IE5 browsers, which are rarely used except for view-checking by other web designers.) http://htmlfixit.com/contribs/MS_conditional_tags.html

Update 16 Dec 2005: Manfred Staudinger has posted a brilliant article on Taming Your IE Standalones over at Position Is Everything that repairs the comments problem.

So the question remains: Which hack to use against the buggy box model of IE5/Win? Which hack has the least amount of side effects?

Another Solution by Tantek

Another way to get around IE5's buggy box model is the Mid Pass Filter (http://www.tantek.com/CSS/Examples/midpass.html). This seems like the best solution, because it doesn't break in any browsers. On the plus side it also separates hacks from normal code.

div {
border: 10px solid;
padding: 10px solid;
}

@media tty {
 i{content:"\";/*" "*/}} @import 'midpassbefore.css'; /*";}
}/* */

div {
width: 100px;
}

@media tty {
 i{content:"\";/*" "*/}} @import 'midpassafter.css'; /*";}
}/* */

Then midpassafter.css contains

div {
width: 140px;
}

Cycloid's Tiny Box Model Hack

This uses a quirk in the way that Windows IE 5,5.5 and 6 (in quirks mode) read the css file (happily IE5.2 on the mac is unaffected and uses the correct box model). They will accept key/value pairs where the value is enclosed in quotes:

div
{
   padding: 10px;
   width:   180px;
   width:   "200px";
}  

This breaks the W3C's rules for CSS, unfortunately, so if producing W3C validated code is more important to you than simplicity then use one of the above comment bug hacks. As the last width rule is seen by non IE browsers as being malformed it is skipped and the first width declaration is used instead.

You can use proprietary code or box in box solutions too

There are some other ways around this "bug" highlighted here: Alternatives for Box Model Hacks Hacking the Box Model Hack using PHPSS

Personal tools