Introduction to CSS Positioning
Mastering CSS layout design is a coveted goal and worthy of pursuit. While flex and grid techniques are used for overall page layouts, positioning is used to manage and fine tune the position of specific elements on a page to create interesting effects.
The CSS position property gives you a set of tools to precisely control the displayed position of individual elements, thus overriding the default positioning created by the normal layout flow.
Normal flow describes how a browser displays an html page when no additional CSS layout properties have been added. For example, the browser will render elements in the same order that they are written in an HTML document from top to bottom based on the element’s default display type (block or inline) and based on the reading direction or Writing Mode of the language used.
For example, consider the following HTML
and screenshot below.
<body>
<div class="container">
<div class="box" id="box1">Box 1</div>
<div class="box" id="box2">Box 2</div>
<div class="box" id="box3">Box 3</div>
</div>
</body>
You can see that the three boxes, which are created using <div> elements are stacked vertically in the same order that they are written in the HTML. We can use the position property to modify the default positioning by adding it to the element’s CSS selector along with one of the values below.
Static — This is the default positioning, which just means the element will be positioned as part of the normal document flow.
Relative — A relatively positioned element will initially be placed in its default location in the document flow and then can be offset, relative to its normal position using the top, bottom, left and right properties.
Absolute — An absolutely positioned element will be removed from the default document flow and positioned relative to its first positioned ancestor (which means a parent container that has a position set to something other than ‘static’). If there are no positioned ancestors it will be positioned relative to the viewport again using the top, bottom, right and left properties.
Fixed — A fixed element will remain fixed relative to the viewport and will not be affected by page scroll. This effect might be used to fix a navigation bar to the top of the screen, for example.
Sticky — A sticky positioned element is kind of a cross between relative and absolute. It will behave like a relatively positioned element while scrolling until it hits a defined point relative to the viewport and then will become fixed to that location.
Let’s go back to the original example to see how these values work.
Here is the corresponding CSS. (*Note — In these examples, I am using the pixel unit for simplicity but it is a good practice to use relative units such as rem in production)
/* CSS 'container' class */
.container {
border: 4px solid black;
width: 50%;
margin-top: 50px;
}
/* CSS 'box' class */
.box {
width: 200px;
height: 200px;
font-size: 40px;
}
/* CSS id='box2' (box1 and box3 are the same except for the border color) */
#box2 { border: 4px solid blue; }
Let’s modify the CSS for #box2 by adding position:relative; and a top and left offset to see what happens.
#box2 {
border: 4px solid blue;
position: relative;
top : 20px;
left: 20px;
}
The first thing to notice is how the top and left properties are rendered when using the relative position. It can be a little confusing as the box has been moved down and to the right. You might think of it as pushing the top down 20px and pushing the left side of the box 20px.
Also notice that even though Box 2 has moved relative to its default position, the original space for box 2 remains meaning that box 2 is still part of the document flow. Understanding this aspect of relative positioning is an important consideration when choosing relative as opposed to absolute positioning.
Now try changing the position for box 2 to absolute but leave the top and left properties the same.
#box2 {
border: 4px solid blue;
position: absolute;
top: 20px;
left: 20px;
}
The first thing to notice is that the positioning is relative to the viewport and not the parent container. In this case, the top and left properties are behaving differently as well. Box 2 is positioned 20px from the top of the viewport and 20px from the left edge of the viewport.
The reason that box 2 is using the viewport, if you remember, is because when using absolute positioning, the element is positioned relative to the first non-statically positioned parent. In this case, the parent container is not using the position property so is still statically positioned by default.
Try changing the position of the container to relative to see what happens.
.container {
border: 4px solid black;
width: 50%;
margin-top: 50px;
position: relative;
}
Now that the parent container is no longer statically positioned, Box 2 is now absolutely positioned relative to the parent container — 20px from the top and 20px from the left edge of the parent container.
The other important thing to notice is that the space where Box 2 would normally be is now gone. The reason for this is that when you give an element absolute positioning it is pulled from the normal document flow and is now on its own layer independent from the other elements on the page.
Let’s change box 2 to fixed positioning.
#box2 {
border: 4px solid blue;
position: fixed;
top: 20px;
left: 20px;
}
To better illustrate the effect. I have added 3 more boxes to the html and css.
In the screenshot, I have scrolled down to the bottom of the page. You can see that Box 2 is still fixed in position, 20px from the top and 20px from the left edge of the viewport while the other boxes scroll underneath.
The last position value is sticky. When the sticky position value is selected, as mentioned above, the element will behave like a relatively positioned element until it hits a defined point relative to the viewport and then will become fixed to that location. One thing to note is that the vertical offset will not be visible until you scroll to that point.
#box2 {
border: 4px solid blue;
position: sticky;
top 20px;
left: 20px;
}
The purpose of this introduction was to give you a starting place for further exploration. The best way to master these techniques is to create some examples of your own and play with the settings and consider how you might use these ideas in your projects.