# Positioning in CSS

The ability to position elements on a page is a must-have for every web developer. I see beginners struggle with it every now and then, and to be honest, I did too. But if you take your time and get this right, you will come to realize that it's not that big of a deal at all. Let's learn more about the **position** property in CSS, shall we?

# The position CSS property

The **position** property tells the browser how an element should be positioned on the page. By default, the value of the **position** of an element is `static`, but we can modify it to be any of the following values: `relative`, `absolute`, `fixed`, `sticky`. In this post, we will go over each of them.

## Examples that we'll be seeing in this article

We will use a simple HTML code which is really basic for our better understanding. It contains a container div, and 3 child div elements, that we will position throughout the examples. I've also added different colors to these child div elements, so it will be easier to see the difference.

```css
<!DOCTYPE html>
<html>
  <head>
    <title> CSS positions </title>
    <style>
      .container {
        background-color: lightblue;
        padding: 20px;
      }

      .container > div {
        padding: 15px;
      }

      .container span {
        margin-bottom: 20px;
      }

      .first {
        background-color: lightgreen;
      }

      .second {
        background-color: lightcoral;
      }

      .third {
        background-color: lightgoldenrodyellow;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <span>Container</span>
      <div class="first"> First </div>
      <div class="second"> Second </div>
      <div class="third"> Third </div>
    </div>
  </body>
</html>
```

## Static

This is the default value of the **position** property. If the position of an element is `static`, the element will render in order, based on its position in the original document flow.

*This is what it looks like -*

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1658907583590/9E1Bc2cQ6.png align="left")

## Relative

If we set the **position** of an element to **relative**, it will appear in the document as it would by default using static. The trick is that by setting position relative, we gain access to the following CSS properties: `top`, `left`, `right`, `bottom`. With these, we can add an offset to the specific direction. So for example, if we set `left: 20px`. The element will be placed 20 pixels to the right. If we would have provided -20px it would push the content to the left with 20 pixels.

If we make the following changes:

```css
.second {
         background-color: lightcoral;
         position: relative;
         left: 20px;
        }
```

*Here's the result -*

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1658907697314/KrPV00cPu.png align="left")

## Fixed

With **fixed position,** we also have access to the `top`, `left`, `right`, `bottom` properties. In this case, the element is positioned relative to the browser window's viewport.

So, if we set `top 70px` and `left 20px` on a **fixed positioned** element it will appear 70 pixels from the top of the viewport and 20px from the left edge of the viewport. **Fixed position** also removes the document from the normal document flow.

If we change the CSS to this:

```css
.second {
         background-color: lightcoral;
         position: fixed;
         left: 20px;
         top: 70px;
        }
```

*This will be the result-*

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1658907833031/7P1pjpaRb.png align="left")

## Absolute

**Absolute position** is the one which can trick developers. It is working like the **fixed position**, but it is not positioned relatively to the viewport, instead, it is positioned based on the closest positioned element (which has a **position** value other than `static`). If there are no positioned parents it will be positioned relative to the viewport (Same result as it would be with `fixed`).

Now let's make the following changes to your CSS:

```css
.second {
         background-color: lightcoral;
         position: absolute;
         left: 20px;
         top: 70px;
        }
```

*We will get the same result as we got with the fixed position-*

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1658907949286/02KtbgP45.png align="left")

If we add a **position** value to a parent, in this case, we will add it to the container div, the child with `absolute` value will be positioned relative to that. We often use `relative` position for the parent as it won't remove it from the standard document flow and the parent will be placed in the site where it would have been without `position: relative`.

Let's add `relative` position to the container:

```css
.container {
            background-color: lightblue;
            padding: 20px;
            position: relative;
           }
```

*This is the result-*

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1658908045939/CAdwiOnuM.png align="left")

## Sticky

Using `sticky` will position our element based on the user's scroll position. It toggles between **position** `relative` and `fixed`. We can provide the offsets using `top`, `left`, `right` and `bottom`. Until the specified offsets are met the element acts like a relatively positioned element, but when the scroll position is greater than the offset it 'switches' to position fixed and be positioned relative to the viewport. It stays fixed until the user scrolls back to the opposite direction and the distance will be less than the offset, then it goes back to act like a `relative` positioned element again.

To be able to scroll add 3 times the height of the viewport to our container

```css
.container {
            background-color: lightblue;
            padding: 20px;
            height: 300vh;
           }
```

We need to add the `sticky` position and the `top` offset to the element:

```plaintext
.second {
         background-color: lightcoral;
         position: sticky;
         top: 0;
        }
```

*The result-*

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1658908170673/vsI6jVDAA.png align="right")

Now, by default, the page looks like we haven't done anything. But if we scroll down, below the second div, it sticks to the top directly (because of the 0px offset, add more if you need), and scrolls with the content in that `fixed` **position**. If we scroll back to the top, it will be placed in its original position.

And this is everything you'll ever need to know in order to position elements on a webpage like a pro.
