facebook twitter
Webucator's Free Introduction to CSS Tutorial

Lesson: Positioning

Welcome to our free Introduction to CSS tutorial. This tutorial is based on Webucator's Introduction to CSS Training course.

In this lesson, you will learn about positioning.

Lesson Goals

  • Understand Normal Flow.
  • Work with the position, top, bottom, left, and right properties.
  • Work with the z-index property.
  • Work with the float and clear properties.

Normal Flow

The flow is the way in which elements are laid out and the normal flow is the way in which elements are laid out by default:

  1. Elements appear on the page in the same order they appear in the code.
  2. Block elements appear on separate lines in single columns.
  3. Top and bottom margins collapse between block elements, so two block elements on top of each other will be separated by the margin of the element with the larger margin and not the combined margin of both elements.
  4. Inline elements appear on the same line adjacent to each other and any text as long as there is space. If there isn't space, they will wrap down to the next line.

A demo illustrating normal flow is shown below:

Code Sample:

Positioning/Demos/normal-flow.html
---- C O D E   O M I T T E D ----

<style>
  .block {
    background: lightblue;
    border: solid black;
    margin: 1rem;
    padding: 0.5rem;
  }

  .inline {
    background: pink;
    border: solid black;
    padding: 0.1rem;
  }
</style>
<title>Normal Flow</title>
</head>
<body class="webucator">
<h1>Normal Flow</h1>
<main>
  <div class="block">
    This is a div element, a standard block element.
  </div>
  <p class="block">
    This is a paragraph element, 
    another block element, that contains a 
    <span class="inline">
      span element, which is a standard inline element
    </span>.
  </p>
  <div class="block"> 
    This is a div element that contains a paragraph element.
      <p class="block">
        This is a paragraph element that contains two 
        <span class="inline">span</span>
        <span class="inline">elements</span>. 
        It also contains a lot more content 
        like these fake sentences: 
        Lorem ipsum dolor 
        sit amet, consectetur adipiscing elit. 
        Curabitur tristique odio ac sem congue luctus.
      </p>
  </div>
</main>
</body>
</html>

Code Explanation

The code above will render the following:Normal Flow

With CSS, we can move elements into a separate flow. This allows us more control over the design and layout of our pages. Throughout this lesson, we will be looking at the different ways we can do this.

position

The position property determines how an element is positioned. It takes the following values:

  1. static - The default value. The element is part of the normal flow.
  2. relative - The element remains in the normal flow, but is positioned relative to its default position in the normal flow.
  3. absolute - The element is removed from the normal flow and no space is left for it in the page layout, and as a result it does not affect the flow of the elements around it. It is positioned relative to its closest positioned ancestor*. If it has no positioned ancestor, it is positioned relative to the document body.
  4. fixed - The element is removed from the normal flow and no space is left for it in the page layout, and as a result it does not affect the flow of the elements around it. It is positioned relative to the viewport, meaning that even when the page scrolls, it will stay in the same place.

*A positioned element is an element with any position value other than static.

Positioning with top, bottom, left, and right

top, bottom, left, and right are used to position non-static elements by setting offsets. They all take the following properties:

  1. auto - the element is positioned where it would be if it were positioned statically.
  2. A length value in units (e.g., 1em) that specifies the offset distance for that respective edge.
  3. A percentage value of the container element's width or height (depending on whether the property is a vertical or horizontal edge).

Some important distinctions in how these properties work with the different position values:

  1. For absolutely positioned elements, the edges are defined by the edges of the padding of the closest positioned parent.
  2. For relatively positioned elements, the edges are defined by the edges of the content of the element itself.
  3. For fixed positioned elements, the containing element is always the viewport and the edges are defined by the edges of the viewport.

Using top, bottom, left, and right

When using these properties to position elements, you can set either top or bottom, but not both, and you can set either left or right, but not both.

Valid combinations are top and left, top and right, bottom and left, and bottom and right.

The following demo shows some examples of positioning:

Code Sample:

Positioning/Demos/position-styles.css
body {
  border: 1px dotted black;  
}

section {
  border: 1px solid black;
  margin: 2rem;
  position: relative;
}

div {
  background: rgba(0, 0, 255, 0.5);
  border: 1px dashed black;
  height: 25px;
  margin: auto;
  width: 75px;
  top: 75px;
  left: 75px;
}

.relative {
  background: rgba(255, 0, 0, 0.5);
  position: relative;
}

.absolute {
  background: rgba(0, 255, 0, 0.5);
  position: absolute;
}

.fixed {
  background: rgba(255, 255, 0, 0.5);
  position: fixed;
}

Code Sample:

Positioning/Demos/position.html
---- C O D E   O M I T T E D ----
<body class="webucator">
<h1>position</h1>
<section>
  <h2>relative</h2>
  <div>Static</div>
  <div class="relative">Relative</div>
  <div>Static</div>
</section>
<section>
  <h2>absolute</h2>
  <div>Static</div>
  <div class="absolute">Absolute</div>
  <div>Static</div>
</section>
<section>
  <h2>fixed</h2>
  <div>Static</div>
  <div class="fixed">Fixed</div>
  <div>Static</div>
</section>
</body>
</html>

Code Explanation

The screenshot below shows how this code will render. The dashed arrows show the top and left offsets.position Demo

Note that the fixed div will always stay in the top-right corner even if the page scrolls. Also note that the absolute and fixed divs get removed from the normal flow, such that the subsequent divs don't make space for it. The relative div remains in the normal flow, so subsequent divs act as if it were where it would have been if it were static.

z-index

The z-index property is used to specify the stacking order of positioned elements. It takes the following values:

  1. auto - the default. Elements that are later siblings sit on top of their earlier siblings if they are positioned to overlap.
  2. A positive or negative integer. The higher the integer, the higher an element is in the stacking order of its siblings.

The following demo shows some examples of z-index:

Code Sample:

Positioning/Demos/z-index-styles.css
nav {
  background: lightgray;
  border: 1px solid black;
  border-radius: 0.5rem;
  width: 300px;
}

section {
  background: rgba(211, 211, 211, 0.8);
  border: 1px solid black;
  position: relative;
  height: 200px;
  width: 300px;
}

.top-section {
  z-index: 3;
}

.middle-section {
  top: -3rem;
  z-index: 2;
}

.bottom-section {
  top: -20rem;
  left: 10rem;
  z-index: 1;
}

div {
  background: rgba(128, 128, 128, 0.8);
  border: 1px solid black;
  height: 100px;
  position: absolute;
  width: 100px;
}

.top-div {
  left: 1rem;
  top: 2rem;
  z-index: 3;
}

.middle-div {
  left: 4rem;
  top: 3.5rem;
  z-index: 2;
}

.bottom-div {
  left: 8rem;
  top: 5rem;
  z-index: 1;
}

:target {
  /* Set z-index of targeted element to 100 */
  z-index: 100;
}

/* Add text to targeted element */
:target::after {
  content: "(z-index: 100)"
}
            

Code Sample:

Positioning/Demos/z-index.html
---- C O D E   O M I T T E D ----
<body class="webucator">
<h1>z-index</h1>
<nav>
  <ol>
    <li><a href="#section1">Section 1</a>
      <ol>
        <li><a href="#div1">Div 1</a></li>
        <li><a href="#div2">Div 2</a></li>
        <li><a href="#div3">Div 3</a></li>
      </ol>
    </li>
    <li><a href="#section2">Section 2</a>
    </li>
    <li><a href="#section3">Section 3</a>
    </li>
  </ol>
</nav>
<hr>
<section id="section1" class="top-section">
  Section 1
  <div id="div1" class="top-div">
    Div 1
  </div>
  <div id="div2" class="middle-div">
    Div 2
  </div>
  <div id="div3" class="bottom-div">
    Div 3
  </div>
</section>
<section id="section2" class="middle-section">
  Section 2
</section>
<section id="section3" class="bottom-section">
  Section 3
</section>
</body>
</html>

Code Explanation

The code above will render the following:z-index Demo

Open Positioning/Demos/z-index.html in the browser and click on some of the links at the top. You'll notice that the targeted element always rises to the top. That's because targeted elements get a z-index of 100.

Try setting the background color of the targeted element to red in the CSS to see this change even more pronounced:

:target {
  /* Set z-index of targeted element to 100 */
  z-index: 100;
  background-color: red;
}

float and clear

float

The float property places block elements to the left or right of their containing elements. It takes the following values:

  1. none - The default value. The element is not floated:No Float
  2. left - The element is floated to the left in its containing element:Float Left
  3. right - The element is floated to the right in its containing element:Float Right

Floated elements are taken out of normal flow, but they continue to occupy space in the page layout, unlike absolutely positioned elements.

All these examples can be seen in Positioning/Demos/float.html and Positioning/Demos/float-styles.css.

Open Positioning/Demos/float.html in the browserand click on some of the links at the top to change the float values.

clear

The clear property is used to force elements to move below floated elements. It takes the following values:

  1. none - The default value. The element is not cleared:No Clear
  2. left - The element is forced below all elements floated left in its containing element:Clear Left
  3. right - The element is forced below all elements floated right in its containing element:Clear Right
  4. both - The element is forced below all floated elements in its containing element:Clear Both

These examples can be seen in Positioning/Demos/clear.html and Positioning/Demos/clear-styles.css.

Open Positioning/Demos/clear.html in the browser and click on the links at the top to change the clear values.

Layouts with float and clear

Before the development of more sophisticated CSS layout systems, float and clear were used to create entire website layouts, but this is no longer recommended.

float, clear, and ::after

Sometimes the floated element is so big that when it is taken out of the flow, it extends beyond the height (which adjusts automatically for its content in normal flow) of its containing element. To fix this, it is possible to give the height a fixed value (e.g., 400px), but this is not great for fluid pages with containers that may shrink and grow depending on the width. The solution is to use the ::after pseudo-element in combination with the clear property.

The syntax is:

Syntax

container::after {
  content: "";
  clear: both;
  display: block;
}

This adds a cleared block pseudo-element at the end of the container element. We use an empty string ("") because we don't want the pseudo-element to be visible to the user. The cleared pseudo-element must stay below any floated elements, so it keeps the height of container from becoming smaller than the floated element. See the demo below for an example:

Code Sample:

Positioning/Demos/float-clear-after.html
---- C O D E   O M I T T E D ----

<style>
  article {
    border: 1px solid black;
    margin: 0.5rem;
    padding: 0.5rem;
  }

  #article1 img {
    float: right;
  }

  #article2 img {
    float: left;
  }

  #article2::after {
    content: "";
    clear: both;
    display: block;
  }
</style>
<title>float, clear, and ::after</title>
</head>
<body class="webucator">
<h1>float, clear, and ::after</h1>
<main>
  <article id="article1" class="top-article">
    <img alt="Marathon" src="images/marathon.jpg">
    <p>Lorem ipsum dolor 
      sit amet, consectetur adipiscing elit. .
      Curabitur tristique odio ac sem congue luctus.
      Praesent vel rutrum lectus. 
      Nam mattis finibus odio. 
      <p>Suspendisse ligula orci, 
      ullamcorper vitae nulla nec, tempor auctor felis. 
      Sed eu luctus sem...</p>
  </article>
  <article id="article2" class="middle-article">
    <img alt="Marathon" src="images/marathon.jpg">
    <p>Lorem ipsum dolor 
      sit amet, consectetur adipiscing elit. .
      Curabitur tristique odio ac sem congue luctus.
      Praesent vel rutrum lectus.
      Nam mattis finibus odio. 
      <p>Suspendisse ligula orci, 
      ullamcorper vitae nulla nec, tempor auctor felis. 
      Sed eu luctus sem...</p>
  </article>
</main>
</body>
</html>

Code Explanation

The code above will render the following:float, clear, ::after Demo

Some things to note:

  1. The first article element adjusts only for the text and not for the floated image. This allows the image to extend past its container and interfere with the rest of the layout.
  2. The second article element has a cleared pseudo-element added at the end of it, so the second article extends all the way to the bottom of the image.

In the following image, we added text and a border to the pseudo-element, so that you can see that it is really there: float, clear ::after with border Demo

Positioning

Duration: 25 to 40 minutes.

In this exercise, you will position elements in a page called Running Blog that is linked to from Runners Home (from the read-more links in the articles).

  1. Open Positioning/Exercises/running-blog.html in your editor. Because this is a new file that you haven't seen before, take some time to go through the HTML to familiarize yourself with the structure. Also note that you have several new images available in the images folder: runner2.png and runner2-tiny.png
  2. Open Positioning/Exercises/blog-styles.css. This is a stylesheet we created for Running Blog. Because this is a new stylesheet that you haven't seen before, take some time to go through the styles that already exist. This will help you when it comes time to add your own styles.
  3. Use your new knowledge of positioning to add some styles to this page. The object of this exercise is to practice using the properties covered in this lesson. Also, feel free to add or change any other properties that you know.
  4. When you are done, open running-blog.html in your browser to see the results. You are welcome to go back to the code and continue to work.

You can design it however you like, or you can try to make it look something like: Positioning Solution Positioning Solution

Solution:

Positioning/Solutions/blog-styles.css
html {
  font-size: 16px;
}

body {
  background: aliceblue;
}

header {
  margin: auto;
  min-width: 500px;
  width: 80%;
}

#title {
  margin: auto;
  width: 90%;
}

header h1 {
  margin: auto;
  width: 220px;
}

header p {
  margin: auto;
  width: 400px;
}

header nav {
  border-radius: 0.4rem;
  margin: 0.5rem auto;
  padding: 0.2rem 1rem;
  width: 140px;
}

nav, 
nav ul,
nav ol {
  margin: 0;
}

a, a:visited {
  color: blue;
  text-decoration: none;
}

a:hover {
  color: purple;
}

a:active {
  color: red;
}

main {
  background: white;
  margin: 1rem auto 8rem;
  min-width: 500px;
  padding: 1rem;
  width: 80%;
}

main nav {
  background: lightgray;
  border-radius: 0.5rem;
  margin-bottom: 1rem;
  padding: 0.5rem;
}

section {
  border-top: 0.2rem solid black;
  padding: 1%;
  width: 98%;
}

article {
  border: 1px solid black;
  margin: 1rem auto;
  padding: 0 0.5rem;
  width: 96%;
}

article:target h3 {
  text-decoration: underline;
}

article img {
  float: right;
  margin: 0.5rem 0 0.5rem 0.2rem;
}

article p:last-child::after {
  content: "";
  display: block;
  clear: both;
}

a.back-to-top {
  background: rgb(158, 170, 202);
  border: rgb(70, 70, 100);
  border-radius: 0.5rem;
  border-style: none solid solid none;
  border-width: 0 0.2rem 0.2rem 0;
  color: navy;
  display: block;
  float: right;
  font-size: 1rem;
  height: 20px;
  margin: 0.2rem 0.2rem 0.2rem 0.5rem;
  padding: 0.2rem;
  text-decoration: none;
  text-align: center;
  width: 90px;
}

section::after {
  content: "";
  display: block;
  clear: both;
}

a.back-to-top:active {
  color:#cce;
  border-width: 0 0.1rem 0.1rem 0;
}

#all article {
  background: #cce;
  height: 30px;
  margin: 0.5rem 0;
  overflow: hidden;
  padding-bottom: 15px;
  width: 75px;
}

#all article:target {
  background: white;
  height: auto;
  width: 80%;
}

#all article:target h3 a {
  color: black;
}

footer {
  background: lightgray;
  font-size: medium;
  font-style: italic;
  min-width: 640px;
  width: 100%;
  margin: 0 -1rem;
  padding: 0.2rem 1rem;
  position: fixed;
  bottom: 0;
}

footer h2 {
  margin: 0;
}

footer a {
  text-decoration: underline;
  margin: 0.4rem;
}

a[href^='mailto'] {
  margin: 0;
}
            

Code Explanation

Note that the footer is fixed, which is why it is in both screenshots.