CTO and co-founder of Signal Sciences. Author and speaker on software engineering, devops, and security.

Using Font Awesome Icons in Hugo

If you just need a icon or two for your website, you can directly embed the icons you need and skip with network. Here’s how.

Icons are now essential for websites. According to Font Awesome, it’s icons are used in 100M websites. Traditional methods for using icons can involve loading a web font, a sprite, or script. That’s a lot of work if you need a single icon or two in the nav. With Hugo we can preload the SVG icons, and inject them into our page with partial template or shortcode, skipping the network. The example will use Font Awesome, but the technique will work many other icon systems.

The Traditional Way

There are few choices, but the current and traditional way of adding Font Awesome icons is to add this in your page footer (or header). For Hugo, this would go into your header or footer partial template:

<script defer src="/static/fontawesome/fontawesome-all.js"></script>

and referring to the icon using something like:

<i class="fab fa-github"></i>

This is certainly easy and provides the full range of icons (and some extra features). However:

  • this forces a network dependency on your website
  • since it’s a script and deferred, there is a cost and a (small) delay in processing.
  • may or may not trigger a repaint / reflow event

If you are a performance maniac, this is a high cost to pay for a 300-byte GitHub icon used in the navigation bar.

The Embedded Way

Font Awesome and many other icon foundries now provide SVG versions of the their icons. With this we can directly embed the icon that is needed without any scripting or network call. It’s final form, we’ll make a partial template and call it as:

{{ partial "fontawesome.html" "github" }} 

or even simpler with a shortcode in content:

{{% fontawesome github %}}

Both use no network calls. Here’s how to do it.

Create a icon directory

We need a place to put our SVG icons. Create a fontawesome directory at the top level of your hugo project. That is, it should be parallel to your content directory. This directory will not be published to your website.

Download the icons you want.

SVG icons are hosting in the FontAwesome/Font-Awesome repo in the advanced-options/raw-svg directory. Find the icon you want in here. For example here’s the GitHub Icon. Click on the raw button and you’ll see the raw SVG version. Save this locally to your fontawesome directory.

Since I hate doing anything manually, I made a script to do this. Adjust to your environment and needs:

#!/bin/sh
set -ex
icons="twitter github"
dest=fontawesome
url=https://raw.githubusercontent.com/FortAwesome/Font-Awesome/master/advanced-options/raw-svg/brands
mkdir -p "${dest}"
for icon in $icons; do
  icon="${icon}.svg"
  wget -O "${dest}/${icon}" "${url}/${icon}"
done

Make a partial template

Create a fontawesome.html file in your layout/partials directory with:

<span class="inline-svg" >
{{ readFile ( print "fontawesome/" . ".svg" ) | safeHTML  }}
</span>

This works for plain text but has problems if it’s used with hover and focus events that change color. To fix this fill=currentColor needs to be added to the SVG <path> element. A more full featured version of the template might be:

<span class="inline-svg" >
{{- $fname:=print "fontawesome/" . ".svg" -}}
{{- $path:="<path" -}}
{{- $fill:="<path fill=\"currentColor\"" -}}
{{ replace (readFile $fname) $path $fill | safeHTML }}
</span>

Style it

You need to add some style or else the icon will not render at all. This is where is get a little hacky. You’ll have to adjust the size to make sure it fits in with your text. This worked for me, but likely you’ll need to adjust the height, width, top (to push the icon down a bit to match the text line). Elliot Dalh wrote up more details in Align SVG Icons to Text and Say Goodbye to Font Icons.

.inline-svg {
  display: inline-block;
  height: 1.15rem;
  width: 1.15rem;
  top: 0.15rem;
  position: relative;
}

Use it in layouts

As advertised in the introduction, you can use the icon in your layouts or other partials using:

{{ partial "fontawesome.html" "github" }}

Shortcodes

If you want your content to use icons, then you need to use a shortcode. It’s almost the same:

<span class="inline-svg" >
{{- $fname:=print "fontawesome/" ( .Get 0 ) ".svg" -}}
{{- $path:="<path" -}}
{{- $fill:="<path fill=\"currentColor\"" -}}
{{ replace (readFile $fname) $path $fill | safeHTML }}
</span>

Place this fontawesome.html in layouts/shortcodes and use it as:

{{% fontawesome github %}}

Conclusion

One can add as many icons as needed, but there is only partial or shortcode for all of them. While Font Awesome’s javascript library and CDN offer additional features, if you just need an icon or two, it’s hard to beat using a shortcode or partial template with Hugo.

hugo webdev

© 2018 Nick Galbreath