CSS Positioning Basics

CSS positioning is powerful, but there are a handful of basic concepts that must be understood before its power can be leveraged. The four most important position values are:

  • static – this is the default position value. It means that the element renders in order, as it appears in the document flow, and its position is determined by the browser and/or by HTML rendering conventions.
  • fixed – the element is positioned relative to the browser window.
  • relative – the element is positioned relative to where it would have been. In other words, if normal rendering would position the element at left=120, top=300 and you specify position: relative; left: 10; top: 20, the element’s position will be offset by these values and it’ll be drawn starting at left=130, top=320.
  • absolute – the element is positioned relative to its containing element, but – and here’s the thing that trips up a lot of people – only if the containing element’s position is not static. If the containing element is static, the browser looks to the next element up. If that element is static, the browser keeps going up and up until it finds a non-static positioned element. If it doesn’t find one, the element is positioned relative to the browser window. In other words, if all of the parent elements have the default static positioning, absolute positioning is the same as fixed positioning.

The next sections go into depth with the four position values.

Static Positioning

This is the default. It means to place the element where the browser would have placed it anyway. It’s rare to specify an element as position: static, but I’ll explain an exception shortly. Here’s an example of static positioning for a div; you’ll see in this case that it doesn’t affect where the div is rendered:

<html>
 <head>
  <style>
   div { position: static; left=400; top=5000; }
  </style>
 </head>
 <body>
  <p><strong>Static positioning</strong></p>
  <div>Here is the static-positioned div</div>
 </body>
</html>

 

Positioning-Static

With static positioning, the top and left values in the div style are ignored; that’s because static positioning means put the element where the browser would have put it anyway.

OK, so why would you ever specify an element as position: static? Only in one special case: if the element’s position is fixed or relative or absolute and you want to revert it to its default position.

Fixed Positioning

Fixed positioning is straightforward: an element is placed at exact coordinates within the browser window, even if there’s already another element there. The order of the elements doesn’t determine their placement; the coordinates do:

<html>
 <head>
  <style>
   .firstItem { position: fixed; left: 0; top: 0; background-color: red; }
   .secondItem { position: fixed; left: 20; top: 40; background-color: green; }
   .thirdItem { position: fixed; right: 0; bottom: 0; background-color: blue; }
  </style>
 </head>
 <body>
  <p><strong>Fixed positioning</strong></p>
  <div class=firstItem>The first item</div>
  <div class=secondItem>The second item</div>
  <div class=thirdItem>The third item</div>
 </body>
</html>

 

Positioning-Fixed

With fixed positioning, the elements are placed relative to the browser window. Some interesting effects to note:

  • The first item is positioned by its top/right coordinates and it "floats" down and right. It ends up on top of the paragraph that says Fixed positioning, which is the expected behavior: the paragraph is positioned statically (by its order in the HTML code), and the first div is placed by coordinates. If they overlap, so be it.
  • The second item is positioned by its top/right coordinates, just like the first.
  • The third item is positioned by its bottom/right coordinates, so it offsets from the bottom right of the screen. To anchor to the bottom left, specify position: fixed; bottom: 0; left: 0. To anchor to the top right, specify position: fixed; top: 0; right: 0.

Relative Positioning

Relative positioning offsets an element from where it would normally render. An example is best here:

<html>
 <head>
  <style>
   .baseElement { background-color: moccasin; }
   .noPositioning { background-color: coral; }
   .rightTenUpThree { position: relative; left: 10; top: -3; background-color: coral; }
   .leftTwelveDownTwenty { position: relative; left: 12; top: 20; background-color: coral; }
   .relativeBottom { position: relative; right: -5; bottom: 10; background-color: coral; }
  </style>
 </head>
 <body>
  <p><strong>Relative positioning</strong></p>
  <div class=baseElement>The base element</div>
  <div class=noPositioning><b>1</b>: No positioning</div>
  <hr>
  <div class=baseElement>The base element</div>
  <div class=rightTenUpThree><b>2</b>: Relative left 10 top -3</div>
  <hr>
  <div class=baseElement>The base element</div>
  <div class=leftTwelveDownTwenty><b>3</b>: Relative left 12 top 20</div>
  <hr>
  <div class=baseElement>The base element</div>
  <div class=relativeBottom><b>4</b> Relative right -5 bottom 10</div>
 </body>
</html>

 

Positioning-Relative
A few things to note about each example:

  • 1: No positioning
    this div doesn’t have any positioning directives, so it renders as part of the normal flow, after the div that precedes it.
  • 2: Relative left 10 top -3
    this div‘s styling is position: relative; left: 10; top: -3;, so its left offset is 10 pixels from where it would normally be placed. Its top offset is -3 pixels from where it would normally be placed, which is why it creeps up into the div that precedes it.
  • 3: Relative left 12 top 20
    this div‘s left position is 12 pixels from where it would normally be, and its top position is 20 pixels from where it would normally be. Its top position is shifted down so far that it overlays the div that follows it, which is expected. Also note that the div which follows it doesn’t have any positioning directives, so it was placed where it would normally go in the flow of the document; it’s not pushed down by the previous div‘s offset.
  • 4: Relative right -5 bottom 10
    This div‘s offset is specified from its bottom/right corner instead of its top/left. Relative offsetting by bottom/right will give the same result as offsetting by top/left, so most designers stick with top/left.

Absolute Positioning

Absolute positioning offsets an element from the first parent element whose position is not static – in other words, the first parent element that uses fixed, relative, or absolute positioning. If the parent’s positioning is static, the browser searches upward to the first non-static parent. If there isn’t a non-static parent, the element is placed relative to the browser window, as though its positioning were fixed.

This first example has an element with absolute positioning, but both of its parent elements are static so the element is positioned relative to the browser window:

<html>
 <head>
  <style>
   .firstElement { background-color: #E66; }
   .secondElement { background-color: #6E6; }
   .thirdElement { position: absolute; left: 0; top: 0; background-color: #66E; }
  </style>
 </head>
 <body>
  <p><strong>First Relative Positioning Attempt</strong></p>
  <div class=firstElement><b>1</b>: no positioning
    <div class=secondElement><b>2</b>: no positioning
      <div class=thirdElement><b>3</b>: absolute left 0 top 0</div>
    </div>
  </div>
 </body>
</html>
Positioning-Absolute-2
Child element 3: absolute left 0 top 0 is offset from the browser window because both of its parents have static positioning.

 
In the second example, the only difference is the secondElement style, which defines the position as position: relative; left: 0; top: 0;. This doesn’t change the second div‘s position at all, but because it’s now non-static it can be used as an offset for its child element:

<html>
 <head>
  <style>
   .firstElement { background-color: #E66; }
   .secondElement { position: relative; left: 0; top: 0; background-color: #6E6; }
   .thirdElement { position: absolute; left: 100; top: 10; background-color: #66E; }
  </style>
 </head>
 <body>
  <p><strong>Second Relative Positioning Attempt</strong></p>
  <div class=firstElement><b>1</b>: no positioning
    <div class=secondElement><b>2</b>: relative left 0 top 0
      <div class=thirdElement><b>3</b>: absolute left 100 top 5</div>
    </div>
  </div>
 </body>
</html>
Positioning-Absolute-1
Child element 3: absolute left 0 top 0 is offset from its parent 2: relative left 0 top 0 because the parent has a non-static position.