Understand css Positioning element

Positioning is tough to understand when you’re first starting out with CSS. Your choices are

  1. Static
  2. Relative,
  3. Absolute,
  4. Fixed.

Static is the default option and is positioned according to the normal page flow.

Relative item is positioned relative to itself, meaning you can move it up, down, left or right, based on where it would normally sit.

Absolute allows you to place an item anywhere on the page, and is the most misused positioning statement. The values you set for it will be relative to the last parent item with relative or absolute, and if there aren’t any, it defaults back to the html tag, allowing you to position it anywhere by declaring top left right or bottom values.

Fixed is positioned relative to the browser window, so an item will stay in place if a user has to scroll. Learning how to use positioning correctly is important, but shouldn’t be used excessively. I rarely use these at all in my stylesheets.

Some usefull css tips, tricks

CSS font shorthand rule

When styling fonts with CSS you may be doing this:

font-size: 1em;
line-height: 1.5em;
font-weight: bold;
font-style: italic;
font-variant: small-caps;
font-family: verdana,serif;

There’s no need though as you can use this CSS shorthand property:

font: 1em/1.5em bold italic small-caps verdana,serif

Much better! Just a couple of words of warning: This CSS shorthand version will only work if you’re specifying both the font-size and the font-family. Also, if you don’t specify the font-weight, font-style, or font-varient then these values will automatically default to a value of normal, so do bear this in mind too.

2. Two classes together

Usually attributes are assigned just one class, but this doesn’t mean that that’s all you’re allowed. In reality, you can assign as many classes as you like! For example:

<p class="text side">...</p>

Using these two classes together (separated by a space, not with a comma) means that the paragraph calls up the rules assigned to both text and side. If any rules overlap between the two classes then the class which is below the other in the CSS document will take precedence.

3. CSS border default value

When writing a border rule you’ll usually specify the colour, width and style (in any order). For example, border: 3px solid #000 will give you a black solid border, 3px thick. However the only required value here is the border style.

If you were to write just border: solid then the defaults for that border will be used. But what defaults? Well, the default width for a border is medium (equivalent to about 3 to 4px) and the default colour is that of the text colour within that border. If either of these are what you want for the border then you can leave them out of the CSS rule!

4. !important ignored by IE

Normally in CSS whichever rule is specified last takes precedence. However if you use !important after a command then this CSS command will take precedence regardless of what appears after it. This is true for all browsers except IE. An example of this would be:

margin-top: 3.5em !important; margin-top: 2em

So, the top margin will be set to 3.5em for all browsers except IE, which will have a top margin of 2em. This can sometimes come in useful, especially when using relative margins (such as in this example) as these can display slightly differently between IE and other browsers.

(Many of you may also be aware of the CSS child selector, the contents of which IE ignores.)

5. Image replacement technique

It’s always advisable to use regular HTML markup to display text, as opposed to an image. Doing so allows for a faster download speed and has accessibility benefits. However, if you’ve absolutely got your heart set on using a certain font and your site visitors are unlikely to have that font on their computers, then really you’ve got no choice but to use an image.

Say for example, you wanted the top heading of each page to be ‘Buy widgets’, as you’re a widget seller and you’d like to be found for this phrase in the search engines. You’re pretty set on it being an obscure font so you need to use an image:

<h1><img src="widget-image.gif" alt="Buy widgets" /></h1>

This is OK but there’s strong evidence to suggest that search engines don’t assign as much importance to alt text as they do real text (because so many webmasters use the alt text to cram in keywords). So, an alternative would be:

<h1><span>Buy widgets</span></h1>

Now, this obviously won’t use your obscure font. To fix this problem place these commands in your CSS document:

h1
{
background: url(widget-image.gif) no-repeat;
}
h1 span
{
position: absolute;
left:-2000px;
}

The image, with your fancy font, will now display and the regular text will be safely out of the way, positioned 2000px to the left of the screen thanks to our CSS rule.

6. CSS box model hack alternative

The box model hack is used to fix a rendering problem in pre-IE 6 browsers, where by the border and padding are included in the width of an element, as opposed to added on. For example, when specifying the dimensions of a container you might use the following CSS rule:

#box
{
width: 100px;
border: 5px;
padding: 20px;
}

This CSS rule would be applied to:

<div id=&quot;box&quot;>...</div>

This means that the total width of the box is 150px (100px width + two 5px borders + two 20px paddings) in all browsers except pre-IE 6 versions. In these browsers the total width would be just 100px, with the padding and border widths being incorporated into this width. The box model hack can be used to fix this, but this can get really messy.

A simple alternative is to use this CSS:

#box
{
width: 150px;
}

#box div
{
border: 5px;
padding: 20px;
}

And the new HTML would be:

<div id=&quot;box&quot;><strong><div></strong>...<strong></div></strong></div>

Perfect! Now the box width will always be 150px, regardless of the browser!

7. Centre aligning a block element

Say you wanted to have a fixed width layout website, and the content floated in the middle of the screen. You can use the following CSS command:

#content
{
width: 700px;
margin: 0 auto;
}

You would then enclose <div id=&quot;content&quot;> around every item in the body of the HTML document and it’ll be given an automatic margin on both its left and right, ensuring that it’s always placed in the centre of the screen. Simple… well not quite – we’ve still got the pre-IE 6 versions to worry about, as these browsers won’t centre align the element with this CSS command. You’ll have to change the CSS rules:

body
{
<strong>text-align: center</strong>;
}

#content
{
<strong>text-align: left</strong>;
width: 700px;
margin: 0 auto;

}

This will then centre align the main content, but it’ll also centre align the text! To offset the second, probably undesired, effect we inserted text-align: left into the content div.

8. Vertically aligning with CSS

Vertically aligning with tables was a doddle. To make cell content line up in the middle of a cell you would use vertical-align: middle. This doesn’t really work with a CSS layout. Say you have a navigation menu item whose height is assigned 2em and you insert this vertical align command into the CSS rule. It basically won’t make a difference and the text will be pushed to the top of the box.

Hmmm… not the desired effect. The solution? Specify the line height to be the same as the height of the box itself in the CSS. In this instance, the box is 2em high, so we would insert line-height: 2em into the CSS rule and the text now floats in the middle of the box – perfect!

9. CSS positioning within a container

One of the best things about CSS is that you can position an object absolutely anywhere you want in the document. It’s also possible (and often desirable) to position objects within a container. It’s simple to do too. Simply assign the following CSS rule to the container:

#container
{
position: relative;
}

Now any element within this container will be positioned relative to it. Say you had this HTML structure:

<div id=&quot;container&quot;><div id=&quot;navigation&quot;>...</div></div>

To position the navigation exactly 30px from the left and 5px from the top of the container box, you could use these CSS commands:

#navigation
{
position: absolute;
left: 30px;
top: 5px;

}

Perfect! In this particular example, you could of course also use margin: 5px 0 0 30px, but there are some cases where it’s preferable to use positioning.

10. Background colour running to the screen bottom

One of the disadvantages of CSS is its inability to be controlled vertically, causing one particular problem which a table layout doesn’t suffer from. Say you have a column running down the left side of the page, which contains site navigation. The page has a white background, but you want this left column to have a blue background. Simple, you assign it the appropriate CSS rule:

#navigation
{
background: blue;
width: 150px;
}

Just one problem though: Because the navigation items don’t continue all the way to the bottom of the screen, neither does the background colour. The blue background colour is being cut off half way down the page, ruining your great design. What can you do!?

Unfortunately the only solution to this is to cheat, and assign the body a background image of exactly the same colour and width as the left column. You would use this CSS command:

body
{
background: url(blue-image.gif) 0 0 repeat-y;
}

This image that you place in the background should be exactly 150px wide and the same blue colour as the background of the left column. The disadvantage of using this method is that you can’t express the left column in terms of em, as if the user resizes text and the column expands, it’s background colour won’t.

At the time of writing though, this is the only solution to this particular problem so the left column will have to be expressed in px if you want it to have a different background colour to the rest of the page.

stop using CSS hacks

With the imminent launch of IE7 your usual CSS hacking methods are going to fail. If you want to save web design, as we know it, it’s time to take some drastic action.

CSS has experienced a colourful and unusual history. From historic slow adoption to the current slow rate of development, ugly hacks have meant filling in the gaps is par for the course.

With CSS1, we had a simple and elegant styling language that was supposed to be friendly to even non-programmers. Hence decisions like, say, lack of variables and constants, or conditional logic. (My kingdom for an if statement!)

Then CSS2 came along and provided us with some powerful layout tools. Except some browsers completely disagreed on how to implement them (the box model and floats are two examples that come to mind). Us web designers took care of that problem however, thanks to our lovely CSS hacks and filters. Using perfectly valid CSS, we were able to exploit a browser’s parsing error and specifically serve (or hide) our CSS to it. Problem solved. Lucky us.

But now that Internet Explorer 7 is looming, we’re getting ready to deal with the first really major upgrade to a browser’s rendering engine since we’ve started using CSS-based layouts in earnest. (The launch of Safari didn’t really count, since it was so capable right out of the gate.) The truth is that when IE 7 comes most of our usual hacking methods are going to fail. Afraid yet?

Here’s the nasty little secret of CSS-based development over the past few years: we’ve had a stable target. Because of IE6’s limitations, we’ve been fairly conservative in our usage. There’s really no such thing as cutting-edge CSS, since the CSS2 spec has been final since the late 90’s and CSS3 is off somewhere in the future. Anything we’ve done to date has been able to degrade as gracefully as possible in IE, so we’ve held back on even the more interesting bits of CSS2.

Sure, there are great advanced demos in the form of the CSS Playground, or CSS/edge, or even various CSS Zen Garden designs. But for production-based sites that we create for clients? Conservative CSS use has reigned supreme.

Except … some of us have been a little more than liberal in our hack usage, haven’t we? You might argue that those hacks were necessary to make any sense of the messy browser landscape we were presented with. At the end of a long day of coding, loading that beautiful new site in Internet Explorer has always been a soul-crushing experience. Almost none of us want to spend the time necessary to wrap our minds around just how on earth IE has decided to mangle our code. A few dashes of * html [1] here or _width [2] there and the problem goes away. The short term fix we applied three years ago, however, now threatens to come back and bite us in the rear.

Conditional Comments

IE7 will fix a lot of traditional CSS hacks. The Internet Explorer team has publicly expressed disapproval of the whole idea of hacks, in favour of an IE-proprietary method known as conditional comments. Instead of code like this to filter a rule to Win/IE:

* html #selector {
	width: 100px;
}

We should instead be using an HTML comment syntax to selectively serve up a link to an external CSS file, which will contain a similar rule. The syntax looks like so

<!--[if IE]>
	<link rel="stylesheet" href="ie-specific-file.css" />
<![endif]-->

And then the IE-specific CSS file in question might contain the following rule:

#selector {
	width: 100px;
}

In theory, this system works much better than CSS hacks ever did. Instead of specifically exploiting bugs in a browser, bugs that will obviously one day get fixed, conditional comments are an officially-sanctioned feature of the browser that won’t ever go away. They validate, and even though they’re proprietary, when used with discretion they allow us to accomplish exactly the same thing as CSS hacks.

Sidebar

The question is begged, of course: why are conditional comments implemented only in HTML, and not in CSS? I have it on good word this is something the IE team may look into for future releases. For now, we must place our conditional comments in our HTML files.

Future Updates

But this is simply one single browser updating, and there’s a larger issue here which we’re going to have to start thinking about sooner or later. I’d prefer sooner.

All popular browsers are improving at a frequent clip again. We’re not stagnating anymore; the improvements are going to keep coming. CSS3 isn’t finished yet, but various modules of it are being implemented already. The future is just around the corner.

As the modern browsers update, in what other interesting and creative ways will our code break? How are we going to test them? How are we going to selectively serve up code to various versions?

Take Safari. Version 2.0 was recently released. Apple has no provision for installing and running multiple versions side by side however, much the same as Microsoft has always done with Internet Explorer.

The practical implication here is that I simply can’t test my work in Safari 1.0 any longer. How do we test now, without needing to own a separate computer for each individual version of a browser? Microsoft suggests we buy Virtual PC and multiple Windows licenses to maintain multiple versions of IE (more of my thoughts on that here), an expensive proposition. Apple hasn’t suggested anything.

Causing web developers to buy more software and hardware simply to test seems an unlikely scenario; but somehow, test we must.

Versioning

And the problem will amplify over time, as more incremental updates are released, and the browser share fragments. In one sense this won’t be 1998 all over again with its 85 different versions of Netscape 4, thanks to browser auto-updating keeping most users current. But, not every user will keep up to date. I can’t count how many times I ignore the update nag message on my own machine, so they can hardly be blamed.

What are the odds that all those early adopters of Firefox 1.0 or 1.2 have kept updating, and made it to version 1.5? Likely not as high as we’d hope. Are we going to continue testing in each of them? How will we fix rendering issues that affect 1.0 and 1.2, but not 1.5? No CSS hack I’m aware of can address that discrepency.

Now, let’s be clear. Ever since CSS1, there’s been a very simple versioning control built into the language. If a browser can’t understand a selector or a rule, it simply ignores it. The theory being, as browsers add new support for a particular CSS property or selector, they’ll simply start rendering the rule they previously ignored all along.

Hasn’t worked out so well, has it? One fatal flaw of this method is that it assumes that support for new selectors and properties will be perfect from the start. Need I even get into the problems that have resulted in browser implementation errors? Box model, anyone?

The other, more subtle flaw in this method is that it assumes the fallback is good enough. Simply not rendering a rule due to lack of support, however, causes adverse side effects in styles that depend on that rule. Side effects that can translate into major usability problems for your site’s visitors.

The most obvious example I can give you lies within the CSS3 text-shadow property, which is supported only by Safari at the moment. By using the drop shadow as an outline, we can do things previously impossible, like set white text on a white background.

Text Shadow Demo

To the left, you see the results in Safari; a perfectly legible pairing. To the right, you see almost nothing at all. This is what the text looks like in every other major browser, since they ignore the text-shadow property.

Is just ignoring the unsupported property a good enough fallback? Not in this case, and there are other potential problems in this vein. Point being, this all-or-nothing method of managing change simply doesn’t cut it. We need browser-specific filtration, to account for scenarios where the fallback causes more harm than good.

“A standard is a standard – you should be able to render the same code consistently in every browser,” I hear some cry. “Browser-specific authoring is a dead end.” And they have my emphatic agreement. I’d love it if the real world proved that were the case. But it’s not.

Legitimate Hack Use

No matter how browsers evolve over the next few years, one thing seems relatively safe to predict – there will always be differing levels of support for web standards, whether it be a difference in rendering between major browsers, or even between various versions of the same browser.

The legitimate need for hacks arose as we discovered major browser bugs that prevented us from adopting CSS in the first place; through the use of hacks, we were able to specifically target versions of browsers and force them to comply. Even those on the W3C CSS working group recognize the need for page authors to work around these bugs; wasn’t it Tantek Çelik who gave us the Box Model Hack, after all?

But our CSS hacks are meant for an older set of browsers that will become less relevant in the near future; we don’t have any new mechanisms for filtering the current stable of browsers. How will we deal with browser discrepancies going forward, in light of potential usability problems?

Coping

I see a few ways.

  1. Limit yourself to only those CSS properties and selectors that you know will work across all browsers without fail. In fact, you don’t even have to wait for this, you can start today. Sure, it’s frustrating when all browsers but a single one render on your intended effect, but we’ve pretty well gotten used to that with things like :hover support on non-anchor elements. So, hang on to that patience, because you’ll need it.
  2. Perhaps this may not even be an issue. If all browsers continually improve, and we never see another repeat of Internet Explorer’s stagnation over the past 5 years, then we simply need to be patient until the effects we seek become practical, and with any luck that won’t be long.
  3. We could discover a whole new bag of hacks and filters. With the number of people hacking away at CSS these days, the chances aren’t small that sooner or later we’ll be able to exploit other bugs in other browsers, and get ourselves right back into this situation. I think a lot of people would prefer we didn’t go this route again, but it’s almost inevitable that sooner or later, the first IE7 and Firefox 1.0 hacks will rear their heads.
  4. Let’s think pie-in-the-sky here: we could get a bit of recognition that this problem is legitimate, and an official W3C-sanctioned method of browser filtration. I suspect the browser manufacturers are well aware that this is a problem; the IE team has given us a method for filtering out their own browser in the form of conditional comments, after all. Suggestions for codifying a similar method within CSS have been made to the CSS working group many times over the years, and I have it on good authority that there has been at least one formal proposal made in the past on the subject, but as far as I know, nothing has developed from either.

The danger in going this route echos what we learned about HTTP user agent strings in the late 90’s, of course. Crappy browsers will force page authors to filter them somehow. Crappy filtering will cause browsers to pose as each other. Maybe it would be better this time around, since the base technologies have matured a little bit. Maybe it wouldn’t.

The Reality

So what do I think is actually going to happen moving forward? Quite likely, a bit of everything.

Many will certainly follow the path of least resistance and simply limit themselves to code that works cross-browser. Others won’t settle for the status quo, and instead will look high and low for new hacks that target specific versions of specific browsers.

And maybe, just maybe, we’ll get a reliable method of filtering on a per-browser basis. I’m not holding my breath on that last one, but stranger things have happened.

Notes

  1. The Tan Hack, or * html bug as it’s also known, causes only IE to parse the CSS within the selector to which it’s applied. It will be fixed in IE7.
  2. The underscore hack causes only IE to parse the CSS within the rule to which it’s applied. It also will be fixed in IE7.

Technorati Profile

CSS specificity

CSS: Specificity Wars

Join me, and together we can rule the galaxy as father and geeks!

A few weeks back in Cupertino, I saw Aaron explain how the specificity of CSS selectors is calculated in a way which I hadn’t seen before. Then today I came across a knotty problem while building XHTML and CSS templates for a new project where two selectors behaved differently to how I expected and I realised that I had not completed my training.

The Dark Side

My problem was a simple one, how to feed a transparent PNG image to browsers which support transparency and a GIF image to older browsers which don’t, without resorting to hacks. Here’s the markup,

<div id="nav-supp">
<p><a id="a-02" href="#webstandards-org">Top</a></p>
<!-- etc. -->
</div>

and my CSS starting point.

a#a-02 { background-image : url(n.gif); }
a[id="a-02"] { background-image : url(n.png); }

I had assumed that a modern browser would see and apply both rules (with the second overriding the first) and that an older browser which does not understand attribute selectors would see and apply only the first, ignoring the second. I was wrong. Modern browsers did not apply the PNG image as I expected. The reason? A standard id selector wins over an attribute selector in terms of the cascade. Dagnammit! I know I should have read the specs, but somehow that particular pleasure had escaped me. If I had, I might have learned that;

ID selectors have a higher specificity than attribute selectors. For example, in HTML, the selector #p123 is more specific than [id=p123] in terms of the cascade.

Sith Lords

A little Googling uncovered some rather dry reading on the subject of selector specificity (resources below).

First, let’s look back at what Lord Elasticus (Patrick Griffiths) wrote on the subject of specificity (with one or two minor changes to fit our nefarious purpose).

You give every id selector (“#whatever”) a value of 100, every class selector (“.whatever”) a value of 10 and every HTML selector (“whatever”) a value of 1. Then you add them all up and hey presto, you have the specificity value.

  • p has a specificity of 1 (1 HTML selector)
  • div p has a specificity of 2 (2 HTML selectors; 1+1)
  • .sith has a specificity of 10 (1 class selector)
  • div p.sith has a specificity of 12 (2 HTML selectors and a class selector; 1+1+10)
  • #sith has a specificity of 100 (1 id selector)
  • body #darkside .sith p has a specificity of 112 (HTML selector, id selector, class selector, HTML selector; 1+100+10+1)

If all of these examples were used, div p.sith (with a specificity of 12) would win out over div p (with a specificity of 2) and body #darkside .sith p would win out over all of them, regardless of the order.

Darth (Gez) Lemon quotes the W3C.

A selector’s specificity is calculated as follows:

  • count the number of ID attributes in the selector (= a)
  • count the number of other attributes and pseudo-classes in the selector (= b)
  • count the number of element names in the selector (= c)
  • ignore pseudo-elements.

Concatenating the three numbers abc (in a number system with a large base) gives the specificity.

Too much! For me, the W3C really is in a galaxy far, far away!

CSS box model Hacks, div box model, width height box model, css hacks

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 CssDiscussList. 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 CaioHack. 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 StarHtmlHack. 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 [test] 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.