Demystifying Position Property
Tags: css, beginners, html, webdev
Published: 2021-07-11 06:38:20

CSS provides the **`position`** property that specifies how an element should appear in the document. This property is helpful when you want to position elements in the DOM outside of normal flow.

## What is this blog post about?
This blog post covers the **`position`** property with the **`top`**, **`right`**, **`bottom`**, **`left`**, and **`z-index`** properties that determine the final position of an element.

Since this property has a notorious tendency to be misunderstood, let's try to figure out this property together!

> Check out the demos I explained in this post [here](https://demystifying-css-position.netlify.app/)

## Prerequisites for the blog
This blog post assumes that you are familiar with the syntax and basics of HMTL and CSS.

<hr />

## What is the CSS position property?
* The **`position`** property specifies _how_ an element is placed in the DOM.
* Along with this, you can use **`top`**, **`right`**, **`bottom`**, and **`left`** properties that specify _where_ the element is placed.

<br />

* The **`position`** property can take _five_ values:
  1. static
  2. absolute
  3. relative
  4. fixed
  5. sticky

* Before we jump in, let's understand in short what **`top`**, **`right`**, **`bottom`**, **`left`**, and **`z-index`** are.
  
<br />

* The **`top`**, **`right`**, **`bottom`**, and **`left`**, properties specify how far away from the top/ right/ bottom/ left and element should be positioned. 
  * By default all these properties have value _auto_, and the element is placed in a [Static Position](#1-static).
  * It accepts both negative and positive integer values and common units such as *px*, *rem*, *em*, *%* etc.

<br />

* **`z-index`** is used to specify the stack level, and layer elements. 
  * The default value for **`z-index`** is 0, and will not work unless you apply position on the element (except static).
  * Elements with a larger **`z-index`** value overlaps elements with smaller **`z-index`** value.
  * It accepts positive and negative integers without any unit.

<hr /> 

### 1. Static
* ***`position: static;`*** is the default value of this property, and the elements appear in their normal flow in the document.
* Properties: **`top`**, **`right`**, **`bottom`**, **`left`**, and **`z-index`** have no effect on an element positioned **`static`**.
* Check the example below. The blue colored `div` with class `static` has a static position.
  ![Element with static position](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g0p8fin4xqk78g6hi0s9.png)

<br />

* The code for the above example:
     ```css
      div.static {
         position: static; /* Need not specify as this is default */
     }
    ```
Check out the codepen here: 
{% codepen https://codepen.io/bhaaratii/pen/MWmjOJa default-tab=html,css %}
 


### 2. Relative
* When ***`position: relative;`*** is applied to an element, it appears in the normal flow of the document.
* But unlike [***static position***](#1-static), it accepts accepts values for **`top`**, **`right`**, **`bottom`**, **`left`**, and **`z-index`**.
  * The element is then placed relative to _itself_ depending on the values of **`top`**, **`right`**, **`bottom`**, **`left`**, and stacked in layers depending on the value of **`z-index`**.

* In the example shown below, the blue colored `div` element with class `relative` has a relative position, with top and left offset values.
  ![Element with relative position](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yqg1m3ujunhi7s1poehl.png)

<br />

* The code for the above example:
     ```css
      div.relative {
         position: relative;
         top: 5em;
         left: 25%;
     }
    ```
Check out the codepen here: 
{% codepen https://codepen.io/bhaaratii/pen/mdmrwJK default-tab=html,css %}


### 3. Absolute
* When ***`position: absolute;`*** is applied to an element, it is taken _out_ of the the normal flow of the document.
* It remains in it's original position unless **`top`**, **`right`**, **`bottom`**, **`left`** values are specified.
* The other elements ignore the element, and behave as if it is not present at all. 
* **`z-index`** can also be specified to stack and layer elements.

<br />

* In the example below, the blue colored `div` with class `absolute` is given a relative position, and no values of **`top`**, **`right`**, **`bottom`**, and **`left`** are specified.
  ![Element with absolute position](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h3no7oyzye5fdczfvsg1.png)

* See what happens when this blue box is given **`z-index: -1;`**
  ![absolute positioned element with z-index -1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v7dpra2xwqfkodw2gb3o.png)
  * The parent of this `div.absolute` is the section with class `section` and `background-color: lightskyblue;` has `z-index: 0;`.
  * Since **`z-index**` of `section.section` is greater than that of `div.absolute`, the `div` is stacked below it's parent.

<br />

* Typically an element with **`position: absolute;`** is placed relative to it's closest positioned ancestor (other than static).
* If no such ancestor is found, it is simply placed relative to the document.
  * Check out the example below, and notice how the element is placed relative to the document.
    ![Element with absolute position relative to document](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qs4cf9en28zdafhzj569.png)

* The code for the above example:
     ```css
      div.absolute-two {
         position: absolute;
         top: 0;
         bottom: 0;
         left: 2em;
     }
    ```

<br />
 

* Check out what happens, if we give the parent (or an ancestor) of an element with absolute position: `position: relative;`.  
  ![Element with position absolute within an ancestor positioned absolute](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pqjfrb093smnra71dfzr.png)
  * Check the red colored `div` with a class `absolute-three`, and it's lightskyblue colored parent `section` with class `section`.
  * Note how this time the absolute `div.absolute-three` is positioned relatively within the parent and not the document.

* The code for the above example is: 
    ```css
      section.section {
         position: relative;
      }

      div.absolute-three{
         position: absolute;
         bottom: 0;
         right: 25%;
         height: 100px;
     }
    ```

Check out the final codepen here: 
{% codepen https://codepen.io/bhaaratii/pen/KKmgqON default-tab=html,css %}


### 4. Fixed
* When ***`position: fixed;`*** is applied to an element, it is taken _out of the the normal flow of the document_ similar to [Absolute Position](#3-absolute).
  * The main difference is that the ***`position: fixed;`*** element is not given space in the layout.
* The fixed element is not affected by scrolling, and remains in the specified position depending on the **`top`**, **`right`**, **`bottom`**, and **`left`** values.
* The positioned element is relative to the document except when it's ancestors have **`transform`**, **`perspective`**, or **`filter`** property applied with a value other than ***none***. 
  * Then, the ancestor behaves as the relative parent.

<br />

* Check out the example below. The text `div` with blue background has a class `fixed` and **`position: fixed`**
  ![Element with fixed position](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/op5t9su8dwx0wn0d9e6z.png)

* The code for the above example is: 
    ```css
      div.fixed {
         position: fixed;
         top: 40vh;
         right: 25vw;
         left: 25vw;
     }
    ```

Check out the codepen here
{% codepen https://codepen.io/bhaaratii/pen/KKmgXpe default-tab=html,css %}

### 5. Sticky
* When ***`position: sticky;`*** is applied to an element, it is positioned in the the normal flow of the document similar to [Relative Position](!#2-relative).
* But as the element is scrolled within the positioned ancestor, it becomes fixed once the offset value specified in **`top`**, **`right`**, **`bottom`**, and **`left`** properties are crossed.

<br />

* For e.g. look at the image below of a header.
  ![Header with sticky positione](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3g2zdyizf0azdtxfgs15.png)
  * The header's parent is the document, and it's ***"sticky"*** within it. As you scroll and the header is _0 away from top_, i.e. `top: 0;`, it becomes a fixed positioned element.

* The code for the above example is: 
    ```css
      header.hero {
         position: sticky;
         top: 0;
     }
    ```

<br />
* Let's deal with another scenario. But this time let's use an element that is positioned **sticky** within another positioned ancestor.
  ![Element with sticky position within a relative positioned ancestor](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m5erk9eb3fsumbe9fzse.png)
  * In this scenario, the sticky positioned element (text with blue colored background) has a class of `sticky`. 
  * It's parent is the `section` with class `section`, and has a `lightskyblue background`.
  * As you scroll down and `div.sticky` is `5px` away from the top, it becomes a fixed element. Before that it remains as relatively positioned element.
  * But there is a catch here. As the parent `section.section` scrolls away from the layout, so does the div with **sticky** position of. It no longer remains fixed, and now becomes relative again.
    ![Element with position sticky within relative positioned ancestor](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9iecnxamfkq9lethmxnk.png)

<br />
* ***Hence the sticky (in particular fixed) behavior of an element remains only within it's closest positioned parent.***

* The code for the above example is: 
    ```css
      section.section{
         position: relative;
      }
      div.sticky {
         position: sticky;
         top: 5px;
      }
    ```


Check the entire codepen here:
{% codepen https://codepen.io/bhaaratii/pen/BaRLmaG default-tab=html,css %}
 

<hr />

## CONCLUSION
Phew! That was a lot. Wasn't it?

I understand that sometimes CSS can be overwhelming but trust me, as you practice the concepts become clearer.

The **`position`** property is very important, and comes in handy in various scenarios.

> Check out the demos I explained in this post [here](https://demystifying-css-position.netlify.app/)


* The `relative` and `absolute` positions are often used, and mostly together when you have pseudo elements. 
  * These positions are also often used to stack items. 
  * The combination of `absolute` position within `relative` position is common, and is used to add styles such as shadows to elements.
* The `sticky` position can be used for headers and navbar as shown in the example for [Sticky](#5-sticky) above.
  * It could also be used in cases when you want to keep an element fixed on the page as long as the positioned parent/ ancestor is visible on the viewport.

> These are not the only available use cases of `position` property. I highly recommend you to practice and get your hands dirty to understand these concepts in depth.


<hr />

Thank you so much for reading this post! 

This was my final blog post on CSS. In the coming posts, I will focus on JavaScript and try to explain few vital concepts.

_**If you liked this post then please help me out giving it a heart, unicorn or a pin!**_
Do share it among your dev friends, and comment down what you feel!

<hr />

## RESOURCES:
- [Absolute and Relative Position Explained by Kevin Powell](https://youtu.be/P6UgYq3J3Qs)
- [Practical Examples of Absolute Position by Kevin Powell](https://youtu.be/lUaw-AA9HnA)
- [Things you can do with Position Sticky by Kevin Powell](https://youtu.be/8TyoihVGErI)
- [CSS Position MDN docs](https://developer.mozilla.org/en-US/docs/Web/CSS/position)