CSS Positioning

Positioning is what makes us determine where elements appear on the screen, and how they appear.

You can move elements around, and position them exactly where you want.

In this section we'll also see how things change on a page based on how elements with different position interact with each other.

We have one main CSS property: position.

It can have those 5 values:

  • static
  • relative
  • absolute
  • fixed
  • sticky

Static positionin

This is the default value for an element. Static positioned elements are displayed in the normal page flow.

Relative positioning

If you set position: relative;on an element, you are now able to position it with an offset, using the properties:

  • top
  • right
  • bottom
  • fixed
  • left

which are called offset properties . They accept a length value or a percentage.

take this example that I give most especially try our try it example to see how it work. In the below code sample, I create a parent container, a child container, and an inner box with some text:


<div class="parent">
  <div class="child">
    <div class="box">
      <p>Test</p>
    </div>
  </div>
</div>

with some CSS to give some colors and padding, but does not affect positioning:


.parent {
  background-color :#af47ff;
  padding :30px;
  width :300px;
} 

.child {
  background-color :#ff4797;
  padding :30px;
} 

.box {
  background-color :#f3ff47;
  padding :30px;
  border :2px solid #333;
  border-style :dotted;
  font-family :courier;
  text-align :center;
  font-size :2rem;
} 

here's the result:

Learn HTML

You can try and add any of the properties I mentioned before ( top , right , bottom , left ) to .box , and nothing will happen. The position is static .

Now if we set position: relative to the box, at first apparently nothing changes. But the element is now able to move using the top, right, bottom, leftproperties, and now you can alter the position of it relatively to the element containing it.

For example:


.box {
  /* ... */
  position :relative;
  top :-60px;
} 

here's the result:

Learn HTML

Now let's keep seeing the resuilt using our Try it text editor.

Example

<!DOCTYPE HTML>
<html>
    <head>
      <style>
      .parent {
        background-color :#af47ff;
        padding :30px;
        width :500px;
      } 
      
      .child {
        background-color :#ff4797;
        padding :30px;
      } 
      
      .box {
        background-color :#f3ff47;
        padding :30px;
        border :2px solid #333;
        border-style :dotted;
        font-family :courier;
        text-align :justify;
        font-size :1rem;
        position :relative;
        top :-60px;
      } 
      
      </style>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
      <title>Title of the Document</title>
    </head>
    <body>
    <div class="parent">
    <div class="child">
      <div class="box">
        <p>Test</p>
      </div>
    </div>
  </div>
  </body>
</html>

A negative value for top will make the box move up relatively to its container. Or by applying the below code.


.box {
  /* ... */
  position :relative;
  top :-60px;
  left :180px;
} 

Example

<!DOCTYPE HTML>
<html>
    <head>
      <style>
      .parent {
        background-color :#af47ff;
        padding :30px;
        width :500px;
      } 
      
      .child {
        background-color :#ff4797;
        padding :30px;
      } 
      
      .box {
        background-color :#f3ff47;
        padding :30px;
        border :2px solid #333;
        border-style :dotted;
        font-family :courier;
        text-align :justify;
        font-size :1rem;
        position :relative;
        top :-60px;
        left :180px;
      } 
      
      </style>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
      <title>Title of the Document</title>
    </head>
    <body>
    <div class="parent">
    <div class="child">
      <div class="box">
        <p>Test</p>
      </div>
    </div>
  </div>
  </body>
</html>

After running the above code you will notice how the space that is occupied by the box remains preserved in the container, like it was still in its place.

Another property that will now work is z-index to alter the z-axis placement. We'll talk about it later on.

Absolute positioning

Setting position: absolute; on an element will remove it from the document's flow, and it will not longer .

Remember in relative positioning that we noticed the space originally occupied by an element was preserved even if it was moved around?

With absolute positioning, as soon as we set position: absolute; on .box, its original space is now collapsed, and only the origin (x, y coordinates) remain the same.


.box {
  /* ... */
  position :absolute;
} 

Example

<!DOCTYPE HTML>
<html>
    <head>
      <style>
      .parent {
        background-color :#af47ff;
        padding :30px;
        width :500px;
      } 
      
      .child {
        background-color :#ff4797;
        padding :30px;
      } 
      
      .box {
        background-color :#f3ff47;
        padding :30px;
        border :2px solid #333;
        border-style :dotted;
        font-family :courier;
        text-align :justify;
        font-size :1rem;
        position :absolute;
      } 
      
      </style>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
      <title>Title of the Document</title>
    </head>
    <body>
    <div class="parent">
    <div class="child">
      <div class="box">
        <p>Test</p>
      </div>
    </div>
  </div>
  </body>
</html>

We can now move the box around as we please, using the top, right, bottom, left properties:


.box {
  /* ... */
  position :relative;
  top :0px;
  left :0px;
} 

Example

<!DOCTYPE HTML>
<html>
    <head>
      <style>
      .parent {
        background-color :#af47ff;
        padding :30px;
        width :500px;
      } 
      
      .child {
        background-color :#ff4797;
        padding :30px;
      } 
      
      .box {
        background-color :#f3ff47;
        padding :30px;
        border :2px solid #333;
        border-style :dotted;
        font-family :courier;
        text-align :justify;
        font-size :1rem;
        position :relative;
        top :0px;
        left :0px;
      } 
      
      </style>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
      <title>Title of the Document</title>
    </head>
    <body>
    <div class="parent">
    <div class="child">
      <div class="box">
        <p>Test</p>
      </div>
    </div>
  </div>
  </body>
</html>

Or with:


.box {
  /* ... */
  position :relative;
  top :140px;
  left :50px;
} 

Example

<!DOCTYPE HTML>
<html>
    <head>
      <style>
      .parent {
        background-color :#af47ff;
        padding :30px;
        width :500px;
      } 
      
      .child {
        background-color :#ff4797;
        padding :30px;
      } 
      
      .box {
        background-color :#f3ff47;
        padding :30px;
        border :2px solid #333;
        border-style :dotted;
        font-family :courier;
        text-align :justify;
        font-size :1rem;
        position :relative;
        top :140px;
        left :50px;
      } 
      
      </style>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
      <title>Title of the Document</title>
    </head>
    <body>
    <div class="parent">
    <div class="child">
      <div class="box">
        <p>Test</p>
      </div>
    </div>
  </div>
  </body>
</html>

The coordinates are relative to the closest container that is not static

This means that if we add position: relative to the .child element, and we set top and left to 0, the box will not be positioned at the top left margin of the window, but rather it will be positioned at the 0, 0 coordinates of .child:


.child {
  /* ... */
  position :relative;
} 

.box {
  /* ... */
  position :absolute;
  top :0px;
  left :0px;
} 

Example

<!DOCTYPE HTML>
<html>
    <head>
      <style>
      .parent {
        background-color :#af47ff;
        padding :30px;
        width :500px;
      } 
      
      .child {
        background-color :#ff4797;
        padding :30px;
        position :relative;
      } 
      
      .box {
        background-color :#f3ff47;
        padding :30px;
        border :2px solid #333;
        border-style :dotted;
        font-family :courier;
        text-align :justify;
        font-size :1rem;
        position :absolute;
        top :0px;
        left :0px;
      } 
      
      </style>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
      <title>Title of the Document</title>
    </head>
    <body>
    <div class="parent">
    <div class="child">
      <div class="box">
        <p>Test</p>
      </div>
    </div>
  </div>
  </body>
</html>

Here's (how we already saw) of .child is static (the default):


.child {
  /* ... */
  position :static;
} 

.box {
  /* ... */
  position :absolute;
  top :0px;
  left :0px;
} 

Example

<!DOCTYPE HTML>
<html>
    <head>
      <style>
      .parent {
        background-color :#af47ff;
        padding :30px;
        width :500px;
      } 
      
      .child {
        background-color :#ff4797;
        padding :30px;
        position :static;
      } 
      
      .box {
        background-color :#f3ff47;
        padding :30px;
        border :2px solid #333;
        border-style :dotted;
        font-family :courier;
        text-align :justify;
        font-size :1rem;
        position :absolute;
        top :0px;
        left :0px;
      } 
      
      </style>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
      <title>Title of the Document</title>
    </head>
    <body>
    <div class="parent">
    <div class="child">
      <div class="box">
        <p>Test</p>
      </div>
    </div>
  </div>
  </body>
</html>

Like for relative positioning, you can use z-index to alter the z-axis placement.

Fixed positioning

Like with absolute positioning, when an element is assigned position: fixed; it's removed from the flow of the page.

The difference with absolute positioning is this: elements are now always positioned relative to the window, instead of the first non-static container.


.box {
  /* ... */
  position :fixed;
} 

Example

<!DOCTYPE HTML>
<html>
    <head>
      <style>
      .parent {
        background-color :#af47ff;
        padding :30px;
        width :500px;
      } 
      
      .child {
        background-color :#ff4797;
        padding :30px;
      } 
      
      .box {
        background-color :#f3ff47;
        padding :30px;
        border :2px solid #333;
        border-style :dotted;
        font-family :courier;
        text-align :justify;
        font-size :1rem;
        position :fixed;
      } 
      
      </style>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
      <title>Title of the Document</title>
    </head>
    <body>
    <div class="parent">
    <div class="child">
      <div class="box">
        <p>Test</p>
      </div>
    </div>
  </div>
  </body>
</html>

let's add more properties:


.box {
  /* ... */
  position :fixed;
  top :0px;
  left :0px;
} 

Example

<!DOCTYPE HTML>
<html>
    <head>
      <style>
      .parent {
        background-color :#af47ff;
        padding :30px;
        width :500px;
      } 
      
      .child {
        background-color :#ff4797;
        padding :30px;
      } 
      
      .box {
        background-color :#f3ff47;
        padding :30px;
        border :2px solid #333;
        border-style :dotted;
        font-family :courier;
        text-align :justify;
        font-size :1rem;
        position :fixed;
        top :0px;
        left :0px;
      } 
      
      </style>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
      <title>Title of the Document</title>
    </head>
    <body>
    <div class="parent">
    <div class="child">
      <div class="box">
        <p>Test</p>
      </div>
    </div>
  </div>
  </body>
</html>

Another big difference is that elements are not affected by scrolling. Once you put a sticky element somewhere, scrolling the page does not remove it from the visible part of the page.

Sticky positioning

While the above values have been around for a very long time, this one was introduced recently and it's still relatively unsupported.

The UITableView iOS component is the thing that comes to mind when I think about position: sticky . You know when you scroll in the contacts list and the first letter is sticked to the top, to let you know you are viewing that particular letter's contacts.

We used JavaScript to emulate that, but this is the approach taken by CSS to allow it natively.