Strange behavior when loading fonts

Hello,

I am trying to load local fonts with a font-face inside a .scss file.
I am wondering why loading fonts is not working with absolute paths or even with some type of relative paths?

My folder structure is as following:
Folder structure

When trying to load in the fonts from my lato.scss file, the following code snippets do not work:

@font-face {
    font-family: "Lato";
    src: url('./lato/Lato-Regular.ttf') format('truetype');
    font-weight: 400;
}

@font-face {
    font-family: "Lato";
    src: url('@/assets/fonts/lato/Lato-Regular.ttf') format('truetype');
    font-weight: 400;
}

Whenever I use the code snippets mentioned above, I receive an error:

This relative module was not found:

./lato/Lato-Regular.ttf in ./node_modules/css-loader??ref--8-oneOf-3-1!./node_modules/postcss-loader/src??ref--8-oneOf-3-2!./node_modules/sass-loader/lib/loader.js??ref--8-oneOf-3-3!./src/assets/styling/app.scss

Strangely, the only thing that works is by first going back a directory:

@font-face {
    font-family: "Lato";
    src: url('../fonts/lato/Lato-Regular.ttf') format('truetype');
    font-weight: 400;
}

I am currently using vue version 3.0.3 with node v8.12.0.
Also tested with the newest vue-cli-3 version and newest node version currently available.

Is this caused by webpack 4 or is this caused by a loader?

I would really like to know why fonts have such a specific syntax, as this feels very unnatural to use.

Thank you in advance for your time :slight_smile:

1 Like
url('~@/assets/fonts/......

Css loaders require a tilde to mark package names/aliases.

1 Like

Yes, that’ll do. :smiley:

Could you elaborate why a font is the same as a package name/alias?

And I am still wondering why url('../fonts/lato/Lato-Regular.ttf') does work in this scenario?

1 Like

I didn’t say that. What I meant was that @/ is a webpack alias, and that works like a package name - it doesn’t start with a ./ relative path.

1 Like

I have no idea what you mean with your last reply. It doesn’t make it much clearer to me…

1 Like

https://cli.vuejs.org/guide/html-and-static-assets.html#url-transform-rules

If the URL starts with ~ , anything after it is interpreted as a module request.

If the URL starts with @ , it’s also interpreted as a module request. This is useful because Vue CLI by default aliases @ to <projectRoot>/src

https://cli.vuejs.org/guide/css.html#referencing-assets

All compiled CSS are processed by css-loader, which parses url() and resolves them as module requests. This means you can refer to assets using relative paths based on the local file structure. Note if you want to reference a file inside an npm dependency or via webpack alias, the path must be prefixed with ~ to avoid ambiguity.

So basically by using ~ you inform webpack to interpret it. By using @ the path defaults to <projectRoot>/src/

1 Like

First add a slash before assets :

(('/assets/fonts/AcrosstheRoad.ttf'))

That may or may not be the problem, depending on where your CSS file is, and how your website is structured.

If the above doesn’t work, the try this tool to convert the font to .woff2 and .woff. The reasoning behind this is that some browsers are really picky. Change your CSS to:

@font-face {
  font-family: 'AcrosstheRoad';
  src:  url('/assets/fonts/AcrosstheRoad.woff2') format('woff2'),
        url('/assets/fonts/AcrosstheRoad.woff') format('woff');,
       url('/assets/fonts/AcrosstheRoad.ttf') format('truetype');
}