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
What does the
positionproperty do? How do the values
absoluterelate 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.
position property specifies the positioning method applied to an element. The additional
bottom properties determine the final display.
There are 5 possible values:
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,
left do not effect an element that is positioned statically.
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.
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 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:
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:
And the CSS:
border: 1px solid red;
border: 1px solid purple;
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.
We achieved this by adding one line to the CSS:
border: 1px solid red;
border: 1px solid purple;
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
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
filter property set to anything but the default of
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.