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.
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.
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);
}
}
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.
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. 🎉
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;
}
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;
}
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.
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.
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.
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 theborder-radius
andposition
.circle-lg
for different values ofwidth
andheight
.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:
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. 😱
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… 🙈