What exactly does the CSS position property do?

Photo by Halacious on Unsplash

Styling is one of my favorite parts of being a developer — I love seeing a page transform with some changes to typography, color scheme or positioning. How we choose to layout a page has a significant impact on the user, and their likelihood to stick around.

One of the first questions added to my ‘All Points Bulletin Board’ (where I keep all of my in-the-moment development questions) related to vanilla CSS, specifically the position property:

What does the position property do? How do the values relative and absolute relate to each other?

There are a range of ways to control the layout of a page — we can use float layouts, flexbox layouts, grid layouts and pure positioning. Usually a finished page has a little bit of everything, being familiar with the basics can be a powerful tool when trying to figure out why an element (or a group of elements) isn’t behaving how you expected.

The CSS position property specifies the positioning method applied to an element. The additional top, left, right, and bottom properties determine the final display.

There are 5 possible values:

  • Static

Position: Static

By default, a web page and its elements are displayed in static position. The elements appear in the viewport according to the document flow and the writing method of the browser. Some browsers display left-to-right, right-to-left, or vertically down the page depending on your country and language. A page without CSS to explicitly change the ordering or positioning of elements is said to be in Normal Flow.

When a page is in Normal Flow, elements are displayed one after another in block dimension. When the user scrolls the page, the elements scroll with it. The other positional properties, top, bottom, right, and left do not effect an element that is positioned statically.

Position: Relative

Whenever an object is moved from its static position in a layout, it’s moved based on a reference. In an element with position: relative applied, it is positioned relative to where it would be in Normal Flow.

The top, bottom, right, and left properties move the element relative to where it would be. Keep in mind the normal space the element takes in Normal Flow is reserved, and surrounding elements will not shift to fit or fill the gap.

Position: Absolute

Setting position: absolute on an element removes it and the space it would normally take from the document flow entirely. The element is then positioned relative to its containing block - which is either a positioned ancestor (a parent element whose position is anything but static), or the browser viewport itself, if such a parent doesn’t exist.

Most of the the time we don’t want to use the viewport as the reference (and when we do it’s easier and better practice to use position: fixed as we’ll see in a moment), so we need to make sure a parent element has a position other than static. Let’s look at a short example:

Parent in default `static` position & Child in `absolute` position

In this example the parent element, the orange-red box, is in Normal Flow. The child div has position: absolute applied, and is then moved 50 pixels from the top and 50% to the left of the viewport.

The html looks like this:

<body>
<div class="parent">
<p>Parent</p>
<div class="child">
<p>Child</p>
</div>
</div>
</body>

And the CSS:

.parent {
height: 150px;
width: 150px;
background-color: orangered;
border: 1px solid red;
text-align: center;
}
.child {
position: absolute;
top: 50px;
left: 50%;
background-color: white;
border: 1px solid purple;
margin: 10px;
}

Instead, we want the child div positioned according to its parent. The simplest way to do that is to add position: relative on the parent div.

Once the child div has a positioned ancestor it will have a new point of reference. Now it is 50 pixels from the top, and 50% to the left of where it would be in its parent.

Parent in `relative` position & Child in `absolute` position

We achieved this by adding one line to the CSS:

.parent {
position: relative;
height: 150px;
width: 150px;
background-color: orangered;
border: 1px solid red;
text-align: center;
}
.child {
position: absolute;
top: 50px;
left: 50%;
background-color: white;
border: 1px solid purple;
margin: 10px;
}

Position: Fixed

If an element should be positioned according to the viewport, we can use fixed positioning. Like with absolute positioning, an element with position: fixed applied will be completely removed from the document flow.

The other positional properties top, bottom, right, and left then need to be used to properly display the element. Fixed elements will scroll with the user, staying where they are.

It is possible to set the position of a fixed element to something other than the viewport (though it’s not considered best practice). To change the point of reference on a fixed element, a containing parent must have the perspective, transform, or filter property set to anything but the default of none.

Position: Sticky

The final position value we have to talk about is sticky. A sticky element works a bit differently than what we’ve seen so far. Its actual position value toggles between relative and fixed, depending on the user’s scroll position.

The element will appear in normal flow (position: relative) until the user scrolls to a certain point in relation to the viewport. Then the element sticks to a given point and scrolls with the user, like a fixed object.

The sticky value is newer, and because of that it sees less support across browsers. Don’t worry too much about that though, the element will revert to fixed position and scroll with the user in the case that the sticky method isn’t supported.

A Word on Normal Flow

Good document structure is key part of web design, especially accessibility-first minded design. A well structured html document is crucial for the users that rely on screen readers and will never see the CSS, and is just as important for those that do.

Normal Flow is based on how readers naturally traverse content. If an element needs to be moved relatively far from where it would appear in Normal Flow, perhaps you should consider adjusting its position in the document instead.

Being familiar with these foundational properties can save invaluable time when designing layouts and debugging. If you want to take a look at an example of all the different position values in use, check out this Codepen. Play with the values and see what each of them does, and how the effects stack.

Resources

I’m Ash, a developer with a passion for web design, accessibility, and learning!

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store