How to load assets from the static folder in a CSS file?

Hello friends,

I’m trying to resolve an issue with the Indigo theme as deployed to the themes gallery. This is part of a deeper audit. Right now, the gallery’s demo site does not load its custom fonts, which are bundled in the /static/fonts folder.

I understand why it doesn’t work — in /static/css/fonts.css, the @font-face declarations look like this:

@font-face {
    font-family: 'Charter';
    src: url('/fonts/charter_regular-webfont.eot');
    src: url('/fonts/charter_regular-webfont.eot?#iefix') format('embedded-opentype'),
         url('/fonts/charter_regular-webfont.woff') format('woff'),
         url('/fonts/charter_regular-webfont.ttf') format('truetype');
    font-display: fallback;
}

That works great when deploying to a root domain, as you can see here. But if it’s in a subfolder, the src: url('/fonts/fontname.ttf'); points to the domain root, which is (of course) wrong.

As I said, I understand what the problem is, but I’m struggling to find an elegant solution.

In an HTML file, I can get an asset from the theme’s /static folder with something like:

<img src={{ "images/site-logo.svg" | absURL }} alt="Site Logo">

But that doesn’t work in CSS files, for whatever reason. I could use inline CSS in an HTML partial, but that feels like a very hack-y workaround. How do you all load assets from the /static folder in your CSS files?

Thanks in advance!

One option is to remove all leading slashes from head.html and fonts.css and to use the base tag in your head.html:

<base href="https://domain.com/folder/">

Another option is to set baseURL to https://domain.com/folder/ in config and add RelURL to your CSS files, e.g.

<link rel="stylesheet" href="{{ "/css/style.css" | relURL }}" />

In any case you will need to update the path to the font files in fonts.css.

about static

I think this isn’t really a Hugo issue, it’s more to do with how CSS interprets urls.

According to W3

Partial URLs are interpreted relative to the source of the style sheet, not relative to the document:

So I think if you do

    src: url('./fonts/charter_regular-webfont.eot');

(i.e. starting urls with a dot) then the browswer will load the font files from a relative directory, rather than working a directory based on web root.

1 Like

This was an ah-ha moment for me! I didn’t realize that the URLs would be interpreted based on the path of the stylesheet — good find. :slightly_smiling_face:

The solution was to go up one level in the path hierarchy (since the static/ and css/ folder are siblings), so two dots instead of one:

src: url('../fonts/charter_regular-webfont.eot');

Thanks everyone for your input!

2 Likes

Since thas relies on the relative folder structure, one might argue that this is preferable:

{{ - site.BaseURL -}}/fonts/...

Pity that CSS doesn’t honor HTML’s <base>.