How to override CSS classes with Hugo


#1

Hey there everyone, really enjoying Hugo but had a little question if I may.

I notice that most themes place all their CSS in one large file and then reference this file in their layout template. I understand that you can override an entire file via the /static and /layout directories, but this is rather troublesome in the case of CSS with many themes because it would mean that I would need to keep my own maintained copy of the original large CSS file.

For example, let’s check out the casper theme for Hugo:

This contains the following CSS:

Fotsies-MacBook-Pro:hugo-theme-casper fots$ tree static/css/
static/css/
├── nav.css
└── screen.css

0 directories, 2 files

In this case, I wish to override a few aspects of screen.css which is 1,910 lines long.

The header layout links to these 2 CSS files but doesn’t allow any room for overriding anything without replacing the original screen.css with a new copy that contains minor alternations.

Fotsies-MacBook-Pro:hugo-theme-casper fots$ grep stylesheet layouts/partials/header.html 
    <link rel="stylesheet" type="text/css" href="{{.Site.BaseURL}}css/screen.css" />
    <link rel="stylesheet" type="text/css" href="{{.Site.BaseURL}}css/nav.css" />
    <link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Merriweather:300,700,700italic,300italic|Open+Sans:700,400|Inconsolata" />

Is this simply due to a poorly designed theme or is there something I’m missing?

I have tried various themes and they all seem to be similar in this respect
Fotis


#2

To override the CSS, just add your own CSS file with a link tag after all of those, linking to an appropriate file in /static. See this for more information if you want to replace them completely.


#3

Thanks so much for your reply. I guess this means that we probably have to override the header.html partial to specify the additional CSS link, is that correct?


#4

This is a common problem when users try to customize a theme. In some of my themes I include an option to easily insert custom stylesheets. Maybe you can do a pull request to add the following scheme to the theme:

Inside the config file I assign an array to a variable:

[params]
    custom_css = ["css/foo.css", "css/bar.css"]

You can reference as many stylesheets as you want. Their paths need to be relative to the static folder.

Inside the header partial you can include every custom stylesheet from above beside the original one:

{{ range .Site.Params.custom_css -}}
    <link rel="stylesheet" href="{{ . | absURL }}">
{{- end }}

This way you don’t touch the header partial at all but you’re still able to overwrite CSS classes.


#5

Thank you so so much for your reply. This is similar to what I had in mind, awesome implementation!

It would be awesome if this were to become a standard practice that all theme developers used. Once I choose a theme, I’ll submit a pull request with this feature.

Really appreciate your help and time!
Fotis


#6

PS: I do the same with Javascript files, by using custom_js as variable name.


#7

Thanks @digitalcraftsman for the solution, I have added this to my theme with thanks to @fgimian for pointing it out.


#8

Just a note, looks a neat solution. Just working through my first attempt and the theme I’m modifying the author has taken a different approach.

Basically created a style.html partial with the intention that is can be overridden ( and does the same with script.html partial for JS )

A different approach but works.


#9

A perhaps more flexible solution for themes would be add an empty “extra-in-head.html” partial. This way, users can put anything into the head by overriding “extra-in-head.html”.

It may for example be that for performance reasons, it is desired to include the css directly in the HTML, thereby eliminating a server request.

Or it may be that the user want to include some css on a specific page. He can then create an “extra-in-head.html” partial which includes the CSS specified in the frontmatter, ie something like this:

frontmatter:

+++
css = "contact"
...

extra-in-head.html:

{{ if eq .Params.css "contact"}}
{{ template "css/contact.html" }}
{{ end }}

{{ if eq .Params.css "about"}}
{{ template "css/about.html" }}
{{ end }}

layouts/css/contact.html:

<style>
  h1 {
    margin: 40px;
  }
</style>

#10

[params] custom_css = ["css/foo.css", "css/bar.css"]

That would be very cool. Does the default Ananke theme has this parameter available? Is it called custom_css or something else? I can not find it in the example site or in their readme.


#11

If not already in the theme, you can always customize the head partial by creating a duplicate in your project source that will override the theme source via Hugo’s lookup order.


#12

Hi Folks! Thanks for this exchange (and thanks for this great Hugo framework!).

I noticed that I can overwrite a css file of a theme like “hugo-universal-theme” by creating a css directory under the static directory, copy the css file to change and apply my changes there.
Unfortunately, these changes are not taken under consideration when I run hugo server. I have to run hugo and generate the ‘public’ folder to see the css file overwritten.
Is it design this way or is it specific to this theme?

Thanks a lot for your help


#13

I was just looking for an answer to this very question with the universal theme when I stumbled across this thread.

So, i took a look at universal’s head.html, and saw the following lines after the <link> to the style.[stylename].css:

<!-- Custom stylesheet - for your changes -->
<link href="{{ .Site.BaseURL }}css/custom.css" rel="stylesheet">

So, at least for “universal,” if you copy the theme’s custom.css into your [theme]/static/css directory, you can put your overrides there. When I build the site, it seems to put the appropriate custom.css in the [theme]/public/static/css directory. So, I’m going to put my css overrides in the site’s custom.css.

Thanks for pointing me in the right direction!


#14

Yes, I second that Universal theme rocks, they have all the bells and whistles I need, just put custom css in /static/css/custom.css (I copied the corresponding file from the theme tree).