Brought to you by CloudCannon, the Git-based CMS for Hugo.
Making good use of layouts is essential to creating an easy-to-maintain, flexible, and thriving Hugo website, so let’s see what makes them tick.
What is a layout?
A layout is used for all the ‘framing’ on a page around the content. For example, think of all the things that remain relatively unchanged between pages on a website, such as the header and footer.
In Hugo, each page on the site is a content file. At the top is a small snippet of metadata called front matter, followed by markdown. The goal of a content file is, well, to store the content in its purest form. There’s rarely any HTML or other presentation logic in a content file.
All of the fancy HTML to display and format the content lives in a layout. One layout might be used for multiple content pages. For example, on a portfolio website you might use the same layout for your about page and services page. Other times, particularly if you’re doing something intricate, you might have a layout specifically for an individual content page, for example a contact page with a complex form.
Your first page
There’s a Hugo concept called Page Bundles which can be tricky to get your head around. We’re going to do the bare minimum here to get your site going.
By default, content pages use a layout called single
. Creating a content file which is named exactly _index.md
, underscore and all, is the exception to this. These pages act like a table of contents for the pages around it and use a layout called list
by default.
Just like a good non-fiction book, it’s a good practice to start off with a table of contents. You’ll do this for the home page of your site.
If all that sounded confusing, it’s actually much simpler than it sounds. Create a file called _index.md
in the directory /content/
with the following content:
---
title: Home
---
Hello, I'm a ferocious lion.
The ---
lines indicate the metadata or front matter I mentioned before. We’ll get to that in a future lesson.
Your first layout
Hugo has a hierarchy to figure out which layout to use for a content_d file. The last fallback is looking for a layout in the _default
directory. Let’s create a default list layout for your home page.
Create a new directory inside /layouts/
called _default
and inside, create list.html
with the following content:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>{{ .Page.Title }}</title>
</head>
<body>
{{ .Content }}
</body>
</html>
Those {{ *** }}
parts are rendering content from our content file (_index.md
) using Hugo templating which we’ll cover soon.
You’ve got everything you need to render your first page. Will it build or will it error? There’s only one way to find out.
Hugo has a command called serve
which will build your site and serve it locally at http://localhost:1313/ (by default). Run this command in the root of your site and open the localhost address in your browser:
hugo serve
Look at you go! That’s real content rendering through a layout on your Hugo site. Let’s celebrate with a second page on your site.
Your second layout
Let’s get a second page on your website. Create /content/about.md
(note that we’re not using an underscore here):
---
title: About
---
I'm learning Hugo, one step at a time.
about.md
looks for a layout named single
by default. We could clone /layouts/_default/list.html
to /layouts/_default/single.html
and it would work fine, but you’d be left maintaining two, very similar versions of the same layout. We want to reduce repetition and make our lives easier where ever possible.
Instead, create a new layout at /layouts/_default/baseof.html
with the following content:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>{{ .Page.Title }}</title>
</head>
<body>
{{ block "main" . }}
{{ end }}
</body>
</html>
This is almost identical to the list
layout, with one minor change. Instead of outputting {{ .Content }}
, we now have a main ‘block’. This block is a placeholder that other layouts can use to only specify that part of the page.
Let’s do that with your list layout. Replace the entire contents of /layouts/_default/list.html
with the following:
{{ define "main" }}
{{ .Content }}
{{ end }}
Create /layouts/_default/single.html
with the exact same code.
Try going to http://localhost:1313/about/ and see your new about page.
Adding styles
This is a Hugo course so we’re not going to go into any CSS. However, you and I can both agree that the default browser styles leave a lot to be desired. Not only am I going to give you a stylesheet, it’s going to be a Sass stylesheet to make it easy to maintain as you expand your website.
We already have a directory called static
where all the static assets live. If we were using a plain CSS file, this would be the place to put it. We’re using Sass which needs to be processed into a CSS file.
Create a directory in the root of your site called /assets/
. This is where the assets that need some form of processing will live. Inside assets, create a directory called sass
. This is where our .scss
files will live. Let’s create a main file at /assets/sass/main.scss
with the following:
body {
width: 400px;
margin: 0 auto;
font-family: sans-serif;
}
nav ul {
list-style: none;
padding: 3px 5px;
background: #111;
a {
color: #fff;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
li {
display: inline;
}
}
footer {
background: #f2f2f2;
padding: 2px 2px;
font-size: .7em;
text-align: center;
}
#map {
height: 300px;
}
We also need to reference the stylesheet in our HTML. Open /layouts/_default/baseof.html
and insert the following below </title>
:
{{ $style := resources.Get "sass/main.scss" | resources.ToCSS | resources.Minify }}
<link rel="stylesheet" href="{{ $style.Permalink }}">
This tells Hugo to build the .scss
files and output the link in a stylesheet tag. You’ll notice this will apply to both the list
and single
layouts. That work we did earlier is already coming in handy! You may need to restart your hugo serve
to see the changes in your browser.
What’s next?
The only way to access the about page currently is by navigating to it directly. In the next lesson we’ll add site navigation using a Hugo partial.
Top comments (0)