CSS2: Absolute and Relative Positioning

Here is an introduction to the use of positioning in CSS. It was originally posted on webmasterworld.com.

Normal Flow

Before getting in to positioning, you first need to understand normal flow.

Normal flow is the way a page would display if you had no positioning or floating. block elements are stacked, one on top of the other, starting at the first element in your document to the last element in your document. If a block element contains several other block elements, the parent grows so that it can fit all of its children. A box's margin adjusts its distance between the box above and below it. If two vertically adjacent boxes have margins set like this:

<div style="margin-bottom: 10px">text</div>
<div style="margin-top: 20px">text</div>

The margins collapse, to become the maximum of the two margins, in this case, there will be 20px of space between the two boxes. The rules for negative margins are slightly different, and the behavior around relatively positioned boxes is slightly different.

When a box is taken out of normal flow, it does not make a space for itself in the flow, it is as if the box doesn't exist at all. A box that is not in the normal flow will not displace the stacking of any other element, anywhere.

Instead, the box is offset relative to its containing box.

Containing Boxes

The root of the document is the initial containing box. Whenever you designate a box as absolute, fixed, or relative (I don't think there are others), you get a new containing box. In this example, the inner div will be absolutely positioned relative to the edges of the outer div.

<div style="position: absolute;
            width: 100px;
            height: 100px;
            border: 1px solid black;">
  <div style="position: absolute;
              left: 50px;
              top: 50px;
              width: 50px;
              height: 50px;
              border-top: 1px solid red;
              border-left: 1px solid red">text</div>
</div>

Relative Positioning

Now we'll go back to relative positioning. If you don't specify an offset, then the element will stay in the same place. The box will still lay out as if it was a normal, staticly positioned box. If you do offset the box, then boxes below it are positioned as if you had not offset the box.

Relative Positioning Example

I want a titlebox, a border around my content, with a description of the box along the border.

Here's some HTML:

<div class="title-box">
  <div class="title-box-title">Title</div>
  <p>Content
</div>

So my plan is to add some margin and padding to the title-box, then relatively position the title-box-title on top of the border. Content inside the title-box should behave as if the title-box-title doesn't exist. (As an additional benefit, this will still look OK in a text-only browser, because the title is a block-element). Let's try.

Ok, here we've got a margin, border, and padding:

.title-box {
  margin: .5em;
  border: .1em solid black;
  padding: .5em;
}

Ok, so we'll move the title of the title-box up onto the border:

.title-box-title {
  position: relative;
  display: inline;
  border: 1px solid;
  border-width: 0 .1em;
  padding: 0 .5em;
  top: -1.1em;
  background-color: white; 
}

But that causes a problem, because we have to add a rule like this to get the content inside the title-box to behave as if the title-box-title doesn't exist:

.title-box-title + * {
  margin-top: -1.1em;
}

Let's try again...

Make the title-box establish a new containing box for positioning:

.title-box {
  position: relative;
  margin: .5em;
  border: .1em solid black;
  padding: .5em;
}

Then have the title-box-title be absolutely positioned (so it no longer is in the flow) and adjust the offsets to match. (No we don't need the rule with the '+' selector, which IE doesn't understand.)

.title-box-title {
  position: absolute;
  display: inline;
  border: 1px solid;
  border-width: 0 .1em;
  padding: 0 .5em;
  top: -.6em;
  left: 1em;
  background-color: white; 
}

And the finished product:

Title

Content

Further Reading

CSS2 Section 9.3: Positioning schemes

CSS2 Section 9.8: Comparison of normal flow, floats, and absolute positioning