Hold your position!. We cool? Now, Let's talk about CSS positioning.
One of the things that help you (the developer) to design the layout you planned out for a web project is positioning, where elements will fit on a page and what happens to their surrounding elements.
CSS positioning is quiet a tricky thing and might take you a while to understand (like me). The aim of this post is to explain it in a way that it's easy to comprehend. We'll write code (no doubt about that) and the resulting images in the browser and Developer Tools should help you get a better picture of this entire concept of Positioning.
Positioning in CSS include:
- Static Positioning
- Relative Positioning
- Absolute Positioning
- Fixed Positioning
- Sticky Positioning
From the list above you should know that relative and absolute positioning are the most used positioning techniques and when you find an article or blog post on the internet discussing CSS positioning, they'll mostly talk about these duo.
Before we proceed, i will like to mention that the CSS position
property sets how an element is positioned in a document.
The following HTML and CSS will be used to demonstrate the positioning techniques in this post, please copy and save them with the .html
and .css
extension and make sure the CSS is linked with the HTML.
<div class="parent">
<div class="child"></div>
</div>
/* To be the best of my knowledge, i believe we've discussed
* all the properties in the CSS rules. The only property that
* you may find foreign is the background-color and the color
* format rgb(), we'll talk about them in the series, i think under
* CSS Colors.
*/
.parent {
margin-top: 32px;
margin-right: auto;
margin-left: auto;
margin-bottom: 32px;
background-color: rgb(200,200,200);
width: 500px;
height: 200px;
}
.child {
margin-top: 30px;
margin-right: 20px;
margin-bottom: 50px;
margin-left: 20px;
width: 100px;
height: 100px;
background-color: red;
}
STATIC POSITIONING
This is the default position of most element and they are not affected by offset properties like top
, right
, bottom
or left
.
Load your HTML in your browser, use "Inspect Element" on the red box and navigate to the Box Model (i believe that by now you should be able to do this).
You should get an output similar to the image below, and i have highlighted the position status of the box.
RELATIVE POSITIONING
Before we dive in and explain what relative positioning is all about in CSS, we need to know the meaning of the term relative.
From Lexico dictionary, when we use the term relative it means it's:
Considered in relation or in proportion to something else.
The definition speaks volumes and it's quite the way relative positioning works in CSS.
Relative positioning is the ability to position a page element relative to its parent. This definition might be basic, let's see what the Mozilla Developer Network has to say on this subject (emphasis mine):
A relatively positioned element is an element whose computed*
position
value isrelative
. Thetop
andbottom
properties specify the vertical offset from its normal position; theleft
andright
properties specify the horizontal offset.
This translates to: When you use relative positioning to position an element, the element will be moved from its normal position either vertically or horizontally depending on the properties used.
Update the .child
CSS rule with the following:
.child {
/* Other properties remain the same */
left: 1.2em;
}
The box will now move a little bit to the right of the screen, and if you check the Box Model you will notice that the browser has added some details that indicate that you've positioned the element.
Now let's the move the box a little bit down the screen, we will achieve this by using the top
property. Add this to your .child
CSS rule just below the left
property:
.child {
/* Other properties remain the same */
top: 1.2em;
}
Save and refresh your browser. Navigate to the Box Model and click on the icon beside the word 'relative' in the previous image, this will show you the top
and left
values that the element is using in its new position.
Now let's move the box to the top of its container. This can be achieved with the bottom
property and we can add either right
or left
to show that it moves. Delete the left
and top
values then add the following:
.child {
/* Other properties remain the same */
right: 1.6em;
bottom: 1.4em;
}
Refresh your browser, and click on the icon beside the 'relative' in the Box Model, the coordinates of the box will be shown.
Mind you if you use two properties that move an element in one direction, horizontally or vertically only one value will apply.
For example, if you move an element using both the left
and right
property only the left
property will apply. To see this in action, delete the right
and bottom
properties in the .child
rule then add the following:
.child {
/* Other properties remain the same */
left: 2.5em;
right: 120.6em;
}
Save your file, and refresh your browser, you will realize only the left
property is applied and the box moves in the right direction.
And you can confirm this by clicking the icon beside the word 'relative' in the Box Model.
But, the browser shows your right
property value in the Box Model.
Likewise if you move an element with the top
and bottom
value, only the top
property will apply. If you have the left
and right
property declaration in your CSS, delete them (for now) and update your .child
rule with the following:
.child {
/* Other properties remain the same */
top: 1.2em;
bottom: 2.4em;
}
Save your file and refresh your browser, you will realize the box just moved from the top a little bit. And you can confirm this by clicking the icon beside the word 'relative' in the box model.
This tells us that in order to effectively move a page element we should combine properties that move an element in the vertical—horizontal direction (top
, bottom
with right
or left
) and not vertical—vertcal(top
, bottom
) nor horizontal—horizontal (left
, right
).
Before we proceed, we should talk about offset introduced in the definition of relative positioning taken from Mozilla Developer Network, i will have explained it earlier, but it might complicate things before all the preceding demonstrations and examples. But now, we can talk about it because it'll come in handy in explaining other positioning techniques.
Take a look at the Box model from the image below, you will observe under the position
in the Box Model Properties it reads offset
(in a blue background) and body
, if you hover your mouse over the offset
it says "Offset parent of the selected element" in this case it's the body
element.
If you hover your mouse over the body
element, it will be highlighted on the web page.
This means the element has been positioned relative to the body
element and not its actual parent which is the div
element with the .parent
class.
Why? This is because most element have a default positioning of static
, and offset properties like top
, right
has no effect on element with static
positioning and if you observe carefully our div
element has a position of static
.
So, when we performed relative positioning on .child
, the browser figured out that the div
element had a static positioning and it will default to the body
element. But, what happens if there is no body
element in the document? The browser will add opening and closing body
tags and the positioning will still default to the added body
element.
You can confirm this by commenting the opening and closing body
tag in your HTML.
We can fix this entire situation by making sure our .parent
has a relative positioning. Add the following to the .parent
class:
.parent {
/* Other properties remain the same */
position: relative;
}
Save your file and refresh the browser, you will notice the changes under Box Model Properties.
Now it gets interesting, delete the top
and bottom
properties in the .child
CSS rule then add the following:
.child {
/* Other properties remain the same */
right: 5em;
}
Save and refresh your browser you will realize that the box will move out of its parent container (the div
element).
If you are pleased with this effect, fine by me. But if you want the box to remain within its parent container, add the following to the .parent
.parent{
/* Other properties remain the same */
overflow: auto;
}
The overflow
help controls what will happen when a child element exceeds the boundary of its parent element, in this case we set it to auto
, it accepts other values like scroll
, visible
and hidden
.
Save your file and refresh your browser, use "Inspect Element" on the red box and view the Box Model. Click on the icon beside the word 'relative', you should get an output similar to the image below.
The box is now contained in its parent. The overflow
will come in handy in situations when you want a child element to stick to its parent container. You will see it in action when we explain the CSS Block Formatting Context and in the Final Project.
That's it for relative positioning, let's proceed to absolute positioning
ABSOLUTE POSITIONING
From the Mozilla Developer Network(emphasis mine):
An absolutely positioned element is an element whose computed
position
value isabsolute
orfixed
. Thetop
,right
,bottom
, andleft
properties specify offsets from the edges of the element's containing block. (The containing block is the ancestor relative to which the element is positioned.) If the element has margins, they are added to the offset
The emphasized sentence above is telling us that we can position an element precisely where we want it in its containing block. The containing block can be the element's parent element or the web page itself. Say what?
Here is the thing, absolute positioning is done relative to the first relatively or absolutely positioned parent element and if the parent element is not relatively positioned, it will be positioned related directly to the page itself.
The question now is: How can we relatively position the parent element?
You already know the answer!. By adding the position: relative
to the parent CSS rule. Let's code.
We will be using the same CSS and HTML from previous explanations, but you've got some clean up and modifications to do. Let your CSS and HTML match the snippet below.
<div class="parent">
<div class="child"></div>
</div>
.parent {
margin-top: 32px;
margin-right: auto;
margin-left: auto;
margin-bottom: 32px;
background-color: rgb(200,200,200);
width: 500px;
height: 400px;
position: relative; /* Note this */
}
.child {
width: 120px;
height: 120px;
background-color: #1560bd;
}
Save your files, and view the Box Model of the parent element, you can confirm that it has a relative position.
Add the following to the CSS rule of the .child
:
.child {
/* all other properties remain the same */
position: absolute; /* for absolute positioning */
}
Save your file and confirm it has an absolute position in the Box Model:
Now lets move some stuff. Update the CSS rule of the .child
with the following:
.child {
/* all other properties remain the same */
top: 5em;
left: 15em;
}
This is will move the blue box just across the center of its parent.
Save your file and refresh your browser. View the Box Model and click the icon beside the word 'absolute', the position of the box will be shown.
Let's move the box to another location, delete the top
and left
properties from the .child
CSS rule then add the following:
.child {
/* all other properties remain the same */
bottom: 3em;
left: 2em;
}
Save and refresh your browser then view the position of the box.
Now some exercises for you.
Using combinations of the offset properties (left
, right
,bottom
, top
), write the property declarations that will move the box to the positions depicted in the following images.
EXERCISE 1
EXERCISE 2
EXERCISE 3
Did you figure it out? Show your answer in the comments.
FIXED POSITIONING
The name of this positioning technique should give away its behavior. It allows you to position an element to a fixed spot on the web page.
It's similar to absolute positioning with the exception that the element's containing block is the initial containing block established by the viewport *.
This means when you set the position of an element as fixed
, the parent container is the available browser window. Now you might ask, Why not its parent element? That's how fixed positioning works. Let's code to see what it's all about.
One of the best way to see this positioning in action is to have enough content in a parent container that will allow us to scroll and we'll notice the fixed element does not move with the rest of the parent's content.
Do some house keeping and let your HTML and CSS match the following and don't forget to save your files.
<div class="parent">
<div class="child"></div>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi
ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit
in voluptate velit esse
cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident,
sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit
in voluptate velit esse
cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi
ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit
in voluptate velit esse
cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident,
sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit
in voluptate velit esse
cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
.parent {
width: 500px;
height: 400px;
margin: 2em auto;
background-color: #dddddd;
}
.child {
width: 100px;
height: 100px;
background-color: #1560bd;
}
Refresh your browser. Your output should be similar to the image below.
Next we need to create an environment that will allow us to scroll content of the parent element, we can use the overflow
property to achieve this (we talked aboutoverflow
in relative positioning).
The overflow
property accepts values like auto
, hidden
, scroll
, visible
. The value we'll use is scroll
. Add the following to your .parent
CSS rule:
.parent {
/* All other properties remain the same */
overflow: scroll;
}
Save and refresh. You will notice a scroll bar has been added to the parent container.
If you scroll, everything moves including the box. Let's change that. Add the following to the .child
CSS rule and save your file.
.child {
/* All other properties remain the same */
position: fixed;
}
You will notice that some text are now behind the blue box and if you scroll through the parent, the box does not move.
Now let's give the box its own space to breath. Remember its a child of .parent
, and we can get this space by creating an internal spacing inside the .parent
. Can you guess what this internal spacing is? Its the Padding.
We can create the internal spacing anywhere we desire inside the parent. We'll create this space at the left side. You should get a feeling of the property we'll have to use. The padding-left
with a value that will give the box some space to occupy without interfering with the text.
Add the following to your .parent
class and save your file.
.parent {
/* All other properties remain the same */
padding-left: 150px;
}
The resulting image in the browser:
Now, we need to move the box. Add the following to the.child
.child {
/* All other properties remain the same */
top: 80px;
left: 10px;
}
Save. Refresh your browser and BAM!.
What just happened? Remember:
when you set the position of an element as
fixed
the parent container is the browser window
That's exactly what happened when you positioned the box, its parent is now the browser window or viewport.
The internal spacing we created earlier for the box is still empty because of the box's current position. In order to make the box take up this space, we will have to send the parent to the browser's edge by eliminating its margin
property.
Delete the margin: 2em auto;
from the .parent
. Save and refresh your browser. The parent will move to the left of the screen and the blue box will now occupy the space we created earlier.
When you scroll, the box wont move and it'll appear to be in relation to the .parent
. But we should know it's in relation to the browser window. To prove this is the case, lets add a border to the html
element and the .parent
CSS rule. Your CSS should be similar in structure like the snippets below.
html {
border: 3px solid gold; /* add this */
padding: 1.2em; /* add this */
}
.parent {
/* all prperties remain the same*/
border: 5px solid #ea3c53; /* add this */
}
.child {
/* properties remain unchanged */
}
Save and refresh your browser, view the Box Model and click on the icon beside the word 'fixed', you will notice in the browser window that the coordinate of the box position is touching the window edges which is the html
element and not .parent
If you want to have some fun, perform relative positioning on the .parent
and .child
and save your file. Then perform the normal steps of viewing the box's coordinates in the Box Model, you will notice the coordinate lines are now touching the .parent
and not the html
element.
STICKY POSITIONING
Sticky, sticky, sticky. I think the name is enough to tell you the nature of this positioning technique. Do we need to explain? ....... Fine Let's explain.
Mozilla Developer Network explains (emphasis mine):
Sticky positioning can be thought of as a hybrid of relative and fixed positioning. A stickily positioned element is treated as relatively positioned until it crosses a specified threshold, at which point it is treated as fixed until it reaches the boundary of its parent
There you go, i think that's straight forward but let's code.
We'll be using the previous HTML with a slight modification.
<!-- Add this before <div class="child"></div> -->
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed
do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<!-- other content remains unchanged -->
And new CSS rules.
.parent {
width: 500px;
height: 400px;
margin: 2em auto;
background-color: #dddddd;
position: relative; /* relatively positioned the element */
}
.child {
width: 100px;
height: 100px;
background-color: #1560bd;
}
Save your file and refresh your browser.
Next we have to enable scrolling on the .parent
, so that we can see the effect of the sticky position when it's applied.
Update your .parent
with the following
.parent {
/* All other properties remains the same */
overflow: scroll; /* to enable scrolling */
}
Save your file and refresh your browser. This should enable scrolling in the .parent
.
Next, we'll make the .child
sticky. Add the following to your .child
:
.child {
/* All other properties remains the same */
position: sticky; /* make it sticky */
}
Save your file and refresh your browser. When you scroll you'll notice the box will still move out of view.
Why is this happening? MDN to the rescue:
You must specify a threshold with at least one of
top
,right
,bottom
, orleft
for sticky positioning to behave as expected. Otherwise, it will be indistinguishable from relative positioning.
This is telling us that after giving an element the position: sticky;
we must specify an offset
for it work, otherwise it'll behave the same like a relatively positioned element. Let's fix that.
Add the following to your .child
CSS rules:
.child {
/* All other properties remains the same */
top: 50px; /* this will move the box down the screen by 50px */
}
Save your file and refresh your browser. If you scroll through .parent
, when you get to the blue box , it won't scroll out of view. It'll appear to snap out of its position and then fixed.
For accessibility reason ensure that elements positioned with an absolute
or fixed
value do not obscure other content when the page is zoomed to increase text size. Say what? This and more will be discussed in Web Accessibility and Usability.
You should note that when you use absolute or relative positioning a stacking context is created when the value of the z-index
is not auto
. But fixed positioning always creates a new stacking context.
There are two questions that may arise from this last statement. They are:
- What is a stacking context?
- What is a
z-index
?
Both questions will be answered in the next topic. The CSS z-index.
Top comments (1)
Excelent explain....!