Our Blog

Ongoing observations by End Point people

Vue, Font Awesome, and Facebook/​Twitter Icons

By David Christensen
July 12, 2018

some Font Awesome fonts

Overview

Font Awesome and Vue are both great technologies. Here I detail overcoming some issues when trying to get the Facebook and Twitter icons working when using the vue-fontawesome bindings in the hopes of saving others future debugging time.

Detail

Recently, I was working with the vue-fontawesome tools, which have recently been updated to version 5 of Font Awesome. A quick installation recipe:

$ yarn add @fortawesome/fontawesome
$ yarn add @fortawesome/fontawesome-svg-core
$ yarn add @fortawesome/free-solid-svg-icons
$ yarn add @fortawesome/free-brands-svg-icons
$ yarn add @fortawesome/vue-fontawesome

A best practice when using Font Awesome is to import only the icons you need for your specific project instead of the thousand+, as this just contributes to project bloat. So in our main.js file, we import them like so:

// Font Awesome-related initialization
import { library } from '@fortawesome/fontawesome-svg-core'
import { faEnvelope, faUser } from '@fortawesome/free-solid-svg-icons'
import { faFacebook, faTwitter } from '@fortawesome/free-brands-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'

// Add the specific imported icons
library.add(faEnvelope)
library.add(faUser)
library.add(faFacebook)
library.add(faTwitter)

// Enable the FontAwesomeIcon component globally
Vue.component('font-awesome-icon', FontAwesomeIcon)

This allows you to include icons in your view components like so:

<template>
  <div class="icons">
    <font-awesome-icon icon="user"/>
    <font-awesome-icon icon="envelope"/>
  </div>
</template>

This worked fine for me until I tried to use the facebook and twitter icon:

<template>
  <div class="icons">
    <font-awesome-icon icon="user"/>
    <font-awesome-icon icon="envelope"/>
    <font-awesome-icon icon="twitter"/>  <!-- broken -->
    <font-awesome-icon icon="facebook"/> <!-- broken -->
  </div>
</template>

Only blank spots and errors in the browser console like so:

[Error] Could not find one or more icon(s) (2)
{prefix: "fas", iconName: "twitter"}
{}
[Error] Could not find one or more icon(s) (2)
{prefix: "fas", iconName: "facebook"}
{}

After turning up dry from a run to the Google well and scanning the docs, I determined that this must come down to a difference in the prefix; since the icons that worked were being imported from the free-solid-svg-icons library, it would seem that that was the source of the fas prefix. Since the non-working icons were coming from the free-brands-svg-icons library it stood to reason that somehow passing in a prefix parameter of fab would work.

I tested modifying things like follows, just to exercise potentially obvious answers. Sadly, this did not result in workage.

<template>
  <div class="icons">
    <font-awesome-icon icon="user"/>
    <font-awesome-icon icon="envelope"/>
    <font-awesome-icon icon="twitter" prefix="fab"/>  <!-- still broken -->
    <font-awesome-icon icon="fab-facebook"/>          <!-- also still broken -->
  </div>
</template>

I finally took to the original source for the FontAwesomeIcon component (every engineer’s favorite thing, aside from brown paper packages tied up with string), and noted the following:

function normalizeIconArgs (icon) {
  if (icon === null) {
    return null
  }

  if (typeof icon === 'object' && icon.prefix && icon.iconName) {
    return icon
  }

  if (Array.isArray(icon) && icon.length === 2) {
    return { prefix: icon[0], iconName: icon[1] }
  }

  if (typeof icon === 'string') {
    return { prefix: 'fas', iconName: icon }
  }
}

AHA! The icon parameter is what was passed in in the <font-awesome-icon> component, so I immediately attempted to utilize an object to pass the prefix and the iconName parameter (since this is the name in the object referenced here, it should be the key).

So I ended up trying:

<template>
  <div class="icons">
    <font-awesome-icon icon="user"/>
    <font-awesome-icon icon="envelope"/>
    <font-awesome-icon :icon="{ prefix: 'fab', iconName: 'twitter' }"/>
    <font-awesome-icon :icon="{ prefix: 'fab', iconName: 'facebook' }"/>
  </div>
</template>

(I am omitting the part where I stupidly left out the leading : to pass in an explicit object instead of a string equivalent.)

Everything worked! And there was much rejoicing! Hope this helps someone else who had the same issue as me.

vue javascript


Comments

Popular Tags


Archive


Search our blog