DEV Community

Habdul Hazeez
Habdul Hazeez

Posted on • Updated on

CSS Positioning

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.

Search Result for CSS positioning on Google.com

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>
Enter fullscreen mode Exit fullscreen mode
/* 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;
}
Enter fullscreen mode Exit fullscreen mode
Margin Collapsing will occur with this code, can you see it?

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.

Static positioning in CSS

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 is relative. The top and bottom properties specify the vertical offset from its normal position; the left and right properties specify the horizontal offset.

*The computed value of a CSS property is the value that is transferred from parent to child during inheritance. We've talked about css inheritance.

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;
}
Enter fullscreen mode Exit fullscreen mode

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.

Positioned Element in CSS

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;
}
Enter fullscreen mode Exit fullscreen mode

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.

A page element positioned with CSS top and left properties

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;
}
Enter fullscreen mode Exit fullscreen mode

Refresh your browser, and click on the icon beside the 'relative' in the Box Model, the coordinates of the box will be shown.

Coordinates of a Page Element positioned with CSS

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;
}
Enter fullscreen mode Exit fullscreen mode

Save your file, and refresh your browser, you will realize only the left property is applied and the box moves in the right direction.

Page element moved in the right direction with CSS positioning

And you can confirm this by clicking the icon beside the word 'relative' in the Box Model.

The effect of CSS left property on a page element

But, the browser shows your right property value in the Box Model.

The value of the CSS right property shown 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;
}
Enter fullscreen mode Exit fullscreen mode

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.

A page element moved from the top of its parent with CSS

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.

The Box model showing the offset parent of a selected element

If you hover your mouse over the body element, it will be highlighted on the web page.

HTML body element highlighted on a web page with Developer Tools

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.

HTML div element with static positioning

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.

The web browser adding the HTML body element

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;
}
Enter fullscreen mode Exit fullscreen mode

Save your file and refresh the browser, you will notice the changes under Box Model Properties.

An element with relative positioning

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;
}
Enter fullscreen mode Exit fullscreen mode

Save and refresh your browser you will realize that the box will move out of its parent container (the div element).

A page element moved out of its parent container

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;
}
Enter fullscreen mode Exit fullscreen mode

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.

A child element contained within its parent element using CSS overflow property

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 is absolute or fixed. The top, right, bottom, and left 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>
Enter fullscreen mode Exit fullscreen mode
.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;
}
Enter fullscreen mode Exit fullscreen mode

Save your files, and view the Box Model of the parent element, you can confirm that it has a relative position.

A relative positioned element

Add the following to the CSS rule of the .child:

.child {
  /* all other properties remain the same */

  position: absolute; /* for absolute positioning */
}
Enter fullscreen mode Exit fullscreen mode

Save your file and confirm it has an absolute position in the Box Model:

An HTML element positioned with CSS absolute property value

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;
}
Enter fullscreen mode Exit fullscreen mode

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.

A positioned element with the absolute property value

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;
}
Enter fullscreen mode Exit fullscreen mode

Save and refresh your browser then view the position of the box.

A positioned element with the absolute property value

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

A positioned element with the absolute property value

EXERCISE 2

A positioned element with the absolute property value

EXERCISE 3

A positioned element with the absolute property value

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 *.

*The viewport is basically the available browser window.

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>
Enter fullscreen mode Exit fullscreen mode
.parent {
  width: 500px;
  height: 400px;
  margin: 2em auto;
  background-color: #dddddd;
}

.child {
  width: 100px;
  height: 100px;
  background-color: #1560bd;
}
Enter fullscreen mode Exit fullscreen mode

Refresh your browser. Your output should be similar to the image below.

fixed positioning in CSS

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;
}
Enter fullscreen mode Exit fullscreen mode

Save and refresh. You will notice a scroll bar has been added to the parent container.

Scroll bar added to an element by the browser

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;
}
Enter fullscreen mode Exit fullscreen mode

You will notice that some text are now behind the blue box and if you scroll through the parent, the box does not move.

Fixed positioning in CSS

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;
}
Enter fullscreen mode Exit fullscreen mode

The resulting image in the browser:

Padding-left applied to an element

Now, we need to move the box. Add the following to the.child

.child {
  /* All other properties remain the same */

  top: 80px;
  left: 10px;
}
Enter fullscreen mode Exit fullscreen mode

Save. Refresh your browser and BAM!.

An element moving out of its parent container

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.

A fixed element on a web page

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 */
}
Enter fullscreen mode Exit fullscreen mode

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

HTML elements with border applied

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.

HTMl elements with border applied

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 -->

Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

Save your file and refresh your browser.

A blue box and some text on a silver background

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 */
}
Enter fullscreen mode Exit fullscreen mode

Save your file and refresh your browser. This should enable scrolling in the .parent.

A page element with scroll bars

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 */
}
Enter fullscreen mode Exit fullscreen mode

Save your file and refresh your browser. When you scroll you'll notice the box will still move out of view.

A box moved out view in its parent element

Why is this happening? MDN to the rescue:

You must specify a threshold with at least one of top,right, bottom, or left 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 */
}
Enter fullscreen mode Exit fullscreen mode

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.

A sticky page element

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)

Collapse
 
hasananamul profile image
hasananamul

Excelent explain....!