How to override CSS classes with Hugo

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

4 Likes

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.

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?

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.

18 Likes

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

2 Likes

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

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

1 Like

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.

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>
1 Like

[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.

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.

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

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!

1 Like

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).

Hi all, not sure I completely understand this thread. But I want to use an example. I have a theme that sets unordered list-style: none. So I get no bullet points. This is good for the page as a whole but I would like to be able to see bullet points on the posts (blog).

My understanding that best practice would be to add a new CSS file with some sort of conditional so that it only does list-style: circle on blog section of the page?

Or maybe use {.inner} to run html stylesheet on the particular blog post that needs the bullet points?

This is an ancient topic and a lot of things have changed in Hugo since 2018.

Please have a look at the forum guidelines.

If your question is about specifying CSS conditionally you would either need to use Conditional Logic in a page template or selectively load the CSS file as a resource and use ExecuteAsTemplate.

If you are looking into loading the CSS conditionally from within a shortcode then this question already has an answer over here: Use conditional for css style with shortcode

I am archiving this topic because as I said above things have changed and also people who participated in this discussion may not be around in this forum currently.

If you are still unable to solve your issue then please open a new topic, while following the Requesting Help tips.