Converting Simple Web Page Into Hugo Theme Part 1 - HTML & CSS

February 8, 2019

Once I’ve decided to start blogging several questions opened like what to use, where to host, what theme… I decided to go with Hugo for generating static sites since hosting static sites is a lot easiear than hosting something dynamic like Wordpress, plus Hugo is fast and supports live reloading (via JS it injects into the page) in development mode when it detects changes in files.

I installed Hugo, wrote some posts and tried some themes hoping to find one that is minimal, light and that fits my expectations. I tries some themes like Hugo-Primer, Coder Portfolio, Basics, Tale, etc and then decided to create my own theme and hopefully learn something along the way.

We’ll cover:

Part 2 - Theme Home Page

Part 3 - Single Post Page

Part 4 - Externalized Configuration

Part 5 - Templating and Icons

Theme wireframe

I’ve set some simple requrements for theme to meet, like it has to be responsive, really simple and light (bootstrap would be overkill).

With that in mind I created wireframe sketches for mobile and desktop layout for list of posts (home page) and for single post page.

Home page layout on mobile looks like this:

And post page like this:

Home page on desktop should look like this:

And post page like this:

Really simple IMHO. Lets put that into HTML.

Theme HTML & CSS

Initial index.html at the moment looks like this:

<!DOCTYPE html>
<html>
<head>
  <title>Esed Alihodzic</title>
  <meta name="viewport" content="width=device-width">
  <link href="style.css" rel="stylesheet">
</head>

<body>
    <div class="wrapper">
    <nav class="main-nav">
     <h3>Esed Alihodzic</h3>
     <ul class="nav">
      <li><a href="index.html">Blog</a></li>
      <li><a href="">About</a></li>
    </ul>

    <ul class="social">
      <li><a href="#">G</a></li>
      <li><a href="#">T</a></li>
      <li><a href="#">Li</a></li>
      <li><a href="#">M</a></li>
    </ul>
  </nav>

  <div class="content">
   <article>
    <h1>Article With Image</h1>
    <p class="article-detail-date">February 8, 2018</p>
    <p>In this layout, we display the areas in source order for any screen less that 500 pixels wide.</p>
    <a href="article.html">Read more...</a>
  </article>

  <div class="page-nav">
    <a href="#">Newer</a>
    <a href="#">Older</a>
  </div> 
</div> 
</div>
</body>
</html>

And that will be backbone of our blog!

When viewed in browser it produces:

Positioning divs correctly was always a pain until CSS Grid Layout and Flexbox came along. This tutorial explains how to achive responsive layouts using CSS Grid and Flexbox.

Our page will have one column on mobile and two columns on desktop. Lets start with mobile.

The part of CSS that tells wrapper to use grid to position its elements and also declares which positions are available inside grid will look like this:

.wrapper {
	display: grid;
	grid-gap: 20px;
	grid-template-areas: 
	"nav"
	"content";
}

After declaring template areas we simply declare classes for said template areas that will be assigned to two divs (one for content and one for main navigation) inside a div with wrapper class:

.content {
	grid-area: content;
}

.main-nav {
	grid-area: nav;
}

Lets add CSS to remove bullets from menu items, fix menu positioning etc. Complete style.css right now looks like this.

nav ul {
	display: flex;
	list-style: none;
	margin: 0;
	padding: 0;
}

nav ul li {
	margin-right: 10px;
}

nav .social li {
	margin-right: 20px;
}

nav .social {
	display: flex;
	margin-top: 10px;
}

.content {
	grid-area: content;
}

.main-nav {
	margin-top: 5px;
	grid-area: nav;
}

.main-nav a, 
.main-nav a:link, 
.main-nav a:visited, 
.page-nav a, 
.page-nav a:link, 
.page-nav a:visited {
	  color: blue;
	  text-decoration: none;
}

.wrapper {
	display: grid;
	grid-gap: 20px;
	grid-template-areas: 
	"nav"
	"content";
}

.page-nav a {
	display: flex;
	justify-content: space-between;
	margin-top: 30px;
	margin-bottom: 30px;
}

.article-detail-date {
	color: #989898;
}

Setting dislplay to flex of an element causes it to display its childred in a row by default, or in a column if flex-direction: column; is set.

nav .social {
	display: flex;
}

Applying this CSS gives us this for home page:

and this for post page:

It’s already usabe on mobile, while home page on desktop this looks like this:

and post page like this:

Desktop needs some fixing to move list of articles and article to the right of sidebar.

Lets fix that. Add this to the bottom of style.css:

@media (min-width: 750px) {

	.wrapper {
		grid-template-columns: minmax(200px, 200px) minmax(400px, 800px);
		grid-template-areas: "nav content";
	}

	nav .nav {
		display: flex;
		flex-direction: column;
		justify-content: space-between;
	}

	nav .social {
		display: flex;
		flex-direction: row;
		margin-top: 20px;
	}

	nav ul li {
		margin-bottom: 10px;
	}

	nav .social li {
		margin-right: 10px;
	}

	.main-nav {
		position: fixed; 
		padding-left: 10px;
	}
}

We set 750px to be breaking point above which desktop layout is applied and below which mobile layout is in place.

We control this by setting wrapper class to display its content into two columns which have minimum and maximum width set. With minmax set on columns, layout guarantees that column width will always be within defined range when addopting to different screen sizes.

Lets also fix sidebar so that it stays in place while main content is scrolling:

.main-nav {
	position: fixed; 
}

After applying this CSS, mobile layout is left unchanged but desktop looks like this:

Post page like this:

Very close to initial wireframe and its responsive! :D

In the next part we’ll see how to convert basic page like this into a real Hugo theme.