Search code examples
vue.jsbuildfont-awesomeweb-component

Font Awesome not rendering in Vue built Web Component


I have a Vue component that I'm compiling into a web component using the following build command:

npm run build -- --target wc --name projName src\components\server-config.vue

I'm missing something though in my Vue file cause the web component won't render the font awesome icons. Here is what it looks like when I, "npm run serve"

Correct Looking example

This is what it looks like after I compile it into a web component and open it in demo.html: enter image description here

I see several issues:

  • Fonts are different
  • Missing Eye button for peeking the password
  • Checkbox box is missing (though if you mouse over it you still get a glow effect)
  • Eye icon is missing. (Just included as a test outside of Vuetify)

How can I properly include fonts into my component? Here is my current vue file:

<template>
    <div style="text-align: center; font-family: sans-serif">
      <v-text-field label="Password" class="mx-4" v-model="password" :type="showPass ? 'text' : 'password'" @click:append="showPass = !showPass" :append-icon="showPass ? 'far fa-eye' : 'far fa-eye-slash'"></v-text-field>
      <v-checkbox class="mx-4" v-model="useIntegratedAuthentication" label="Use Integrated Authentication" ></v-checkbox>
      <div>
        <i class="far fa-eye"></i>
        <span>My eye here</span>
    </div>
    </div>
</template>

<style scoped>
  @import '../../node_modules/vuetify/dist/vuetify.min.css';
  @import 'https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900';
  @import 'https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css';
</style>

<script src="https://kit.fontawesome.com/XXXXXXXXX.js" crossorigin="anonymous"></script>
<script lang="ts">
import { VTextField, VCheckbox } from 'vuetify/lib';
import vuetify from '@/plugins/vuetify';
import Vue from 'vue';

export default Vue.extend({
  vuetify,
  components: {
    VTextField, VCheckbox
  },
  data() {
    return {
      showPass: false,
      password: '',
      useIntegratedAuthentication: false
    };
  }
})

</script>

Solution

  • Figured out a workable solution. You need to load the font-faces inside a script tag after the component is mounted:

    mounted() {
      const css = `
    @font-face {
      font-family: 'Font Awesome 5 Free';
      font-style: normal;
      font-weight: 400;
      font-display: block;
      src: url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-brands-400.eot);
      src: url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-brands-400.woff2) format("woff2"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-brands-400.woff) format("woff"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-brands-400.ttf) format("truetype"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-brands-400.svg#fontawesome) format("svg")
    }
    
    @font-face {
      font-family: 'Font Awesome 5 Free';
      font-style: normal;
      font-weight: 400;
      font-display: block;
      src: url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-regular-400.eot);
      src: url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-regular-400.eot?#iefix) format("embedded-opentype"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-regular-400.woff2) format("woff2"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-regular-400.woff) format("woff"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-regular-400.ttf) format("truetype"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-regular-400.svg#fontawesome) format("svg")
    }
    
    @font-face {
      font-family: 'Font Awesome 5 Free';
      font-style: normal;
      font-weight: 900;
      font-display: block;
      src: url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-solid-900.eot);
      src: url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-solid-900.woff2) format("woff2"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-solid-900.woff) format("woff"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-solid-900.ttf) format("truetype"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-solid-900.svg#fontawesome) format("svg")
    }`;
    
      // if our style is already injected we do not need to inject it a second time
      if (!document.getElementById('myCustomInjectedStyle')) {
        const head = document.head || document.getElementsByTagName('head')[0];
        const style = document.createElement('style');
        style.id = 'myCustomInjectedStyle';
        style.type = 'text/css';
        style.innerText = css;
        head.appendChild(style);
      }
    },
    

    I never got material designs to work for the checkbox so I updated my vuetify.ts file to always use font awesome.

    import Vue from 'vue'
    import Vuetify from 'vuetify/lib/framework'
    
    Vue.use(Vuetify)
    
    export default new Vuetify({
        icons: {
            iconfont: 'fa'
        }
    })