Update Note
When this post was originally published, it linked to a dynamic version of the All Posts list page. That page has been retired. Consequently, links to that page have been replaced with a links to a saved static version of that page.
Introduction
This project is built with Hugo and uses the Minimal Hugo theme.
This post is part of an ongoing effort to tailor the theme over time.
Objective
For this post, we’ll prototype a new user interface for navigating between list pages.
As of this writing, the list page has right and left arrows that allow navigating to the list pages for earlier and later posts. We’ll keep those, and add a count of the list pages to provide some context, as well as adding a link to the All Posts list page.
We’ll arrange those four elements so that they are easy to see, understand, and interact with.
Development Approach
Changing the user interface of a Hugo theme can sometimes become complicated. So, before trying to make the update to the Hugo project, we’ll prototype the basic layout in a plain HTML file that isn’t built by Hugo. Once we’ve developed and tested an interface we like, we can then merge it into the Hugo theme.
Start with the HTML
To work directly with the HTML, we’ll create a file inside a separate project folder.
Prototype 1 - Just HTML
In addition to typical HTML boilerplate, we’ll include the following inside the <body>
tag:
<hr>
<h3>Page Navigation, Prototype 1 - Just HTML </h3>
<div>Left Navigation</div>
<div>List Page X of Y</div>
<div>See All Z Posts</div>
<div>Right Navigation</div>
<hr>
Looking at the first prototype page, it’s clear the interface would benefit from additional structure and styling.
Incorporate CSS
While all the necessary elements for the user interface are defined in the HTML file, the arrangement and styling will occur principally in a linked CSS file. So, most of our design decisions will focus on CSS.
CSS Flexbox vs CSS Grid
Because we are structuring an interface, the two obvious approaches are CSS Flexbox and CSS grid, so the first decision is to select between them.
In Chris Coyier’s excellent article, Quick! What’s the Difference Between Flexbox and Grid?, he points out many of the reasons CSS Grid seems the better choice for this task, but perhaps the simplest articulation comes from a quote that he includes in the article:
flexbox looks like it does what you want
but grid is usually what you want
With that hypothesis, we need to figure out how to utilize CSS Grid for our task.
Getting Started with CSS Grid
As is often the case, a helpful place to start is the Fireship YouTube channel by Jeff Delaney. Specifically, he has two excellent videos that provide a great introduction to CSS Grid:
And as we build, another reliable resource, CSS-Tricks offers a very helpful reference:
Prototype 2 - Basic CSS Grid
To test the effect of CSS Grid, we’ll start by adding a new section to the <body>
of our HTML file:
<h3>Page Navigation, Prototype 2 - Basic CSS Grid</h3>
<div id="listpage-navigation-panel-proto02">
<div id="listpage-navigation-left-proto02">Left Navigation</div>
<div id="listpage-navigation-pagexofy-proto02">List Page X of Y</div>
<div id="listpage-navigation-allpostlink-proto02">See All Z Posts</div>
<div id="listpage-navigation-right-proto02">Right Navigation</div>
</div>
<hr>
Looking more closely:
<div id="listpage-navigation-panel-proto02">
- We’ve added a containing <div>
around our existing divs to act as the CSS Grid parent and given it a unique ID.
We also gave our four child divs unique IDs.
Next, we’ll add a style section to the <head>
tag to link our CSS file:
<style>
@import url('./prototype.css');
</style>
And for our CSS file we’ll include the following:
/* List Page Navigation - Prototype 2 */
div#listpage-navigation-panel-proto02 {
display: grid;
grid-template-areas:
"left-proto02 pagexofy-proto02 right-proto02"
"left-proto02 allpostlink-proto02 right-proto02";
grid-template-columns: 1fr 1fr 1fr;
justify-items: stretch;
background: gray;
}
div#listpage-navigation-left-proto02 {
grid-area: left-proto02;
text-align: center;
background: red;
}
div#listpage-navigation-pagexofy-proto02 {
grid-area: pagexofy-proto02;
text-align: center;
background: green;
}
div#listpage-navigation-allpostlink-proto02 {
grid-area: allpostlink-proto02;
text-align: center;
background: orange;
}
div#listpage-navigation-right-proto02 {
grid-area: right-proto02;
text-align: center;
background: hotpink;
}
We’ve added a different background color to each div so that we can easily see what area they occupy.
Looking at the second prototype page, we can already see that the result is much improved but there are still several issues we’ll want to address.
Adjust the CSS
Prototype 3 - Making the CSS Grid Responsive
Testing the design by resizing the browser window reveals that the result is not particularly attractive or useful at either large or small sizes.
To compare our changes we’ll again add a new section to our HTML file:
<h3>Page Navigation, Prototype 3 - Making the CSS Grid Responsive</h3>
<div id="listpage-navigation-panel-proto03">
<div id="listpage-navigation-left-proto03">Left Navigation</div>
<div id="listpage-navigation-pagexofy-proto03">List Page X of Y</div>
<div id="listpage-navigation-allpostlink-proto03">See All Z Posts</div>
<div id="listpage-navigation-right-proto03">Right Navigation</div>
</div>
<hr>
There is no structural change to this addition. We just updated the IDs to end in -proto03 so that we can target this new section with our changes and make their effect clear. We’ll likewise duplicate and update the IDs of our CSS code for this new example.
Now, we can fix the resizing issue with a single line change to the CSS:
div#listpage-navigation-panel-proto03 {
display: grid;
grid-template-areas:
"left-proto03 pagexofy-proto03 right-proto03"
"left-proto03 allpostlink-proto03 right-proto03";
grid-template-columns: repeat(3, minmax(50px, 300px));
justify-items: stretch;
background: gray;
}
We replaced the previous grid-template-columns: property with repeat(3, minmax(50px, 300px))
. This keeps the width of each column equal to one another (as in the previous prototype), but it now sets a minimum and maximum width for the columns.
Testing the third prototype page shows that it resizes appropriately when the screen size changes and it looks good at various sizes.
A new problem emerges, however, because now the navigation panel always touches the left edge of the viewport. This isn’t obvious on small screens, but once the screen exceeds the maximum navigation panel width, the panel sticks to the left edge. For our purposes, we’ll want to keep the panel centered.
Prototype 4 - Centering the Navigation Panel Horizontally
Again, before making changes we’ll add a new duplicate section to our HTML and CSS files, updating only the ID suffixes to -proto04.
Now, in our HTML file we’ll wrap our navigation panel in an additional <div>
element:
<h3>Page Navigation, Prototype 4 - Centering the Navigation Panel Horizontally</h3>
<div id="listpage-navigation-container-proto04">
<div id="listpage-navigation-panel-proto04">
<div id="listpage-navigation-left-proto04">Left Navigation</div>
<div id="listpage-navigation-pagexofy-proto04">List Page X of Y</div>
<div id="listpage-navigation-allpostlink-proto04">See All Z Posts</div>
<div id="listpage-navigation-right-proto04">Right Navigation</div>
</div>
</div>
<hr>
And we’ll style that new div as a CSS grid as well:
div#listpage-navigation-container-proto04 {
display: grid;
justify-content: center;
grid-template-columns: minmax(50px, auto);
background: gold;
}
As the fourth prototype page shows, this allows us to keep the navigation panel centered even as the page is resized.
Prototype 5 - Centering the Navigation Panel Elements' Content Vertically
Now, to center the navigation panel elements' content vertically, we’ll turn to CSS Flexbox. We’ll add three lines to all four of the panel elements:
div#listpage-navigation-left-proto05 {
grid-area: left-proto05;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
background: red;
}
The fifth prototype page demonstrates that the panel elements' content is now vertically centered.
Prototype 6 - Adding Hyperlinks
Now that we have the structure the way we want it and since this is a prototype of a navigation panel, it’s time to add some hyperlinks for navigation.
For now we’ll use empty links because we just want to demonstrate the functionality and don’t need or want to leave the prototype page while testing.
<h3>Page Navigation, Prototype 6 - Adding Hyperlinks</h3>
<div id="listpage-navigation-container-proto06">
<div id="listpage-navigation-panel-proto06">
<a id="listpage-navigation-left-proto06" href="">Left Navigation</a>
<div id="listpage-navigation-pagexofy-proto06">List Page X of Y</div>
<div id="listpage-navigation-allpostlink-proto06"><a href="">See All Z Posts</a></div>
<a id="listpage-navigation-right-proto06" href="">Right Navigation</a>
</div>
</div>
<hr>
We changed three lines: replacing the left and right navigation div elements with anchor elements and enclosing the allpostlink div element text in an additional anchor element.
The reason for the differing approaches is that in the case of the left and right elements we want the entire grid area to be the clickable target area, to make forward and backward navigation easy. Whereas, for the the allpostlink we want to reduce the likelihood of accidentally clicking that element by only making the text in that area clickable.
The sixth prototype page demonstrates the difference.
Prototype 7 - Example Form
With the basic structure and all core features in place, we can remove/replace the background colors in the seventh prototype page to get a sense for how the navigation panel will look on our site.
Conclusion
We now have a working prototype including all the basic features we want.
This design isn’t perfect and probably has lots of room for improvement and simplification, but as Jeff Delaney says:
When you first become a Junior Developer your code will look like Play-Doh snakes.
But as you progress to Senior Developer … your code will look like the Sistine Chapel.
But when you then progress to Principal Engineer you’ll realize that nobody wants to maintain the Sistine Chapel for a silly website and go back to making Play-Doh snakes.
We have a working and complete prototype. Let’s move on to the next challenge and make more useful Play-Doh snakes.