Published
Edited
Dec 11, 2019
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
html`<h2 style="margin-bottom: 10px;">Heading</h2>
<p style="margin-top: 10px;">Paragraph</p>
` // open devtools to see the padding and margin
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

md`
The `position` property, while important, is not what you should be using for the majority of layout related decisions. Changing `position` from it's default value (`static`) should be reserved for a few specific situations. There are three that are mainly used: `fixed`, `absolute`, and `relative`. A positioned element is affected by `top`, `left`, `right`, `bottom` and `z-index`.

### Normal flow

If you do not modify the `position` of any element, everything pertains to the [Normal flow](https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Normal_Flow) of the document. All this means is that:

- block level elements will take up the **full width** of their **container**, and the height of their content
- block level elements will stack on top of each other vertically, from top to bottom
- inline elements are as tall and wide as their content
- all elements are aware of each other, and margins will collapse

### Static

The default state of `position` is `static`. It means your element stays in the normal flow of the document. If you have three static `div`s next to each other, they will all be aware of each other and stack on top of each other.

```html
<div>div</div>
<div>div</div>
<div>div</div>
div {
border: 1px solid black;
padding: 15px;
margin: 15px;
}
```

[![div](https://www.taniarascia.com/static/16af13724d9ba12965e46d368101476b/4d3f1/div.png)](https://www.taniarascia.com/static/16af13724d9ba12965e46d368101476b/9199c/div.png)

`static` elements are not positioned, and therefore not affected by `top`, `left`, `right`, `bottom`, or `z-index`.

> **Note:** Just because elements have a `static` position does not always mean they will stack each other vertically. The `display` property might modify this, with `inline-block`, `grid`, or `flex`, but they will still be part of the regular document flow and other elements will be aware of them.

### Fixed

A `fixed` element is the easiest position to understand: it is always visible and positioned according to the viewport.

A few common uses of `fixed` positioning:

- a stick-to-top **navigation bar**
- a **back to top** button in the bottom right of the screen
- a **popup modal** that is in the center of the viewport

```css
nav {
position: fixed;
}
```

A few things to know about `fixed` elements:

- their position on the screen is determined by `top`, `left`, `right`, and `bottom` properties. `top: 0` means it will stick to the top of the viewport, and `top: 10px` means it will be `10px` from the top of the viewport
- other elements are **not aware** of the existence of a `fixed` element. This generally means you must account for the space they would occupy by **adding margins** to the elements around them.
- `fixed` elements are no longer part of the flow and do not have a containing element, and therefore do not expand to fill their container like a normal (block) element would.

This means if all we do is set our `nav` to fixed with no other properties, it will not expand the full width of the viewport.

```html
<nav>nav</nav>
<div>div</div>
<div>div</div>
div {
border: 1px solid black;
padding: 15px;
margin: 15px;
background: white;
}

nav {
position: fixed;
background: gray;
}
```

[![nav](https://www.taniarascia.com/static/e8e5eff5e855842eef21a32d93c752cc/4d3f1/nav.png)](https://www.taniarascia.com/static/e8e5eff5e855842eef21a32d93c752cc/65d02/nav.png)

So we can update it to be full width, and stick to the top and left of the viewport:

```css
nav {
position: fixed;
top: 0;
left: 0;
padding: 20px;
width: 100%;
background: gray;
z-index: 2;
}
```

[![nav2](https://www.taniarascia.com/static/e41dd6f0f3aeccb88f276085f1508f9e/4d3f1/nav2.png)](https://www.taniarascia.com/static/e41dd6f0f3aeccb88f276085f1508f9e/a0d55/nav2.png)

We're adding the `z-index` property, which affects the z-axis of the element. Since we intend this element to always be completely visible, we give it a `z-index` greater than `0` to ensure it's always "above" any element in our document. As we can see, there's one last issue, which is that the `nav` is overlapping the content. As mentioned previously, you *must* add space (margins) to `static` elements to make space for the `fixed` element. Simply adding a `margin-bottom` to the `nav` won't have any effect.

```html
<nav>nav</nav>

<section>
<div>div</div>
<div>div</div>
</section>
section {
margin-top: 80px;
}
```

[![nav3](https://www.taniarascia.com/static/dc89f59585ed11cbda5417582da73e70/4d3f1/nav3.png)](https://www.taniarascia.com/static/dc89f59585ed11cbda5417582da73e70/a5d5c/nav3.png)

So now we have that all taken care of and `fixed` positioning should make sense.

### Absolute and relative

`absolute` and `relative` positions go hand in hand. Take everything you just learned about `fixed` elements and apply them to `absolute` elements. They behave almost exactly the same: other elements don't know about `absolute` elements, they're affected by the directional properties and `z-index`. The difference is instead of being positioned relative to the viewport (browser window), they're positioned relative to the nearest element that is not `static` - so a `fixed`, `absolute`, or `relative` element.

`relative` elements, on the other hand, behave almost exactly the same as a `static` element - they are part of the document flow, and simply setting `relative` to an element will not change its appearance at all. The difference is a `relative` element *can* use the directional properties - `top`, `left`, `right`, and `bottom`.

However, the most common usage of `relative` and `absolute` is that a `relative` element is treated as `static`, but as an **anchor point** for some other `absolute` element.

I'll make an example with a `section` (red) that has a nested `div` (blue).

```html
<section>
section
<div>div</div>
</section>
```

With no positioning applied, the `div` is contained inside of the `section`.

[![absolute1](https://www.taniarascia.com/static/973437fb2fd3a20a41e6e37a67b4f24f/4d3f1/absolute1.png)](https://www.taniarascia.com/static/973437fb2fd3a20a41e6e37a67b4f24f/a3bc3/absolute1.png)

Now imagine I have a bunch of card elements that are always `100px` tall, regardless of the content contained within, and I want a button to always exist at the same spot on the bottom right. Using `relative` and `absolute`, the `div` will always be in the same spot on any card.

```css
section {
position: relative;
height: 100px;
}

div {
position: absolute;
bottom: 15px;
right: 15px;
}
```

[![absolute2](https://www.taniarascia.com/static/59ad2d1e21bdc78cb2d2852ef0b95d85/4d3f1/absolute2.png)](https://www.taniarascia.com/static/59ad2d1e21bdc78cb2d2852ef0b95d85/e3c01/absolute2.png)

To summarize, use `relative` when you want something else to be anchored to an element but you don't want that element itself to move or be affected at all, and use `absolute` on the element to be anchored. A common usage of this is card-like elements.

This [card element](https://taniarascia.github.io/card/) is an example of absolute coming in handy to make sure they're always the same size but the buttons line up.

[![absolute3](https://www.taniarascia.com/static/3fe8f91943c60678bd9cc4040f942904/4d3f1/absolute3.png)](https://www.taniarascia.com/static/3fe8f91943c60678bd9cc4040f942904/b054d/absolute3.png)

### Positioning Reference

| Position | Behavior | In Document Flow |
| :--------- | :----------------------------------------------------------- | :--------------- |
| `static` | default behavior; elements stack in order and are aware of each other | Yes |
| `relative` | positioned relative to its original position in the flow | Yes |
| `fixed` | positioned relative to the viewport | No |
| `absolute` | positioned relative to closest non-static (`fixed`, `relative`, `absolute`) element | No |


`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more