Understanding Position in CSS

“Close-up of a person's hands on the keyboard of a MacBook” by Glenn Carstens-Peters on Unsplash

Developing an understanding of the position property in CSS can be one of the most frustrating experiences for a beginner.

I can remember lucking out sometimes playing CSS roulette — trying different combinations of positions until I kind of got what I wanted. Kind of. I also remember times I wasn’t so lucky and ended up with a garbled mess.

Turns out, lady luck favours the prepared, so before your next spin on the wheel, here’s an ace to have up your sleeve.

This is CSS positioning simplified.

tldr — there’s a cheat sheet at the bottom.

There are two types of positioning

There is static-type positioning and relative-type positioning.

Static-type positioning consists of only one value: position: static. It’s the default, so you’ll rarely see it declared.

Relative-type positioning consists of the values position: relative, position: absolute and position: fixed. These positioning values interact with each other and allow you to move elements around in interesting ways.

Static Positioning

Let’s get the boring stuff out of the way first. While its not very often you’ll see a static position declaration in the wild, it behooves us to start our positioning journey at the beginning.

.ourBox {
position: static;
Static positioning, the default for every element ever.

Static positioning is the default positioning of every element, regardless of whether you declare it. It tells the element to position itself in the normal flow of the document, like a good little boxy.

Relative Positioning (relatively speaking)

Relative-type positioning is where things start to get exciting.

Available values are relative, absolute and fixed and they are called relative-type positions because they allow elements to be offset relative to themselves, a parent or the viewport respectively.

All relative-type positions can do the following:

  • Be moved out of their normal flow positions through the use of offset properties, those being: top, right, bottom and left.
  • Create a new relative-type positioning context which allows child elements with position: absolute to be positioned relative to the position of this element.

Let’s take a closer look at each of the three relative-type positions.

Position Relative

You’ve probably seen it before. The code looks like this:

.ourBox {
position: relative;

Elements that are position: relative can be moved out of their normal flow position while still taking up the same space. This is achieved by utilising those offset properties to offset the element, relative to itself.

For clarity, when you use an offset to visually move an element with position: relative, the space that it takes up in the document doesn’t move.

Let's have a look at an example.

.ourBox {
position: relative;
  top: 20px;
left: 20px;
Our box is offset from its original position using offset properties.

Here we can see the top of the element being offset by 20px, relative to where it would have been in normal flow. The same is being applied to the left side.

Notice that the positions of the boxes on either side have not changed. Remember, when you offset an element’s position with position: relative, the space it takes up doesn’t move, so it won’t affect anything around it.

It's like our box has a free spirit and can go wherever it wants, but always in relation to where it was originally.

It’s important to note that if you apply position: relative to an element, you don’t have to apply offset properties. Some boxes are fine where they are after all.

Position Absolute

Strap in.

position: absolute essentially does the same thing as position: relative, with two key differences:

  • The element is taken out of normal flow and leaves no space behind.
  • The element is positioned relative to its nearest parent with a relative-type positioning.

Let’s take a look:

.ourBoxesParent {
position: relative;
.ourBox {
position: absolute;
top: 0;
left: 0;
Here we take our box out of normal flow and offset it relative to its nearest relative-type parent.

We’ve added a wrapper to our trio of boxes which is position: relative. We’ve also changed our box to be position: absolute. Notice that the space we were taking up before has collapsed — the two grey boxes now appear side by side.

position: absolute specifies that you want to take your element out of normal flow, leaving no space behind, and offset its position relative to the nearest parent which also has a relative-type positioning.

Position Fixed

Now that we know about position: absolute, this one is a piece of cake.

fixed is the same as absolute with one key difference:

  • The element is positioned relative to the viewport.
.ourBox {
position: fixed;
top: 0;
left: 0;
Using fixed positioning, our box has moved to the top left corner of the viewport.

This means that even if the page is scrolled, our little box is staying put.

Cheat Sheet

For quick reference, here’s a cheat sheet for what we’ve learned.

position: static

  • Default positioning for all elements.
  • Puts element in normal flow.

position: relative

  • Can be offset with top, right, bottom and left.
  • Offset relative to itself.
  • Creates relative-type positioning context for children.

position: absolute

  • Can be offset with top, right, bottom and left.
  • Offset relative to its nearest relative-type positioned parent.
  • Creates relative-type positioning context for children.

position: fixed

  • Can be offset with top, right, bottom and left.
  • Offset relative to the viewport.
  • Creates relative-type positioning context for children.

Further reading:

MDN Web Docs: positioning

CSS Tricks: Absolute, relative, fixed positioning. How do they differ?