Documentation Level: 
Intermediate

Backdrop 1.28.0 introduced a new API for using SVG-based icons. Icons can be provided and used by Backdrop core, any module, and any theme. The icons provided by Backdrop core are from the Phosphor Icon Set by Helena Zhang and Tobias Fried, the icon set is MIT licensed and thus compatible with bundling in a GPL licensed project like Backdrop CMS.

Backdrop includes the full set of Phosphor icons, in both the "Regular" and "Fill" variations. This makes for a total of 3,024 available icons out-of-the-box.

Finding the Available Icons

There are 3 ways to find icons currently:

  1. Open the /core/misc/icons directory and check the icons there.
  2. Visit phosphoricons.com. This can sometimes make finding an icon easier because they include keyword matching beyond just the icon name.
  3. There is a work-in-progress Icon Browser module, which will be a part of the contrib repository. This module can be useful because it can find icons provided by modules and themes in addition to the core set.

For all icons provided by core and by themes, the file name of the icon is the key by which the icon is matched (minus the .svg extension). Modules can provide a mapping (see below) so the file name and icon name may not always be one-to-one.

Basic Usage (Inline Icons)

The icons in Backdrop can be used in a variety of ways, including as inline HTML, as a CSS custom property, and in JavaScript. The most common usage of an icon is through the icon() function, this returns the contents of an SVG directly so that it can be printed to the page. Here is an example usage that you might see in a template file (.tpl.php):

<?php print icon('circle'); ?>

This will print the SVG contents as text in the template. The above code would print the following circle icon:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" aria-hidden="true" class="icon icon--circle"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Z"/></svg>

Inline icons like this can also be passed attributes like additional classes.

<?php print icon('circle', array('attributes' => array('class' => array('toolbar-icon')))); ?>

And you can also pass in an alt option, which will be rendered as an accessible <title> tag within the SVG:

<?php print icon('circle', array('alt' => t('Select this option'))); ?>

If an alt option is not provided, the icon is automatically assigned an aria-hidden="true" attribute, meaning it will not be picked up by screen readers or other accessibility software. If an icon is accompanied by a label right next to it (such as in a menu), there is no need to provide an alt option as the icon is decorative only. If an icon is being used in place of text or without an accompanying label, an alt option should be provided.

Colorizing Inline Icons

One of the main benefits of using inline SVG icons is the ability for them to take on any color. All icons within core have the special attribute fill="currentColor" on the <svg> tag. This makes the SVG take on the CSS color attribute. So if you wanted your icons to appear black, it is as simple as adding the following CSS:

.icon {
  color: #000000;
}

A lot of the time, if the icon is right next to text of the same color, no additional CSS is needed at all. An icon placed next to white text will take on the white font color, and an icon placed next to black text will take on the black font color.

Using Icons in CSS

Inline icons are great for a lot of reasons: they reduce HTTP requests, they can take on color from CSS, they're accessible, and they're easily scalable. But often modifying the markup to inline an SVG is difficult, and using CSS to add an icon can be a lot easier. 

Because the number of icons is so large, Backdrop does not make every icon available on every page. Instead, if you want an icon to be available, it should be added through hook_library_info() or with backdrop_add_icons(). Icons can also be added in an array to a form element with $form['#attached']['icons'].

The preferred method to add icons is with hook_library_info(), so the CSS and icons (and any JS) are added together through a single reference. For example if a module needed the icons for "pencil" and "image", it would declare the icons in hook_library_info() as below:

function hook_library_info() {
  $libraries['my-module-library'] = array(
    'title' => 'My module library',
    'css' => array(
      backdrop_get_path('module', 'my_module') . '/my-module.css' => array(),
    ),
    'icons' => array(
      'pencil',
      'image',
    ),
  );
}

Alternatively, if you are not using hook_library_info() or just need to add an icon without adding any other CSS or JS, then icons can be added directly with backdrop_add_icons() like this:

backdrop_add_icons(array(
  'pencil',
  'image'
));

You can call backdrop_add_icons() in any hook or function which would load on the page where the icon is needed, such as a form or preprocess function.

Now because the icons have been added to the page, they are made available within CSS as a custom CSS property (also know as a CSS variable). In your CSS file, you can then reference the icon like this:

.my-element {
  background-image: var(--icon-pencil);
}

The --icon-[icon-name] variable will be populated with the full URL to the icon (there is no need to also add url() around the variable). This is pure CSS; it does not require SASS or any precompiling.

Colorizing CSS Icons

Using a CSS icon is a great way to avoid changing markup, but colorizing it is a bit more involved. Unless you want the default black-colored icon, you'll need to use a CSS mask to modify the SVG color. For an icon, it's often useful to leverage a pseudo-element to position the icon. Here is one example:

.my-element::before {
  content: '';
  mask: var(--icon-pencil) no-repeat center center;
  background: #ffffff;
  width: 1em;
  height: 100%;
}

In this example, the icon will be placed before the element, match the height of the neighboring text, and be displayed as a white icon. The mask property defines the shape of the icon, and the background property defines its color.

Using Icons in JavaScript

Using icons in JavaScript is very similar to using an icon in CSS. Add the icon to the page using either hook_library_info() or backdrop_add_icons() (see the CSS section above). Then in the JavaScript file, the icon path can be located using:

const pencilIconPath = Backdrop.icons['pencil'];

Like in CSS, this only provides the path to the icon, not the contents of the icon itself. Any icon added to the page is available in both CSS and JavaScript files. This can be useful when trying to determine what icons are available in CSS, you can open the Developer Console in the browser and type Backdrop.icons to find a list of all currently available icons.

Adding New Icons

Icons can be declared by both modules and themes. In either case, prefixing the icon with the name of the project is a good idea. That avoids accidentally overriding an icon provided by core. Even if core does not provide an icon by that name currently, it's possible that future versions of core will use that name.

Adding an Icon Through a Theme

Adding an icon to a theme is very simple.

  1. Create an icons directory within your theme.
  2. Place .svg icon files within the icons directory. For example an icon named my-theme-banana.svg
  3. Now you can use <?php print icon('my-theme-banana'); ?> within your template files. Or use hook_preprocess_page() in a theme's template.php file and add icons with backdrop_add_icons().

Adding an Icon Through a Module

Adding an icon through a module is more involved. Because there are many modules on a site and automatically scanning every icons directory is not performant, modules must declare the icons they wish to provide through hook_icon_info().

Using hook_icon_info() has multiple benefits, such as being able to segment icons into multiple directories (such as for variants like "filled" or "thin"), and icon file names do not need to directly map to the icon names. This can be useful to have entire replacement sets of icons (such as Font Awesome) without needing to rename every SVG image file. For details on adding an icon through a module, see the documentation for hook_icon_info(). There is also hook_icon_info_alter() if you would like to modify the icons provided by modules (such as delisting an icon). Note that hook_icon_info_alter() only applies to icons provided by modules, as core and themes use the icon file name directly with no additional metadata.

Overriding Icons

Any icons provided by core can be overridden by either a module or a theme. They only need to use the same icon name as core, and the icon provided by core will be replaced by the one provided by a module or theme.

Themes win over modules as well, so if a theme provides an icon with the same name as a module icon, the theme icon will be output. Because collisions can happen so easily, it is a good idea to prefix icons provided by modules or themes with the project name, unless intentionally overriding icons provided by other projects.

Fun Tricks

Adding an Icon to Admin Bar or Admin Landing Page

Backdrop 1.28.0 has already integrated icons into the Dashboard, Admin Bar, and Admin Landing Pages (such as admin/config). Adding an icon to either a top-level admin bar menu or an admin landing page is very easy. Find the hook_menu() entry that defines the menu entry, and then add the name of the icon you would like to be associated with that path. For example:

function my_module_menu() {
  $items['admin/example'] = array(
    'title' => 'Example Top Page',
    'page callback' => 'my_module_admin_page',
    'access arguments' => array('access administration pages'),
    // Specify the icon used in the admin bar:
    'icon' => 'gear-fill',
  );
  $items['admin/config/example'] = array(
    'title' => 'Example Config Page',
    'page callback' => 'my_module_config_page',
    'access arguments' => array('access administration pages'),
    // Specify the icon used on the admin/config page:
    'icon' => 'gear',
  );
  return $items;
}

Note that generally, icons in the admin bar use the "fill" variant while icons under admin/config use the regular variant. However this rule is not strict, module developers should use the icons that looks best when shown with other icons in the same context.

Colorizing 3rd Party Icons

The icons provided by Backdrop core all include the special fill="currentColor" attribute within the SVG file. But sometimes when using a 3rd party SVG, such as one from another icon library, an icon from a CDN, or a vendor-provided logo, the SVG may not have this property in its source code. You may be able to modify the source, but you can also just provide the fill attribute when calling the icon() function like this:

icon('circle', array('attributes' => array('fill' => 'currentColor')));

Because any attribute can be added to the <svg> tag, you can use it to add the special attribute needed for coloring, without modifying the SVG file. Neat!