Right now you have a single CSS file for the site with a pretty minimalist design. As it grows, you may want to break it up into components, or evolve it further.
To use the pipelines feature of Hugo, you’ll need to move your CSS files out of the static directory and into a new assets directory.
Stop your Hugo server with Ctrl-c. Create a new directory in your theme named assets. You can do this with your editor, or with the following command:
| | $ mkdir themes/basic/assets |
Then move the static/css directory there:
| | $ mv themes/basic/static/css themes/basic/assets |
Then in themes/basic/layouts/partials/head.html, locate the line of code that loads the stylesheet. Add this line above the stylesheet link to load the assets/css/style.css file:
| » | {{ $css := resources.Get "css/style.css" }} |
| | <link rel="stylesheet" href="{{ "css/style.css" | relURL }}"> |
The resources.Get function uses the assets directory as its base path. The contents of the file are read in to the $css variable.
To use the CSS file, modify the stylesheet link to use the $css variable:
| | <link rel="stylesheet" href="{{ $css.RelPermalink }}"> |
The $css.RelPermalink piece writes the file to your site’s public/css/ directory and places the proper relative URL into the HTML document.
Start your server with hugo server and visit your home page again to ensure your styles still work.
Now that you’re pulling the CSS in with resources.Get, you can apply some transformations to the file.
It’s common practice to minify front-end content. This removes non-printable characters and comments, resulting in smaller files that transfer faster.
In addition, you can fingerprint your assets. When you serve up your stylesheet, your browser will cache it. When you update the page, your browser might not notice the changes unless you clear your local cache. One way to get around that is by using fingerprinting to create a unique filename for your CSS files that gets updated every time you make changes.
Hugo supports both minification and fingerprinting when you use the resources.Get function. You can pipe the resource to the minify and fingerprint functions. Modify the resources.Get line to do just that:
| » | {{ $css := resources.Get "css/style.css" | minify | fingerprint }} |
| | <link rel="stylesheet" href="{{ "css/style.css" | relURL }}"> |
This results in a file with a name like /css/style.min.a939605b22...815d1.css". Its contents are minified, and the filename will change when you change the contents. Because Hugo is managing all of this, you don’t have to think about it.
Sass is a CSS preprocessor that offers advanced features. With Sass, you can break up your CSS into manageable chunks, define variables, and perform math. While some of these features are making their way into browsers, Sass is a popular choice for building front-end sites.
First, rename themes/basic/assets/css/style.css to themes/basic/assets/css.style.scss:
| | $ mv themes/basic/assets/css/style.css themes/basic/assets/css/style.scss |
The scss syntax of Sass is a superset of CSS, so a CSS file is already a valid Sass file.
To use this file, update the filename and introduce the toCSS function into the pipeline, in front of the minify function:
| | {{ $css := resources.Get "css/style.scss" | toCSS | minify | fingerprint }} |
This gets things working, and you can now integrate many of Sass’s features into your styles.
For a quick example, let’s extract the styles for the navbar into its own file so it’ll be easier to manage.
Create the file themes/basic/assets/css/_navbar.scss. The underscore denotes that this is a Sass partial which you can include into a main Sass stylesheet.
Switch to styles.scss and locate the styles related to the navigation bar:
| | nav { |
| | display: flex; |
| | flex-direction: column; |
| | } |
| | nav > a { |
| | flex: 1; |
| | text-align: center; |
| | text-decoration: none; |
| | color: #fff; |
| | } |
Remember that one of the styles for the navigation bar is within a media query with some other styles:
| | @media only screen and (min-width: 768px) { |
| » | nav { flex-direction: row; } |
| | |
| | .project-container { display: flex; } |
| | |
| | .project-container .project-list { width: 20%; } |
| | |
| | .project-container .project { flex: 1; } |
| | } |
Cut these style rules from the file and paste them into the _navbar.scss file. Create a new media query also. Your file will look like this when you’re done:
| | nav { |
| | display: flex; |
| | flex-direction: column; |
| | } |
| | |
| | nav > a { |
| | flex: 1; |
| | text-align: center; |
| | text-decoration: none; |
| | color: #fff; |
| | } |
| | |
| | @media only screen and (min-width: 768px) { |
| | nav { flex-direction: row; } |
| | } |
Then, back in the style.scss file, add an import statement, which will pull the _navbar.scss file’s contents into the main stylesheet when Hugo builds your site:
| | nav, footer { |
| | background-color: #333; |
| | color: #fff; |
| | text-align: center; |
| | } |
| | |
| » | @import 'navbar'; |
Save all of your changes. You now have a path forward to creating more complex and organized stylesheets for your site.
You haven’t done too much with images in this book yet, but that’s about to change. Hugo has some fantastic features for working with images that you’ll explore next.