I moved this blog from WordPress to Hugo in December 2017 to learn about static site generators and to practise maintaining a site using modern processes like Git. I chose the Future Imperfect theme as a foundation and put my own styles in add-on.css, which takes precedence over the theme’s stylesheet main.css.

Override stylesheets are great. You can restyle particular elements of a theme yet leave the core styles – the layout, type scheme and so on – intact. When a new version of the core stylesheet is available, you can upgrade a theme safely without affecting your override stylesheet.

Over time though, override stylesheets can bloat. Four months after switching to Hugo, I reached a tipping point. Battling precedence conflicts and unwanted cascades between add-on.css and main.css absorbed too much time. I wanted a tidy, maintainable theme and to commit more time to blogging.


Refactoring a theme can be a scary, significant undertaking. main.css has 2,500 lines while my add-on.css reached 1,000 lines.

As well as merging these stylesheets into one, I knew I needed to edit other parts of the theme, which is written in the Go language. I’m no programmer; I scrape through either by reading manuals or experimentation.

Two things gave me the confidence to jump in:

  • A day’s training (and the required prep work) by the head of Warwick’s web development team encouraged me to think more like a developer – “to get more into a mindset of building a house than painting a wall”.
  • Adam Silver’s MaintainableCSS, a superb short book of principles and practical examples of how to write modular and maintainable CSS.


Before writing a line of CSS, I decided on these principles:

  • Design for small screens first and progressively add style for wider breakpoints – to invert main.css’s large-screen-first-then-down structure of media queries.
  • Write in the LESS language – to speed up writing and to take advantage of variables.
  • Define a new typography scheme – a larger base font size with vertical rhythm and spacing based on ems.

Responsive breakpoints

I prefer names related to scales rather than devices such as -tablet or -mobile. At the top of main.less, I defined breakpoint variable names inspired by T-shirt sizes:

@screen-xxl-min: 1680px;
@screen-xl-max: 1679px;
@screen-xl-min: 1280px;
@screen-l-max: 1279px;
@screen-l-min: 980px;
@screen-m-max: 979px;
@screen-m-min: 736px;
@screen-s-max: 735px;
@screen-s-min: 480px;

Colour palette

Next up at the top of main.less, I defined colour variables with names prefixed with gw-. This helps me search for instances of the colour classes I use throughout the stylesheet. It also makes changing the whole site palette in the future a swift task.

@gw-green-mid: #2ab7ca;
@gw-green-dark: #1b7581;
@gw-green-light: #def2f4;
@gw-grey-dark: #3b4045;
@gw-grey-mid: #d2d2d5;
@gw-grey-light: #edeeef;
@gw-white: #fcfcfc;

Stating the colour in the class name does conflict with the HTML5 spec, which Adam Silver quotes in his semantics chapter:

“[…] authors are encouraged to use values that describe the nature of the content, rather than values that describe the desired presentation of the content.”

I could use @gw-colour-mid, for example. In this instance though, as it’s only me maintaining the stylesheet, I chose a variable name that’s semantic to me.


I reset the base font size to 16px for small devices and 20px for larger screens. The type scale is 1.200 Minor Third:

Font sizes for body text and headings

The post content’s line length is optimised to maintain readability, and left- and right-hand white space, across all screen widths. The stylesheet is heavy with media queries to ensure a line length of 45-90 characters. The weighty, repetitive code is worth it though. For a succinct explanation, see Matthew Butterick’s Practical Typography.

Mini map

To help write the new stylesheet and check off sections of main.css and add-on.css as I merged them, I used a mini map with TODO: comments at the top of main.less. The map outlines the stylesheet structure:

- Palette variables
- Breakpoint variables
- Reset
- Type
- Wrapper
- Header
    - Menu
    - Search
- Main layout
- Category list
- Portfolio list
- Post
- Sidebar
- Social share buttons
- Footer

The structure of the stylesheet matches how I look at a site design, interpret the main elements and decide an order in which to tackle the work:

  • Colour palette
  • Responsive breakpoints
  • Typography
  • Main layout elements
  • Content
  • Footer

It’s easy to go down a rabbit hole and dive into styling the content, for example, so I try to focus on styling elements from left to right, top to bottom:

Eye tracking across a page layout

When I get stuck or take a break, I leave TODO: comments behind in main.less. Wayou Liu’s TODO Highlight extension for Visual Studio Code helps me see these:

Highlighted comment in Visual Studio Code

A keyword search in the theme for TODO helps me locate any final parts to review, which I may have forgotten about.

Compiling LESS to CSS

I’m using a standalone application, Koala, to watch for changes to main.less and compile it to the theme’s stylesheet main.css. Using an app outside of the Hugo build and deploy process, however, isn’t great practice. I should figure out how to include preprocessing and compilation as part of the Hugo site build. That’s a chunky piece of learning for another day.

For now, I have one maintainable stylesheet for this site’s theme, a responsive mobile-first implementation and a clean visual aesthetic based on solid typography. The original 3,500 lines of CSS are a more manageable 2,000 lines of LESS.

Time for a brew.

comments powered by Disqus