April 9th, 2008 - by Paul OB

Sometimes the simplest things can turn out to be more complicated than you ever imagined. This can sometimes be the case with CSS and cross-browser support. It’s no wonder that beginners to CSS often throw their hands up and revert back to using tables because some bug or other has thrown them off course.

As an example I thought I’d document a few problems that crop up time and time again with absolute positioned elements in our favorite browser – yes, IE6, I’m talking about you again!

Removed From The Flow

Absolute elements are removed from the flow and have no affect on surrounding content. Conversely surrounding content should not be able to affect absolute elements either. That’s not quite true as a positioned element will create a stacking context for further positioned elements but that’s as far as any effect will go. (We often set position:relative on a parent so that the absolutely positioned child can be placed in respect of that parent and not the viewport.)

In effect the absolute element should not care what else goes on around it and is oblivious to anything except its own start position. IE, however, has a few peculiar issues with this in the simplest of layouts and we will document a few of the most common and thought-provoking problems you will encounter on a day to day basis.

The following examples are a little contrived in order to show the effects at the simplest level and could be done by other methods but that’s not the point of the Lose Weight Exercise.

The Disappearing Margin Trick

The following example creates an absolute element at the top of the page which is 100px high. The following element is static but has a margin top of 100px to move it below the absolute element by 10px (remembering that absolute elements are removed from the flow so that the margin is taken from the top of the container and not the absolute element).

  1. #outer{
  2.     width:300px;
  3.     margin:auto;
  4.     border:1px solid #000;
  5.     position:relative;
  6. }
  7. .abs{
  8.     position:absolute;
  9.     top:0;
  10.     left:0;
  11.     width:300px;
  12.     height:100px;
  13.     background:red;
  14. }
  15. .follow{
  16.     margin:110px 0 0 0;
  17.     width:300px;
  18.     height:100px;
  19.     background:yellow;
  20. }
  1. <div id="outer">
  2.     <div class="abs">Absolute element</div>
  3.     <div class="follow">Following block</div>
  4. </div>

If you run this code in Firefox you will see something like the screenshot in Figure 1.

Figure 1
abfig01.gif

The code couldn’t be simpler as it’s basically two lines of code but let’s see what IE makes of it.

Figure 2
abfig02.gif

As you can see the yellow block which follows the absolute element has completely disappeared in both IE6 and IE7.

Where has it gone?

Although I said the yellow block has disappeared that’s not quite true. If we reduce the width of the absolute element we can see the yellow block skulking underneath the red block.

[CSS]
.abs{
position:absolute;
top:0;
left:0;
width:200px;/* width reduced*/
height:100px;
background:red;
}
[/CSS]

With the absolute element’s width reduced, the yellow block can be seen at the edge shown in Figure 3.

Figure 3
abfig03.gif

So what can we deduce from this?

It would seem that the top margin on static content is ignored in IE when it follows immediately after an absolutely placed element in the HTML.

For my next trick….

We know the issue is not a “haslayout” issue because the element already has a “layout” due to the width we gave it. Let’s try floating the following content instead and see if that fixes the problem for us.

  1. .follow{
  2.     margin:110px 0 0 0;
  3.     width:300px;
  4.     height:100px;
  5.     background:yellow;
  6.     float:left;/* float added*/
  7. }

All we have done is to add float:left to the static content and the result is shown in Figure 4.

Figure 4
abfig04.gif

Well things are looking much better in IE7!

IE6 is also showing the yellow block in the correct position but unfortunately IE6 has now hidden the red absolutely positioned block!

Obviously floating fixes IE7 but leaves IE6 still broken so it’s not a solution we can use.

What else can we try?

Let’s first remove the float we just added so that we are back to the original code and try something else. The following solution is one that I have tried and tested and probably posted 2 or 3 times a week in the forums. We won’t change the CSS at all but instead address the HTML. If we move the absolutely placed element to the end of the current stacking context then all these problems disappear.

[HTML]

Absolute element

[/HTML]

All we have done is to move the div that has a class of “abs” to the end of the current stacking context (i.e. to the end of #outer). The result of that simple change can be seen in Figure 5 below.

Figure 5
abfig05.gif

Both IE7 and IE6 now display the elements correctly. It’s a pain that the HTML has to be changed but I have found that this is the only reliable way to squash this rather annoying bug.

And there’s more….

The strangeness doesn’t stop there I’m afraid. If we use the new revised HTML but change our yellow block to be floated we observe another strange behavior in IE6 and under.
[CSS]
.follow{
margin:110px 0 0 0;
width:300px;
height:100px;
background:yellow;
float:left;
}
[/CSS]

The result of adding float makes the absolutely placed red block disappear altogether as shown in Figure 6 below.

Figure 6
abfig06.gif

We fixed our original problem by changing the order of the HTML which made everything work fine but now that we’ve added a float to the element following the absolute element we find that the absolute element has disappeared again. Damn!

Obviously we can’t change the HTML around again because we already know that it won’t work so what could be a solution this time?

This leads to a solution that I haven’t seen documented before (except by me) and the logic of the solution is nonsense which is why it probably hasn’t been noted before. In order to make the absolute element re-appear we add clear:both to the absolute element!

Of course this makes no sense because absolute elements are removed from the flow and therefore should not be affected by floats. Clear floats in our current example would seem to have no bearing in any shape or form. However, believe it or not by simply adding clear:both to the absolute element it miraculously re-appears.

The HTML is still as follows:
[HTML]

Absolute element

[/HTML]

  1. .abs{
  2.     position:absolute;
  3.     top:0;
  4.     left:0;
  5.     width:300px;
  6.     height:100px;
  7.     background:red;
  8.     clear:both
  9. }

Figure 7 shows that finally all elements are present and correct in IE6.

Figure 7
abfig07.gif

As I said at the start of the article the examples are a little contrived but that was in order to show the full effect of these strange bugs in the simplest of situations. Now that you know what they are and how they occur you will be able to fix them easily when it happens to you. The things to look out for are disappearing absolute elements or disappearing and misplaced content next to absolute elements or when floats follow absolute elements in the HTML. The full-proof solution is to move the HTML for the absolute element to the end of the current stacking context and then to add clear:both to it.

IE makes CSS so much fun — if things were to just work the first time, where would be the fun in that?

51 Responses to “CSS – An Absolute Mess”

1 Web Design Code, Tutorials, & Tools « Eric's Logic

[…] CSS – An Absolute Mess […]

mulberry sale spyder womens jacket cheap new balance 574 mulberry outlet cheap new balance 574 arcteryx outlet mulberry sale spyder womens jacket mulberry sale spyder womens jacket mulberry outlet mulberry outlet new balance 574

Popular Articles

Top 10 Commentators


Subscribe to this feed! Subscribe by Email!

Random Bits Podcast

Blogs Worth Reading