Use Bulma and FontAwesome 5 with Nuxt.js
Tags: nuxt, bulma, vue, node
Published: 2019-09-07 22:36:10

### So, you created a new boilerplate site using Nuxt.js. Now what?

Well, maybe you'll want to use a CSS framework to get started with styling your site. Sure, using a framework comes with its own set of advantages and disadvantages, but honestly it can be a great place to start.

If you haven't heard of [Bulma](https://https;//bulma.io) yet, I recommend checking it out, since it's pretty awesome. Its class names make a lot of sense, it comes with a good number of components and prefabs out-of-the-box, but not too many that it can be overwhelming if you haven't used it before (looking at you, [Vuetify](https://vuetifyjs.com)... OK, Vuetify's great too, and it's definitely worth spending the time to get used to it, but this article's about Bulma, so there.)

Anyway, once you have your site all set-up, open up your favourite code editor in your site's project folder, and add Bulma to your `package.json`:

```bash
$ yarn add bulma
```

Next, you're going to want to add Bulma to your site by importing it. There are actually a few ways of doing this, but the way I'm going to explain it seemed to work for me, so feel free to follow along.

1. Create a `main.scss` file in your site's `assets/scss/` folder.
2. Import Bulma's utilities file with the following line of code:

```scss
@import "~bulma/sass/utilities/_all";
```
3. Add your customizations (like custom brand colours, in this case - see [https://bulma.io/documentation/customize/](https://bulma.io/documentation/customize/) for more info):

```scss
/* Custom colours:
   (These are what we use on our website,
   https://overscorestudios.ml,
   so feel free to experiment with your own
   colours/variables - see https://bulma.io/documentation/customize/
*/

$primary: hsl(242, 100%, 76%);
$primary-invert: findColorInvert($primary);

$info: hsl(337, 55%, 58%);
$info-invert: findColorInvert($info);

$light: hsl(275, 20%, 83%);
$light-invert: findColorInvert($light);

$dark: hsl(0, 0%, 15%);
$dark-invert: findColorInvert($dark);

$link: hsl(242, 100%, 76%);
$link-invert: findColorInvert($link);

$link-hover: hsl(229, 19%, 66%);
$link-focus: hsl(229, 19%, 66%);

$strong-color: hsl(229, 19%, 66%);

$colors: (
    "white": ($white, $black),
    "black": ($black, $white),
    "link": ($link, $link-invert),
    "light": ($light, $light-invert),
    "dark": ($dark, $dark-invert),
    "primary": ($primary, $primary-invert),
    "info": ($info, $info-invert),
    "success": ($success, $success-invert),
    "warning": ($warning, $warning-invert),
    "danger": ($danger, $danger-invert)
);

```

4. Import the rest of Bulma:

```scss
// The rest of Bulma
@import '~bulma';
```

5. Get Nuxt to import your custom styles in all of your custom .Vue files by installing [@nuxtjs/style-resources](https://github.com/nuxt-community/style-resources-module):

```bash
$ yarn add @nuxtjs/style-resources
```

6. Finally, get Nuxt to recognize your `main.scss` file by editing the `nuxt.config.js` file in two places:

```js
  css: [
    '~/assets/scss/main.scss',
  ],

  // ^ Add your main.scss file to Nuxt's Global CSS array
```

```js
  modules: [
    '@nuxtjs/style-resources'
  ]

  // ^ Make sure to add @nuxtjs/style-resources to Nuxt's modules array
  // (Remember to add a comma if you have more than one module already)
```


## Cool Beans

Now, without any additional finagling, you should be able to use all of Bulma's classes - along with any custom colours - in your .Vue components!

Speaking of which, let's create some components for FontAwesome 5 icons!

## Font Whosome?

[FontAwesome 5](https://fontawesome.com/) is a free/premium icon font, one that's super-popular and used on a lot of sites. It includes icons for a lot of major brands, emoji, and a plethora of others that will undoubtedly be useful while you're building your site.

Again, there are a lot of ways to go about adding FontAwesome 5 to your Nuxt site, and if you out there in Internet-land have any suggestions for alternative methods, leave them in the comments below. :]

## The big import

In order to use FontAwesome, you'll have to import it. In this case, we'll be using the SVG icon set they offer, though there's also a webfont and a few other things.

Here's the command to install the Node packages you'll need:

```bash
$ yarn add @fortawesome/fontawesome-svg-core &&
$ yarn add @fortawesome/free-brands-svg-icons &&
$ yarn add @fortawesome/free-solid-svg-icons &&
$ yarn add @fortawesome/vue-fontawesome &&
$ yarn add nuxt-fontawesome
```

Feel free to add all of the packages using the same command; it just is easier to show them like this. Basically, you'll need FontAwesome 5 Free's packages for SVG brand/solid icons, as well as their importer packages (for JavaScript in general, and for Vue and Nuxt in specific).

Now, add `nuxt-fontawesome` to your `nuxt.config.js` modules list:

```js
  modules: [
    '@nuxtjs/style-resources',
    'nuxt-fontawesome' // Imports FontAwesome 5 SVG icons
  ]
```

Next, add an array to your `nuxt.config.js` that looks something like this:

```js
  fontawesome: {
    imports: [
      {
        set: '@fortawesome/free-solid-svg-icons', // Solid icons
        icons: ['faCookieBite', 'faCommentDots', 'faEnvelope', 'faGrinWink', 'faHeart']
      },
      {
        set: '@fortawesome/free-brands-svg-icons', // Brand icons
        icons: ['faDev', 'faFacebook', 'faTwitter', 'faInstagram', 'faYoutube', 'faGithub']
      }
    ]
  },
```

Now, you may have noticed that in the above code snippet, I imported a few icons from the Solid set and the Brands set. You technically *can* import all of them, but I'd really advise against it (unless for some inane reason you actually needed *all* of them), since keeping your imports smaller keeps your site's bundle size smaller, and your load-times faster!

That being said, you can look up what icons you want to use [on FontAwesome's website](https://fontawesome.com/icons?d=gallery&m=free). Make sure you import any icons using the following schema:

```
Icon Name: adobe
Import Name: faAdobe (in the brands icons array)

Icon Name: align-left
Import Name: faAlignLeft (in the solid icons array)
```

If you can't seem to get the hang of it, you can always peer into the murky depths of your site's `node_modules` folder, in the `@fortawesome/free-brands-svg-icons/` or `@fortawesome/free-solid-svg-icons` folder, and look for the name of the icon you want to import - you'll notice two of each because [TypeScript](https://www.typescriptlang.org/) exists and each icon's JS file has a corresponding TypeScript definition file.

## Almost There!

Now, you imported the icons, but how do you make them work in your .Vue files?

I chose to create custom components for them, `Fas.vue` for solid icons and `Fab.vue` for brand icons:

```vue
<!--- components/Fas.vue -->

<!---
  FontAwesome 5 Free Solid Icon Component

  Usage Example:

  <Fas i="arrow-down" />

  Props:
  - i: The FontAwesome 5 Free Solid icon name (like "arrow-up" or "ad")
  - classes: CSS classes to add to the icon

  Caveats:
  - Each icon has to be pre-loaded in nuxt.config.js or it won't show up

-->
<template>
  <font-awesome-icon :class="`${classes}`" :icon="['fas', i]" />
</template>

<script>
export default {
  props: {
    i: {
      type: String,
      required: true,
      default: 'arrow-down'
    },
    classes: {
      type: String,
      required: false,
      default: 'icon is-medium'
    }
  }
}
</script>

```

```vue
<!--- components/Fab.vue -->

<!---
  FontAwesome 5 Free Brands Icon Component

  Usage Example:

  <Fab i="facebook" />

  Props:
  - i: The FontAwesome 5 Free Brands icon name (like "twitter" or "reddit")
  - classes: CSS classes to add to the icon

  Caveats:
  - Each icon has to be pre-loaded in nuxt.config.js or it won't show up

-->
<template>
  <font-awesome-icon :class="`${classes}`" :icon="['fab', i]" />
</template>

<script>
export default {
  props: {
    i: {
      type: String,
      required: true,
      default: 'facebook'
    },
    classes: {
      type: String,
      required: false,
      default: 'icon is-medium'
    }
  }
}
</script>

```

Is it worth explaining exactly how/why these work? Well, probably not. I really don't think I'm great at teaching Vue to someone who's completely new to it, though I *can* say that it only took me about 3 months to get confident with using Vue, fiddling around with it on/off. Honestly, it wasn't until I started using Nuxt that it all began to click, and in a couple weeks of off/on experimenting I think I have a pretty good idea of how it works.

My advice to Vue-newbies is honestly to just try building a website from scratch using Vue (or Nuxt, since I really think it does much of the "dirty work" for you, allowing you to focus on writing quality, readable, testable, powerful code). If you already know how to build a website, then it shouldn't be too hard - just get there and try it. If you don't know where to start, I can't recommend [FreeCodeCamp](https://www.freecodecamp.org/) enough.

## But how though?

Here's an example of a `Fab.vue` component being used in the wild:

```vue
<a href="https://facebook.com/overscorestudios" target="_blank" rel="noreferrer" aria-label="Like us on Facebook">
  <Fab i="facebook" />
</a>
```

Don't forget to import all custom components in your page/component/layout's `<script>` tag:

```js
import Fab from '~/components/Fab.vue

export default {
  components: {
    Fab
  }
}
```

And, you might have noticed that I added an `aria-label` to the `<a>` tag in which the `<Fab />` was. I'm pretty sure this does what I want it to do - namely, allow screen-reader users to understand what the icon they can't see actually means. Again, I'm no expert on any of this, but from what I can tell it does its job. Make sure to always have accessible fallbacks like that for icons. If they're just decorative, I guess you probably don't need them, but if they are for buttons/links or anything interactive, or if they are important in the context of your page somehow, they really should have `aria-label`s or something like that. Again, feel free to discuss in the comments.

Well, there you have it! Bulma and FontAwesome should be up-and-running!

Next, I'll cover how to get PurgeCSS to work (to keep your bundle sizes small), how to add a cookie consent banner (and ethical tracking with Matomo), how to add Anime.js (for nifty animations), Typed.js (for typing animations), and Prism.js (for syntax highlighting) to your site, and how to add a news page with Netlify CMS - among other things.

In the mean time, if you're following along and creating a site of your own, it's probably about time to make a Git commit:

```sh
git add .
git commit -am "Add Bulma CSS and FontAwesome 5"
git push
```