close
Skip to content
Explainers logo Explainers for Devs Helping you build a better Web

CSS Positioning

Relative and absolute positioning

CSS positioning often seems like the most obvious solution to positioning elements on a web page, but the implementation is not intuitive, it often causes frustration, and there are usually better solutions.

Reading time:
4 minutes
On this page

Introduction

This code example is designed to illustrate how CSS positioning works. Initially, it might seem that positioning is the best way to locate elements within the viewport, but there is usually a better, more robust method. It’s important to realise that when you use positioning, you are breaking the natural flow of content, and that often causes other problems later in the design process.

1
2
3
4

Set the position value on #container

The block formatting context

Positioning with CSS is often misunderstood. The key is to understand what’s known as the “block formatting context” and how it can be changed. An appreciation of context has become more important recently with the addition of CSS Grid and CSS Flexbox to the specification. For example, to cause a container to act as a grid container, we change the context to “grid”, using the declaration display: grid;. Similarly, we can cause a container to act as a flexbox container using display: flex;. Once we have done this, any children of that container will behave acording to the defined context.

Positioning is slightly different. We don’t use the display property to change the context, we use the position property, but the effect is the same. To cause a parent container to act as the local context for absolutely positioned children, we use the declaration, position: relative; on that container.

Having done that, each child element that is to be positioned must include the declaration, position: absolute; along with one or more declarations that detail the actual position of the child element.

For example, the arrangement of elements (circles) above is achieved using the CSS below:


#container {
    position: relative; /* sets the context for child elements */
    height: 280px;
    width: 280px;
    border: 3px dotted #777;
    margin: 50px auto;
}
#container div {
    position: absolute; /* with respect to the parent element */
    height: 120px;
    width: 120px;
    border-radius: 50%;
}
#container div:nth-child(1) {
    background-color: #758;
    top: 0;
    left: 0;
}
#container div:nth-child(2) {
    background-color: #246;
    top: 0;
    right: 0;
}
#container div:nth-child(3) {
    background-color: #932;
    bottom: 0;
    left: 0;
}
#container div:nth-child(4) {
    background-color: #893;
    bottom: 0;
    right: 0;
}
			    
Code block 1

The markup is just four child <div> elements nested within a parent <div> container. We’re using the nth-child selector to style each of the four circles differently.


<div id="container">
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
</div> <!-- close #container -->
			    
Code block 2

What happens if we don’t set a context for positioning?

The default position value for all elements is static and the block formatting context for all child elements whose parents are static is the viewport. If no parent context is set, the position “top left”, means the top left-hand corner of the viewport.

In the example above, if we were to change the position value of #container to static, the circles would be positioned in the corners of the viewport.

The circles have no parent context and so they break out of the parent container and position themselves acording to the default context, the viewport. Click on the buttons to test this principle.

Further reading

For more on this topic, read/view:

Top of page Top of page icon