Vue Cli 3 Local fonts not loading

22,839

Solution 1

Did you try

@font-face {
font-family: 'OpenSans-Regular';
src: url('~@/assets/fonts/OpenSans-Regular.eot');
src: url('~@/assets/fonts/OpenSans-Regular.eot?#iefix') format('embedded-opentype'),
     url('~@/assets/fonts/OpenSans-Regular.otf') format('font-opentype'),
     url('~@/assets/fonts/OpenSans-Regular.woff') format('font-woff'),
     url('~@/assets/fonts/OpenSans-Regular.ttf') format('font-truetype'),
     url('~@/assets/fonts/OpenSans-Regular.svg#OpenSans-Regular') format('svg');
font-weight: normal;
font-style: normal;
}

Works for me Vue CLI 3, no vue.config.js settings.

I'm loading my styles like this:

import Vue from 'vue';

import router from './router';
import store  from './store';
// eslint-disable-next-line
import styles from './scss/app.scss';

import App from './App.vue';

Vue.config.productionTip = false;

new Vue({
    router,
    store,
    render: h => h(App)
}).$mount('#app');

Not sure if that is good practice.

Solution 2

What I ended up doing was moving to a file loader method to get the fonts to package over and set the the public path.

vue.config.js

module.exports = {
  assetsDir: 'assets/',
  publicPath: '/', // Base directory for dev
  css: {
    sourceMap: true,
    loaderOptions: {
      sass: {
        data: `@import "@/styles/main.scss";`
      }
    }
  },
  chainWebpack: config => {
    config.module
      .rule("fonts")
      .test(/\.(ttf|otf|eot|woff|woff2)$/)
      .use("file-loader")
        .loader("file-loader")
        .tap(options => {
          options = {
            // limit: 10000,
            name: '/assets/fonts/[name].[ext]',
          }
          return options
        })
        .end()
  }
};

File-loader doesn't see the files unless called in the js so I imported them in main.js The console log is to navigate around the linter flagging unused imports

// Fonts need to be called in js for webpack to see and copy over
import OpenSansReg from './assets/fonts/OpenSans-Regular.ttf';
import OpenSansLight from './assets/fonts/OpenSans-Light.ttf';
import OpenSansBold from './assets/fonts/OpenSans-Bold.ttf';


console.log(OpenSansReg, OpenSansBold, OpenSansLight);

then in one of my scss files

@font-face {
    font-family: 'OpenSans-Regular';
    src: url('/assets/fonts/OpenSans-Regular.eot?#iefix') format('embedded-opentype'),
         url('/assets/fonts/OpenSans-Regular.otf') format('opentype'),
         url('/assets/fonts/OpenSans-Regular.woff') format('woff'),
         url('/assets/fonts/OpenSans-Regular.ttf') format('truetype'),
         url('/assets/fonts/OpenSans-Regular.svg#OpenSans-Regular') format('svg');
    font-weight: normal;
    font-style: normal;
}

Solution 3

For me, I just took out that 'format()' thing and works... Finally..

Solution 4

I stuck my custom icon-font in the head tags of my initial index.html page Which also has a custom font import. The same page that you would stick your <div id="vue-app"></div>. All the other pages /components can use the font-family for me.

<head> ... <link rel="stylesheet" href="icon-font/styles.css" /> </head>

But if i try any other location in the project it fails. and the Scss doesnt even compile.

Share:
22,839
P. Jack
Author by

P. Jack

Updated on March 18, 2021

Comments

  • P. Jack
    P. Jack about 3 years

    When trying to load custom local fonts in Vue CLI 3 the fonts still will not appear. I am not receiving any error messages. The inspector shows the correct rule being loaded, but fonts are falling back to serif on #app. Fonts are not showing up in my dist folder anywhere.

    I have tried adding loaders in vue.config.js, changing url paths, and moving the @font-face rules around to different locations, changing the public path to ' ' and '/', importing scss into main.js.

    Font loading:

    @font-face {
        font-family: 'OpenSans-Regular';
        src: url('/assets/fonts/OpenSans-Regular.eot');
        src: url('/assets/fonts/OpenSans-Regular.eot?#iefix') format('embedded-opentype'),
             url('/assets/fonts/OpenSans-Regular.otf') format('font-opentype'),
             url('/assets/fonts/OpenSans-Regular.woff') format('font-woff'),
             url('/assets/fonts/OpenSans-Regular.ttf') format('font-truetype'),
             url('/assets/fonts/OpenSans-Regular.svg#OpenSans-Regular') format('svg');
        font-weight: normal;
        font-style: normal;
    }
    

    And use within App.vue:

    <style lang="scss">
    #app {
      font-family: 'OpenSans-Regular', serif;
    }
    </style>
    

    That styling is placed within my main.scss file. The file structure as follows:

    src
      assets
        fonts
          OpenSans-Regular.eot
          OpenSans-Regular.woff
          etc
      styles
        main.scss
      App.vue
    vue.config.js
    

    vue.config.js file is as follows:

    module.exports = {
      publicPath: '/',
      css: {
        sourceMap: true,
        loaderOptions: {
          sass: {
            data: `@import "@/styles/main.scss";`
          }
        }
      },
      configureWebpack: {
        module: {
          rules: [{
            test: /\.(ttf|otf|eot|woff|woff2)$/,
            use: {
              loader: "file-loader",
              options: {
                name: "fonts/[name].[ext]",
              },
            },
          }]
        }
      }
    }
    

    I have also tried a chainWebpack in vue.config.js to no avail:

    chainWebpack: config => {
        config
          .module
          .rule("file")
          .test(/\.(woff2?|eot|ttf|otf)(\?.*)?$/,)
          .use("url-loader")
          .loader("url-loader")
          .options({
            limit: 10000,
            name: 'assets/fonts/[name].[ext]'
          })
          .end();
      }
    
  • Mr. Alien
    Mr. Alien over 4 years
    wow, trying since 2 hours by using chainWebpack methods and what not, this works, absolutely no idea why...
  • Brenddon Anjos
    Brenddon Anjos about 4 years
    Works for me to, Save my life
  • Taras Kryvko
    Taras Kryvko about 4 years
    @Joeri what do you mean by this "// eslint-disable-next-line" I can't do it, I get an error "Cannot find module .."
  • Joeri
    Joeri about 4 years
    @TarasKryvko If you don't use a Lint then remove that line. My linter (syntax checker) does not like me importing to a lib into a var that I don't use in my code.
  • Lyokolux
    Lyokolux almost 4 years
    Yes thank you :+1: As I use scss, @import works for me in the <style lang="scss"> in .vue files
  • Daniel_Knights
    Daniel_Knights almost 4 years
    Saved me headache!
  • Sjoerd Oudman
    Sjoerd Oudman over 3 years
    Thanks Joeri, ~@/assets did it for me two
  • chrizonline
    chrizonline over 3 years
    If you have lint, you can just import "./scss/app.scss";
  • Robin Huy
    Robin Huy almost 3 years
    Why I using @/assets in the CSS file is not working, but it works when import Component. In CSS I must use ~@/assets. What is the difference?