Hugo + resources = inline svg icons

Hugo + resources = inline svg icons


Updated 2021-05-13: Minor rewording & added license free fonts link

Example on how to add custom svg icons which are configurable and easy to use in the content and/or your HTML layout when using Hugo.

This article was written for Hugo 0.70.

There are multiple ways of showing icons on a webpage, one can use a sprite (1 big image that contain all icons), have a script generate and/or fetch them, use a custom font + CSS or inline/embed the svg data directly in HTML. Each have their pro’s and cons, if you only have a few icons on your website inlining is probably the most efficient which is what will be demonstrated in this post.

Many people use fontawesome to show icons on their Hugo website since it is highly optimized, easy to use and has a very extended (free) icon library. It supports all approaches mentioned above and can be configured to only include what you need; however usually people do not bother and add everything wasting bandwidth.

Inline/embedded svg icons

Create a /svg folder in your Hugo asset directory which contains all the svg files1. Give the files clear names, they will be used to refer to icons in HTML/content.

How you add the icons to the folder is up to you. They can be added manually (downloaded/created) or, with a script, before running Hugo automatically download/generate them and add them to the folder.

Make sure the svg files you use are minimized (e.g. use svgomg) as they will be copied verbatim in HTML.

Usage

If you want to show assets/svg/heart.svg simply use this your layout:

{{ partial "inline-svg" "heart"}}

If you want to configure the icons in the config/front matter you can add a variable, e.g.:

[params]
myIcon = "heart"
{{ partial "inline-svg" .Site.Params.myIcon }}

You can also use icons in your (markdown) content if you convert the partial to a shortcode. There are no additional options.

Example

Some text goes here {{< inline-svg "heart" >}} and here.

Some text goes here and here.

Code

The partial will get the corresponding svg file from the assert folder and inline its content. Add the partial in layouts/partials/inline-svg.html.

{{ $svg := resources.Get (print "svg/" . ".svg") }}
<i class="inline-svg" >{{ $svg.Content | safeHTML }}</i>

The shortcode, which just calls the partial. Add the shortcode in layouts/shortcodes/inline-svg.html.

{{- partial "inline-svg" (.Get 0) -}}

The accompanying SCSS.

.inline-svg {
  display: inline-block;
  vertical-align: middle;

  svg {
    width: 1em;
    height: 1em;
    fill: currentColor;
    display: inline-block;
  }
}

One can extend the partial/shortcode to allow specifying additional parameters, e.g. classes to customize the icons or colors, by default they have the same color and height as the surrounding text (as specified in SCSS).

Limitations

Downsides of inlining are bloated HTML2 and not being able to use icons in CSS/Javascript (only works for files parsed by Hugo). If these are no issues for your use-case inlining svg icons is probably the best way to go (performance/efficiency wise).

Alternative

If you need to use icons from CSS/Javascript your are probably better of using a webfont, for example fontawesome (be mindful of the license!). There are plenty of font options (free, even for commercial use).

Adding fontawesome is trivial, load the CSS file and off you go.

<link defer href="{{ "css/fontawesome-all.min.css" | relURL }}" rel="stylesheet">
or use a CDN instead of hosting it yourself (in Hugo’s static folder).

In HTML use the following, or set the class with Javascript.

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

Emoji support

Besides custom svg files one can also use emoji’s which Hugo supports out of the box. The emojify function can be called directly in templates or inline shortcodes.
The Emoji cheat sheet is a useful reference for emoji shorthand codes.

🙈 :see_no_evil: 🙉 :hear_no_evil: 🙊 :speak_no_evil:

Note even with enabled Unicode Standard emoji characters and sequences support in Hugo, rendering of these glyphs depends on the browser and the platform. To uniformly style the emoji you should either use a third party emoji font or a font stack; create a shortcode and wrap them in a CSS class for a more consistent cross browser experience.

.emoji {
	font-family: Apple Color Emoji,Segoe UI Emoji,NotoColorEmoji,Segoe UI Symbol,Android Emoji,EmojiSymbols;
	font-size: 2rem;
	vertical-align: middle;
}

  1. to reduce the size of your HTML, especially if you use a lot of icons and/or complex icons make sure to minify them (can also be done by Hugo). ↩︎

  2. the svg data is copied for every occurrence of that icon , so if you have 100x the same icons the svg data is included 100 times at which point fetching a svg file or using a webfont is more efficient bandwidth wise. ↩︎

Noticed an error in this post? Corrections are appreciated.

© Nelis Oostens