Using Font Awesome 5 with React

  • 时间: 2018-09-23 06:22:34

Font Awesome is an... awesome (sorry I had to) product. React is a brilliant coding library. It would only make sense to use them together. I've been using Font Awesome for a long time and was stoked when their Kickstarter for the new version went live.

There's a whopping 3,978 icons as of the time of this writing!

We use React and Font Awesome together whenever you see an icon here on Scotch. That includes the user navigation, cards, brand icons, and more.

While the Font Awesome team has made a React component to make this integration easy, I found a couple gotchas and had to understand some fundamental things about the new Font Awesome 5 and how it's structured. I'll write up what I found and the ways to use the React Font Awesome component.

Ways to use Font Awesome

Normally, if you were used to how Font Awesome worked in their previous versions, then you would add the .css file to the head of your document and then use something like:

<i class="fa fa-user-happy"></i>

This was cool in the previous version, but the downside was that we had to bring in the entire Font Awesome library even if we only used some fonts

Font Awesome 5

With Font Awesome 5, there are a few different ways we can use the icons.

  1. Using SVG and CSS: This is similar to how we did it before (font-face)
  2. Using SVG and JS: This way, we will use JS to parse our HTML and inject an SVG

The SVG way has benefits detailed by the Font Awesome team and contrary to what I had originally thought, faster than the font-face way.

Another big benefit to the SVG way is that we can pick and choose what fonts we need and only include those in our final bundle size.

The problem with Font Awesome and React together

With the SVG and JS way, the JS to parse our HTML and add the SVG may fire before React has time to mount it's components. So we have to find a way to parse the HTML once React has mounted its components.

Using Font Awesome 5 and React

Lucky for us, the Font Awesome team has created a React component to use Font Awesome with React. With this library, we are able to do the following after you pick your icon . We'll use the boxing-glove icon and do everything right inside App.js

import React from "react";import { render } from "react-dom";// get our fontawesome importsimport { faHome } from "@fortawesome/free-solid-svg-icons";import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";// create our Appconst App = () => (  <div>    <FontAwesomeIcon icon={faHome} />  </div>);// render to #rootrender(<App />, document.getElementById("root"));

Now we have a little home icon! Notice how we can pick out only the home icon so that only one icon is added to our bundle size.

It's tiny and not styled, but we have it!

Now, Font Awesome will make sure that this component will replace itself with the SVG version of that icon once this component is mounted!

I'm placing this section before installing/using because it's important to know how the Font Awesome libraries are laid out. Since there are so many icons , the team decided to split them up into multiple packages.

These packages are differentiated by the following. I'm also placing the package name that you would npm install here:

@fortawesome/fontawesome-svg-core@fortawesome/react-fontawesome@fortawesome/free-regular-svg-icons@fortawesome/pro-regular-svg-icons@fortawesome/free-solid-svg-icons@fortawesome/pro-solid-svg-icons@fortawesome/free-light-svg-icons@fortawesome/free-light-svg-icons@fortawesome/free-brands-svg-icons

When picking and choosing which fonts you want, I recommend visiting the Font Awesome icons page . Notice the filters along the left. Those are very important because they will indicate what package to import your icon from.

In the example above, we pulled the home icon out of the @fortawesome/free-solid-svg-icons package.

Knowing which package an icon belongs to

You can figure out which package an icon belongs to by seeing the filters on the left. You can also click into an icon and see the package it belongs to.

Once you know which package a font belongs to, it's important to remember the three-letter shorthand for that package. Here they are:

fasfarfalfab

You can search for a specific type from the icons page:

Using Icons From Specific Packages

If you browse the Font Awesome icons page page, you'll notice that there are usually multiple versions of the same icon like this one:

In order to use a specific icon, you will need to change up your <FontAwesomeIcon> a little bit. Here's using mutiple types of the same icon from different packages. Remember those three-letter shorthands we talked about earlier.

Note: The below examples won't work until we build an icon library in a few sections.

// solid version<FontAwesomeIcon icon={['fas', 'code']} />// defaults to solid version if not specified<FontAwesomeIcon icon={faCode} />

And the light version using fal :

// light version<FontAwesomeIcon icon={['fal', 'code']} />;

We had to switch our icon prop to be an array instead of a simple string. Normally, the icon would default to the solid ( fas ) version so you could rewrite the above as:

Since the pro fonts are the fonts you have to pay for, they have to be paywalled somehow. How do we authenticate and then npm install ? How does https://npmjs.org handle paid packages?

We are going to add an .npmrc to the root of our application and you can find your secret key in our Font Awesome settings :

Add your .npmrc to the root of your project with the following:

@fortawesome:registry=https://npm.fontawesome.com///npm.fontawesome.com/:_authToken=YOUR-TOKEN-HERE

Installing Font Awesome

I know this part sounds simple, but it actually tripped me up a bit. Since there are multiple versions of an icon, multiple packages, and free/pro packages, installing them all isn't as simple as installing one npm package.

You'll need to install multiple and pick and choose which icons you want. You can:

  1. Install all the packages and then import the individual icons as needed
  2. Install only the packages you want and use the entire thing
  3. Install only the packages you want and import individual icons

For this article, we'll install everything so we can demonstrate the multiple ways:

// the base packagesnpm i -S @fortawesome/fontawesome-svg-core @fortawesome/react-fontawesome// regular iconsnpm i -S @fortawesome/free-regular-svg-iconsnpm i -S @fortawesome/pro-regular-svg-icons// solid iconsnpm i -S @fortawesome/free-solid-svg-iconsnpm i -S @fortawesome/pro-solid-svg-icons// light iconsnpm i -S @fortawesome/free-light-svg-iconsnpm i -S @fortawesome/pro-light-svg-icons// brand iconsnpm i -S @fortawesome/free-brands-svg-icons

Or if you prefer to get them all installed in one go:

// if you just want the free thingsnpm i -S @fortawesome/fontawesome-svg-core @fortawesome/react-fontawesome @fortawesome/free-regular-svg-icons @fortawesome/free-solid-svg-icons @fortawesome/free-light-svg-icons @fortawesome/free-brands-svg-icons// if you have pro enabled and an .npmrcnpm i -S @fortawesome/fontawesome-svg-core @fortawesome/react-fontawesome @fortawesome/free-regular-svg-icons @fortawesome/pro-regular-svg-icons @fortawesome/free-solid-svg-icons @fortawesome/pro-solid-svg-icons @fortawesome/free-light-svg-icons @fortawesome/pro-light-svg-icons @fortawesome/free-brands-svg-icons

We've installed the packages, but haven't actually used them in our application or added them to our app bundles just yet. Let's look at how we can do that now.

Creating an Icon Library

It can be tedious to import the icon you want into multiple files. Let's say you use the Twitter logo in a bunch of places, you don't want to write that whole thing everywhere.

To * import everything in one place * instead of importing each icon into each separate file, we'll create a Font Awesome library .

I like creating a fontawesome.js in the src folder and then importing that into index.js . Feel free to add this file wherever as long as the components you want to use the icons in have access (are child components).

You could even do this right in your index.js or App.js , but I moved it out since this file can get large.

// import the libraryimport { library } from '@fortawesome/fontawesome-svg-core';// import your iconsimport { faMoneyBill } from '@fortawesome/pro-solid-svg-icons';import { faCode, faHighlighter } from '@fortawesome/free-regular-svg-icons';library.add(  faMoneyBill,  faCode,  faHighlighter  // more icons go here);

If you did this in its own file, then you'll need to import into index.js :

import React from 'react';import { render } from 'react-dom';// import your fontawesome libraryimport 'fontawesome';render(<App />, document.getElementById('root'));

Importing an Entire Icon Package

This isn't recommended because you're importing every single icon into your app. Bundle size could get large but if you're so inclined, you can import everything from a package.

Let's say you wanted all the * brand icons * in @fortawesome/free-brands-svg-icons .

import { library } from '@fortawesome/fontawesome-svg-core';import { fab } from '@fortawesome/free-brands-svg-icons';library.add(fab);

fab represents the entire brands package.

Importing Icons individually

The recommended way to use Font Awesome icons is to import them one by one so that your final bundle sizes are as small as possible. Only use what you need.

You can create a library from multiple icons from the different packages like so:

import { library } from '@fortawesome/fontawesome-svg-core';import { faUserGraduate } from '@fortawesome/pro-light-svg-icons';import { faImages } from '@fortawesome/pro-solid-svg-icons';import {  faGithubAlt,  faGoogle,  faFacebook,  faTwitter} from '@fortawesome/free-brands-svg-icons';library.add(  faUserGraduate,  faImages,  faGithubAlt,  faGoogle,  faFacebook,  faTwitter);

Importing the Same Icon from Multiple Styles

What about if you want all the types of boxing-glove for the fab , fas , and fal packages? Import them all as a different name and then add them.

import { library } from '@fortawesome/fontawesome-svg-core';import { faBoxingGlove } from '@fortawesome/pro-light-svg-icons';import {   faBoxingGlove as faBoxingGloveRegular } from '@fortawesome/regular-light-svg-icons';import {   faBoxingGlove as faBoxingGloveSolid } from '@fortawesome/solid-light-svg-icons';library.add(    faBoxingGlove,    faBoxingGloveRegular,    faBoxingGloveSolid );

You can then use them using the different prefixes:

<FontAwesomeIcon icon={['fal', 'boxing-glove']} /><FontAwesomeIcon icon={['far', 'boxing-glove']} /><FontAwesomeIcon icon={['fas', 'boxing-glove']} />

The ability to size icons was always a pain. Font Awesome 5 makes this incredibly easy. I find myself using this a ton .

Once you've installed everything and adding your icons to your Font Awesome library, let's use them and size them. I'll use the light ( fal ) since that's what we use around Scotch.io.

// normal size<FontAwesomeIcon icon={['fal', 'code']} />// named sizing<FontAwesomeIcon icon={['fal', 'code']} size="sm" /><FontAwesomeIcon icon={['fal', 'code']} size="md" /><FontAwesomeIcon icon={['fal', 'code']} size="lg" /><FontAwesomeIcon icon={['fal', 'code']} size="xl" />// numbered sizing (up to 6)<FontAwesomeIcon icon={['fal', 'code']} size="2x" /><FontAwesomeIcon icon={['fal', 'code']} size="3x" /><FontAwesomeIcon icon={['fal', 'code']} size="4x" /><FontAwesomeIcon icon={['fal', 'code']} size="5x" /><FontAwesomeIcon icon={['fal', 'code']} size="6x" />// decimal sizing<FontAwesomeIcon icon={['fal', 'code']} size="2.5x" />

Coloring Icons and Backgrounds

Font Awesome has a cool way of styling the SVGs it uses. It just takes the text-color of the CSS!

If you were to place a <p> tag where this icon were to go, what color would the paragraph be? That's the color of the icon!

<FontAwesomeIcon icon={faHome} style={{ color: 'red' }} />

Font Awesome has a nifty power transforms feature where you can string together different transforms.

<FontAwesomeIcon icon={['fal', 'home']} transform="down-4 grow-2.5" />

You can use any of the transforms found on the Font Awesome site :

  • shrink
  • grow
  • up
  • right
  • down
  • left
  • rotate
  • flip-v
  • flip-h

I've been using this a lot to move icons up/down/left/right to get the positioning perfect next to text or inside of buttons.

When using icons in a spot where they all need to be the same width and uniform, Font Awesome lets us use the fixedWidth prop. For instance, we needed fixed widths for our navigation dropdown:

<FontAwesomeIcon icon={['fal', 'home']} fixedWidth /><FontAwesomeIcon icon={['fal', 'file-alt']} fixedWidth /><FontAwesomeIcon icon={['fal', 'money-bill']} fixedWidth /><FontAwesomeIcon icon={['fal', 'cog']} fixedWidth /><FontAwesomeIcon icon={['fal', 'usd-square']} fixedWidth /><FontAwesomeIcon icon={['fal', 'play-circle']} fixedWidth /><FontAwesomeIcon icon={['fal', 'chess-king']} fixedWidth /><FontAwesomeIcon icon={['fal', 'sign-out-alt']} fixedWidth />

Spinning is a cool trick that I use for form buttons when a form is processing. You can use the spinner icon to make a nice loading effect.

<FontAwesomeIcon icon={['fal', 'spinner']} spin />

You can use the spin prop on anything!

<FontAwesomeIcon icon={['fal', 'code']} spin />

Advanced: Masking Icons

I haven't used this too much yet, but Font Awesome let's you combine two icons to make some cool effects with masking .

All you have to do is define your normal icon and then use the mask prop to define a second icon to lay on top. The first icon will be constrained within the masking icon.

We created our Tag Filters using masking:

<FontAwesomeIcon  icon={['fab', 'javascript']}  mask={['fas', 'circle']}  transform="grow-7 left-1.5 up-2.2"  fixedWidth/>

Notice how you can chain together multiple transform props to move the inner icon to fit inside the masking icon.

We even colorize and change out the background logo with Font Awesome:

Using react-fontawesome and Icons Outside of React

This is a tricky problem to have. Let's say that your entire site isn't a single-page-app (SPA). You have a traditional site and have sprinkled React on top , much like our own Scotch.io.

It wouldn't be good to import the main SVG/JS library and then also import the react-fontawesome library. So which do we choose?

The Font Awesome team has seen this and has provided a way to use the React libraries to watch for icons outside of React components .

If you have any <i class="fas fa-stroopwafel"></i> , we can tell Font Awesome to watch and update those using:

import { dom } from '@fortawesome/fontawesome-svg-core'dom.watch() // This will kick of the initial replacement of i to svg tags and configure a MutationObserver

MutationObserver 's are a cool new web technology that allow us to watch the DOM for changes performantly. Find out more about this technique on the React Font Awesome docs.

Using Font Awesome and React together is a great pairing. The move to the multiple packages and styles of icons threw me off when I first started using the two together. Hopefully this helped you out and you are well on your way to adding those hundreds of great icons to your projects.