Tutorial: Four CSS Layout Modes and Their Use Cases

Lara Aigmüller

As somebody who started building websites when table-based layouts and framesets were cool (and the only option we had), I’m more than happy about using modern and powerful CSS layout algorithms like flexible box layout and grid layout today. We’ve already had a look at both in previous tutorial articles when building a responsive navigation using flexbox and a responsive form layout.

While it sounds great to use these two layout methods basically everywhere because they are super flexible and provide solutions for a lot of layout problems, there are still use cases where other algorithms are better suited for the job.

Let’s dig in! 💪

CSS layout algorithms

When I started learning CSS, I never thought about the concept of having different layout algorithms. I just added some properties here and there and hoped that, somehow, my layouts would eventually turn out to look as expected. 🙃

Years went by and after some time, a lot of frustration, and bug fixing, I realized that understanding the differences and strengths of each layout algorithm would help me build more robust layouts with less code.

In CSS, there are 7 different layout algorithms we can use:

  • Flow layout
  • Float layout
  • Multi-column layout
  • Positioned layout
  • Table layout
  • Flexible box layout
  • Grid layout

In this article, we are going to explore the first 4 of the list above.

Flow layout

Flow layout is our default algorithm if nothing else is specified. This is what you get when looking at an HTML file without any custom CSS attached in your browser: it’s a collection of inline and block elements, stacked next to and on top of each other.

Inline elements stay on a line in inline direction (which is from left to right in languages like English or German). Their size is always based on their content.

Block elements take up all the horizontal space they can get and are stacked in block direction (in our case from top to bottom). We can set properties like width and height on block elements.

In case you also read previous posts of this tutorial series, this might sound familiar as we were talking about block and inline boxes when learning about the CSS box model.

In flow layout, every box pushes the other boxes away. Each part of the content gets its own space on the page. The distance between elements can be adjusted using padding and margin properties to make the content readable. This is taken care of by browsers and the user agent stylesheet. By default, headlines are using a larger font size than body text, between headings and paragraphs there’s margin to create hierarchy, lists are indented using padding-inline-start—the list goes on.

Flow layout is the reason we can enjoy consuming (text) content when opening an HTML file in a browser. When I want to create a single column layout, I can do this using flow layout only. Additionally, when I don’t add any other custom CSS, the page is perfectly responsive by default.

Once website layouts and designs get more complex, flow layout isn’t enough anymore. As soon as we want to place (block) items next to each other, we need to switch to another layout mode.

Float layout

Back in the early days of the web, there was no flexbox or grid layout algorithm. For a long time, grid systems for multi-column page layouts were created using float layout. Back then, I always had to search for “CSS float clearfix” code snippets and never really understood what’s going on exactly when sections started to overlap. 🙈

Today, I don’t want to explain how you can throw out all flex and grid layouts we’ve added to our small example website and go back to using float layout instead… I’d rather like to explain the only use case where using this layout mode still makes sense today, in my opinion.

For this, I open the code of the tutorial website’s index page. You can do the same, or, in case you are new here, have a look at the GitHub repository, where you can find the code from all previous articles and start from there.

Adding content

I could be creative now and add more meaningful text to the website’s homepage. But as this article is about layout algorithms and not the content itself, I use the good old “Lorem ipsum” to fill the page.

In the index.html file in the first content section, I put the image first and add more (dummy) text to the two existing sentences:

<section class="content-section">
  <div class="content-container">
    <h2>This is me</h2>
    <p>
      <img src="./images/me.jpg" alt="A photo of me and my white cat Gandalf." />
      I not only like web development and music but also cats. On the photo you can see me with
      my cat Gandalf (the white). Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent porttitor quam
      a aliquam scelerisque. Vivamus euismod nunc ornare dictum fermentum. Morbi eu tincidunt nulla, cursus semper leo.
      Nulla nulla odio, elementum sed placerat ut, auctor at massa. Mauris volutpat viverra augue non aliquet.
      Nulla ipsum diam, maximus ut efficitur ut, auctor eu arcu. Lorem ipsum dolor sit amet, consectetur
      adipiscing elit. Nunc non ornare augue, eget facilisis mi. Sed viverra purus eu dictum condimentum.
      Ut est mi, pharetra vitae tincidunt sit amet, lobortis et nisl.
    </p>
  </div>
</section>

In the browser this looks as follows: The image, being an inline element, sits on the same line as the first couple of words. Once the text reaches the end of the .content-container there’s a line break and the text continues on the next line.

A screenshot of the “This is me” section on the index page. There’s an image with Lara and her cat Gandalf and mostly dummy text next to it.

Make the image float

Now, we want a layout that looks like in a magazine or a newspaper, where the text floats around the image. This is where float layout comes in and this is also the original use case for this layout algorithm.

Let’s add a class (e.g. floating-image) to the img element in the index.html file and the following to the CSS file:

.floating-image {
  float: left;
}

It means, the image should float to the left and the text should wrap around on the right side.

A screenshot of the “This is me” section on the index page. The image is on the left side of the text and the text wraps around the image.

I only want this behavior once the viewport reaches a certain width. On smaller viewports, the image should be above the text. Additionally, there should be a little bit of spacing around the image. I update my CSS code as follows:

.floating-image {
  display: block;
  margin-bottom: var(--spacing-2);
}

@media screen and (min-width: 700px) {
  .floating-image {
    float: left;
    margin-right: var(--spacing-2);
  }
}

A screenshot of the “This is me” section on the index page. The image is on the left side of the text and the text wraps around the image. There’s more spacing now between the image and the text.

As always, there’s much more to learn about float layout in CSS. In this small example, I wanted to show you, where you still can (and should) use this layout mode today.

The full code of this article can be found on GitHub. Go to repository.

Multi-column layout

Let’s add more dummy content to have a look at another layout algorithm: the multi-column layout.

On the index page, add a section with a little bit of text between “This is me” and “My projects”. In my example, the new section looks as follows (note the HTML elements and classes I added around the content):

<section class="content-section">
  <div class="content-container content-container-wide">
    <h2>Multi-column layout</h2>
    <div class="multi-column">
	    <p><!-- first paragraph of Lorem Ipsum --></p>
	    <p><!-- second paragraph of Lorem Ipsum --></p>
    </div>
	</div>
</section>

Without any additional styles, we have a headline and two paragraphs in flow layout, stacked on top of each other in block direction.

A screenshot of the new section with a headline “Multi-column layout” and two paragraphs of “Lorem ipsum” in flow layout.

For another newspaper-inspired section, we’re going to add the following lines to our CSS file:

.multi-column {
  column-count: 3;
}

And tada—there we have the text perfectly divided into three columns. 🎉

A screenshot of the new section with a headline “Multi-column layout” and two paragraphs of “Lorem ipsum” now in a three-column layout.

Three columns might be a bit much given the available horizontal space from a design perspective, as the lines of text are quite short. We could use a combination of media queries and an even larger content container to improve this, but for now, I’ll just leave the section as it is.

Using more related CSS properties, we could adjust the gap between columns, add a line between them, and much more. Find all the details in the official multi-column layout documentation on MDN.

Positioned layout

There’s one more layout algorithm I use when I want to manually set the exact position of an element on the page. In contrast to flow layout, in positioned layout elements can overlap and be stacked on top of each other, which opens up a lot more possibilities, and increases the chances of introducing nasty visual bugs. 😅

I can switch an item from flow to positioned layout when using the position property in CSS and setting the value to something other than static (the default). The options we have are:

  • relative
  • absolute
  • sticky
  • fixed

When I use one of these four values, I get access to other properties to define the element’s position: top, bottom, left, and right.

I try to quickly describe the differences with the help of illustrations.

When an element’s position is relative, it can be moved relative to its original position. The space stays “reserved” and other elements on the page are not affected. In the visualization below, the CSS code for this element could look as follows:

.pos-relative {
  position: relative;
  top: 20px;
  left: 30px;
}

A dashed line visualizing the viewport; within there are three rectangles. The one in the middle is positioned and uses the value relative. It’s moved a little to the right and down from it’s original position which is illustrated by another dashed line.

When using an absolute position, the element is taken out of the document flow and all other elements that come after ignore it and take up space as if the absolutely positioned element wasn’t there. In the visualization below (imagine that again, the second of three elements is positioned), the CSS code for this element could look as follows:

.pos-absolute {
  position: absolute;
  top: 20px;
  left: 30px;
}

A dashed line visualizing the viewport; within there are three rectangles. The one in the middle is positioned and uses the value absolute. It’s moved a little to the right and down by using the CSS properties top and left relative to the viewport. The third rectangle moves up and occupies the space where the second rectangle has been initially.

When the absolutely positioned element has no positioned ancestor, it is positioned relatively to the initial viewport by specifying top, bottom, left, or right.

The values fixed and sticky are similar. When an element is fixed, it stays in its original (or specified) position, even if the user starts scrolling.

A dashed line visualizing the viewport; within there are some rectangles showing a header on top, a sidebar and some content next to it.

A dashed line visualizing the viewport; within there are some rectangles showing a header on top, a sidebar and some content next to it. Only half of the header rectangle is visible and there are more content rectangles and a hint that the user scrolled down. The sidebar has a fixed position and stays at the same place.

When using the following CSS snippet…

.sidebar {
  position: sticky
  top: 20px;
}

…the sidebar element scrolls with the rest of the page until it reaches 20 pixels from the top and then stays fixed when the user scrolls further down the page.

A dashed line visualizing the viewport; within there are some rectangles showing a sidebar and some content next to it. The sidebar sits almost on top in its sticky position and there’s an indicator that the user scrolled down.

Let’s stop talking about the theory and use positioned layout in our small website project!

Adding decorative items to the page footer

In the pages’ footer sections, I’d like to add some decorative items: circles in different shades of purple that are placed in the corners of the footer area.

A screenshot of the bottom of the index page where the footer is visible. In the top left and bottom right corners of the footer are decorative circle elements.

To achieve this, we need to prepare the HTML code by adding empty div elements to the footer, which will become the circles.

<footer class="page-footer">
  <div class="circle circle-lg circle-lg-tl"></div>
  <div class="circle circle-tl"></div>
  <div class="circle circle-lg circle-lg-br"></div>
  <div class="circle circle-br"></div>
  <p>This website is built with love in Austria.</p>
</footer>

The classes I use explained:

  • .circle for the base styles like the border-radius and position
  • .circle-lg for different values of width and height
  • .circle-tl, .circle-br, etc. for the individual circles to add the exact position values

To create circles, I need squares (i.e. elements with equal width and height) with a 50% border-radius. I also add some color values for the elements using CSS custom properties. (We learned about them in the last article of this tutorial series.) This is what my CSS code looks like:

:root {
  /* all the CSS custom properties */
  --circle-background-color: #8968a4;
  --circle-lg-background-color: #d6a0ff;
}

.circle {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background-color: var(--circle-background-color);
}

.circle-lg {
  width: 110px;
  height: 110px;
  background-color: var(--circle-lg-background-color);
}

Now to the fun part: we want to position the circles absolutely, relative to the footer. Here comes the CSS update:

.page-footer {
  /* other page footer styles */
  position: relative;
  overflow: hidden;
}

.circle {
  /* the styles from above */
  position: absolute;
}

.circle-tl {
  top: -20px;
  left: 40px;
}

.circle-lg-tl {
  top: -20px;
  left: -30px;
}

.circle-br {
  bottom: 30px;
  right: -10px;
}

.circle-lg-br {
  bottom: -30px;
  right: -20px;
}

Each circle gets its own position. Play around with the values and try to find positions that look nice. Don’t forget to add position: relative to the page footer. If you wouldn’t do that, the circles would be positioned relatively to the initial viewport, which would look as follows:

A screenshot of the top part of the index page where the circles are placed in the top left and bottom right corners of the viewport (and not the footer).

Not making the circles overflow their parent container (overflowing content is one of the challenges in CSS), we need to set the overflow property to hidden. Note, that this might have some unwanted side effects, so I suggest to always add a comment to the CSS code noting why the property has been set. This saves co-workers and your future self a lot of time when hunting for bugs. 😉

Items can overlap

One main difference to flow layout is that items can now overlap. This is what we want for the circles, but there’s one tiny problem we have now on smaller viewports: the circles overlap the footer text. 😱

A screenshot of the footer on the index page on a smaller viewport. The first and last word of the footer text “This website is built with love in Austria” is hidden behind the circles.

The reason is that positioned elements are put on an additional layer on top of elements in flow layout. This is why in our example the footer text is partially hidden behind the circles. To fix this, we could change the layout mode for the footer text and make it a positioned element as well like so:

.page-footer p {
  position: relative;
}

The paragraph is moved to the “positioned layout layer” and because the element comes after the circle divs in the HTML code, it is rendered on top of them and the text is visible again.

The full code of this article can be found on GitHub. Go to repository.

Wrapping up

Wow! Today, we’ve learned a lot about layout in CSS beyond flexible box and grid layout. Using a combination of the seven available layout modes you can build awesome responsive layouts for your websites and applications.

As mentioned above, there are many more use cases and examples for multi-column or positioned layout we didn’t discuss in detail in this part of the web development basics tutorial series. Using the (MDN) documentation and inspiration from other resources and websites, I’m sure you’ll find the perfect mix of layout algorithms and their features for your next project! 😊

There are also more interesting details about inline, inline-block, and block elements, item alignment in general and the z-index worth checking out (search for stacking context if you’d like to go down this rabbit hole 🐰)… Maybe I’ll cover some of these topics in a future blog post.

Meanwhile, I can recommend an article about layout algorithms by Josh W. Comeau.

We’re almost done with this tutorial series. 🥳 In the next and officially last part, I’d like to wrap up with more thoughts on accessibility and user experience in general. I also plan one bonus article where I am going to add some finishing touches and design updates to the example website I started building 3.5 years ago and no longer like today… 🙈

Any thoughts or comments?

Say hello on Mastodon or contact us via email or contact form!