Introduction

Avoid unnecessary decoration - only use icons if there’s a real user need:

  • if icons are needed ensure they are clear, simple and accompanied by relevant text
  • don’t hide functionality under icons
  • icons should be easily recognizable
  • keep icon designs simple and schematic.

We use two types of icons: unicode glyphs and a custom icon font:

Unicode icons

We use unicode symbols as icons because:

  • there are over 136,000 of them
  • they don't require a download so are better for performance.

Use unicode symbols instead of SVGs icons wherever possible. If there is no unicode symbol available, then use an icon from our icon font.

Unicode glyphs

We use a few unicode glyphs within our core code. These are available for by name to avoid using 'magic strings' in code:

{% assign unicode = site.data.sass.nice-design-system.items | where_exp: "item","item.context.name == 'nice-glyphs'" | first %}
<div class="grid">
    {% for glyph in unicode.property %}
        <div data-g="6 xs:4 md:3 lg:2" class="text-center">
            <div class="h2">
                &#x{{ glyph.resolvedValue }};
            </div>
            <p>
                {{ glyph.name }}
            </p>
        </div>
    {% endfor %}
</div>

Usage in SASS

SASS map

The core unicode glyphs we use are defined within the [$nice-glyphs map]({{ site.baseurl }}{% link technical/sass/documentation/helpers.md %}#nice-glyphs).

This map can be overriden in your application if you use different glyphs, or can be added to over time within the core code.

SASS function

The [get-glyph function]({{ site.baseurl }}{% link technical/sass/documentation/helpers.md %}#get-glyph) is a convenient way to use a unicode glyph without needing to know its codepoint. For example:

.rule:before {
    content: get-glyph(greater-than);
}

Usage in markup

To use a unciode icon in markup, you must set $nice-output-glyph-classes: true so that the classes are generated. Note: this is set to false by default to reduce the size of our CSS.

Usage follows this pattern:

<span class="glyph glyph--greater-than" aria-hidden="true"></span>

Note: you can use any unicode glyph in markup yourself if you know it's codepoint or shortcut, e.g. ©. However these 'magic number' codepoints can make it more difficult to understand what icon is being used. It is advisable to use descriptive class names wherever possible.

Icon font

Use icons from an icon font when there are no applicable unicode icons.

We use a custom icon web font for rendering our icons, built from [source SVGs]({{ site.repository }}/tree/master/src/icons){:target="_blank"} by a [grunt task]({{ site.repository }}/blob/master/.grunt-tasks/webfont.js){:target="_blank"} as part of our build process.

  • any custom icons can be used
  • icon fonts support IE8+
  • icons are infinitely scalable.

The icons

The following icons are included within our icon font by default:

<div class="grid">
    {% for glyph in site.data.fonts.nice-icons.glyphs %}
        <div data-g="6 xs:4 md:3 lg:2" class="text-center">
            <div class="h2">
                <span class="icon icon--{{ glyph }}"></span>
            </div>
            <p>
                {{ glyph }}
            </p>
        </div>
    {% endfor %}
</div>

Icon markup

Use custom icons in markup wherever possible. Note: there are also SASS functions and mixins available for building custom components.

  • hide from screenreaders with [aria-hidden="true"]
  • use BEM style CSS classes (icon--NAME modifier)
  • prefer <span> over <i>.

For performance reasons, all icons require a base class and individual icon class. To use, place the following code just about anywhere. Be sure to leave a space between the icon and text for proper padding.

<span class="icon icon--syndication" aria-hidden="true"></span>

Icon classes cannot be directly combined with other components. They should not be used along with other classes on the same element. Instead, add a nested <span> and apply the icon classes to the <span>.

Icon classes should only be used on elements that contain no text content and have no child elements. Use a <span> tag rather than <i>.

Usage in SASS

There are generated SASS constructs (map, function and mixin) available for creating custom components. These are useful if the default classes for use in markup are not sufficient.

<a href="{{ site.baseurl }}{% link technical/sass/documentation/icons.md %}" class="btn">Browse SASS docs for icons</a>
.search {
    &__btn {
        @include nice-icon(search);
    }

    // or
    &__btn {
        @include nice-icon-base;

        &:before {
            content: nice-icon(search);
            display: block;
        }
    }
}

Custom URL

By default, icon font files are referenced from CSS at the /fonts/ directory. This can be overridden with the $nice-font-base-path variable in your application's SASS. For example:

  • serve fonts from a different folder (e.g. $nice-font-base-path: '/assets/icons/';)
  • serve fonts from a CDN (e.g. $nice-font-base-path: 'https://cdn.nice.org.uk/fonts/';).

See [$nice-font-base-path]({{ site.baseurl }}{% link technical/sass/documentation/icons.md %}#nice-font-base-path) in the SASS docs.

Icon font path

The icon font files are included with the dist/fonts folder so are either:

  • \bower_components\nice-design-system\dist\fonts
  • \node_modules\@nice-digital\design-system\dist\fonts

To serve these they either need to be served directly or copied into a directory:

Node/express

If you're using node and express then you can use the following to serve the compiled font files (woff/eot/ttf etc) directly from the node_modules/@nice-digital/design-system/dist/fonts folder:

const express = require("express"),
    path = require("path");

const app = express();

app.use("/fonts", express.static(path.join(__dirname, "./node_modules/@nice-digital/design-system/dist/fonts")));

Grunt

If you're not using express but using Grunt, use a copy task{:target="_blank"} to copy the font files to a directory of your choice on build, e.g.:

// Run `npm install grunt-contrib-copy --save-dev`
module.exports = function(grunt) {

    grunt.loadNpmTasks("grunt-contrib-copy");

    grunt.initConfig({
        copy: {
            icons: {
                cwd: "node_modules/@nice-digital/design-system/dist/fonts/",
                src: ["*"],
                dest: "/fonts/",
                expand: true,
                flatten: true,,
                filter: "isFile"
            }
        }
    });
};

404 in IIS

If you get a 404 error for .woff files with IIS, then you may need to add the MIME type{:target="_blank"} to your web.config:

<system.webServer>
    <staticContent>
        <remove fileExtension=".woff" />
        <mimeMap fileExtension=".woff" mimeType="application/x-font-woff" />
    </staticContent>
</system.webServer>

IE8 and @font-face

Internet Explorer 8 has some issues with @font-facewhen combined with :before. Our icon font uses that combination. If a page is cached, and loaded without the mouse over the window (i.e. hit the refresh button or load something in an iframe) then the page gets rendered before the font loads. Hovering over the page (body) will show some of the icons and hovering over the remaining icons will show those as well.

Custom icons

The icons provided by default (unicode or icon font) should cater for most scenarios but sometimes you'll need an icon that isn't included.

There are 2 options for creating custom icons:

  1. Create a new icon and add it to the core code to make it available for all applications
  2. Create a new icon and generate a custom icon font within your application.

Creating SVG icons

The following should be followed when creating custom SVG icons:

  • icons should be easily recognizable
  • keep icon designs simple, clear and schematic
  • use a 512px height SVG
  • use a single compound path
  • ensure the viewbox is from 0,0.

Core icon

To create a new core icon:

  • create an SVG as per the creating SVG icons section
  • save into the src/icons folder
  • run npm start to build and run the dev site locally
  • test the icon renders correctly
  • submit a pull request
  • release a new version after it's merged to master.

Custom icon font

Creating a custom icon font is the best option if you need bespoke icons for your application:

  1. create the SVG as per the creating SVG icons section
  2. create a grunt task for webfont generation{:target="_blank"}. You can base this off [our webfont task]({{ site.repository }}/blob/master/.grunt-tasks/webfont.js){:target="_blank"}.
  3. use a custom template for the Grunt task to override the $nice-icons map. You can base this off [our custom template]({{ site.repository }}/blob/master/src/icons/.nice-icons.tmpl.scss){:target="_blank"}. You don't need the mixins in your template.
  4. reference both your custom SVG icon(s) and the core ones: src: ["./icons/*.svg", "./node_modules/@nice-digital/design-system/src/icons/*.svg"].
  5. override the $nice-font-base-path variable if you generate your font files anywhere other than /fonts/