Icons have a storied history on the web. In the bad old days, they were treated like any other images on a web page, implemented using individual image elements. This carried several negative implications, among them poor semantics and excessive HTTP requests as every icon image on a page were loaded separately. A much-improved method emerged with image replacement using CSS, pseudo-elements, and sprites. A CSS-based approach left HTML semantics undisturbed, and sprite images cut down on unnecessary asset requests with single large images combined with background positioning, instead of an image per icon.
Of course, even the CSS sprite technique still has the chief downfall that it’s image-based. This means that image editing software is required to create or edit sprites, whether or not you are creating your own icons or pulling them in from elsewhere. It also means that at the end of the day your icons are a flat set of pixels, subject to resolution limitations. (Note the Magento 1 responsive theme’s use of two distinct sizes of sprite image, in order to accommodate high pixel density displays like Retina devices.) An approach fast gaining wide adoption today, which cuts images out of the story entirely, is that of icon fonts. Magento 2’s native theme fully embraces this technique.
Using fonts for icons makes sense for a lot of reasons. In reality, iconography has always had more in common with text than content images; icons are glyphs that communicate meaning to the audience. And in technical terms, font glyphs are vector information that can scale up to any resolution. Of course, if you’re a web developer used to working with image-based icons, it’s likely that you have no small degree of discomfort with generating your own font files. Luckily, the growing adoption of icon fonts means there are great tools available for you. The native Magento theme provides the framework you need for implementation, and in this article, I’ll introduce you to a foundation that will leave you even better equipped for customizing Magento’s icons easily.
A Brief Overview of Magento’s Icon CSS
You’ll find the icon font files for the Magento Blank theme in lib/web/fonts/Blank-Theme-Icons
(in the typical multiple file formats to support all user agents). lib/web/css/source/lib/variables/_typography.less
defines the font icon path and name, and in the Magento Blank theme web/css/source/_icons.less
uses these to define the icon font face itself, to be used in all CSS declarations.
The final relevant piece to be aware of is lib/web/css/source/lib/variables/_icons.less
, where LESS variables are defined to store the Unicode characters that correspond to the right font glyphs for each icon. This will be a handy reference for you when needing to re-assign said character codes to new icons.
The defined icon font face and the character variables are used throughout the theme LESS code to define icons, usually through a call to the lib-icon-font
mix-in.
Armed with this info about the CSS structure for customizing icon fonts, you’ve got a great starting point; change the variables defining the icon font path and name, and you’ve successfully replaced the native icons with your own. But that still leaves the question of how to generate your own icon font in the first place.
Font Libraries and Tools
You’ve got two main options for defining custom icons for your Magento theme: Create your own, or cherry pick some from available libraries. There are online tools that support either approach and allow you to wrap up your custom creation in a final font. A great example, and the one covered here is IcoMoon.
This font generation tool has a number of free and paid icon sets from which you can pick and choose. It also supports other features important for your Magento icon customization: importing of existing fonts, importing of your own custom icon SVGs, and importing/exporting your selections as JSON-based configuration, so that you can pick up straight from an already configured icon set. IcoMoon also features a fairly robust editing interface for adjusting the scaling and positioning of individual icons.
Using IcoMoon, you can start with an imported font like Magento’s native icons, make your desired tweaks by removing some and adding others, and then re-export a finished font. Of the five file types that Magento makes available natively, IcoMoon’s are missing only woff2. That’s not a problem, though, since there are plenty of tools out there for font file type conversion as well. Try Everything Fonts. IcoMoon’s final package handily includes JSON configuration and example CSS as well, though you’ll be eschewing said CSS in favor of Magento’s native structure.
Caveats and an Enhanced Starter Package
I said earlier that, once you’ve got your custom icon font in hand, replacing Magento’s native icons would be as simple as setting the right LESS variables for the font path and name. It would be great if that were the case. Unfortunately, if you’re using Magento Blank as your theme starting point and plan to customize it with available libraries, you’re likely to run into a snag: the size of the icons in the Blank font relative to their bounding box is significantly smaller than the typical fonts you’ll find on IcoMoon. Combining drop-in replacements with the font sizes and line heights in the Blank theme will result in unusually large icons compared with the spaces where they’re used.
There are two ways to approach this problem. The first is to scale down any icons you are using in your custom set using IcoMoon’s aforementioned editing interface. With this approach, you avoid any CSS changes, but you’ll have to touch every icon you wish to include in your custom font.
The second approach is to customize CSS font sizes and line heights to match the more typical icon sizes. This has the benefit of not needing to worry about sizing icons every time you drop a new one in, but it carries some up front overhead. It would be nice if a few typical icon sizes were defined in LESS variables for just such a customization. Unfortunately, the definition of these sizes is considerably more scattershot throughout the various module LESS source files in Magento. It’s a lucky break, then, that the Magento Luma example theme contains a more typically sized icon font, along with corresponding font sizes.
If you want to extend the leaner, more vanilla Magento Blank with your theme instead of extending Luma, the latter at least provides an appropriate boilerplate from which to extract the right styles to normalize icon sizes. And that’s exactly what I’ve done in this starter theme package. This theme extends Blank but uses the Luma icon font, containing appropriate CSS resets for sizing. You will note that these resets are contained within the theme’s _extend.less
, meaning that it supersedes rather than replaces the baseline styles. While this leads to slightly more bloated compiled CSS, it’s a trade-off to avoid entirely duplicating a myriad of core theme files, since the vast majority of styles in said files won’t change from Blank. (The resulting _extend.less
also provides a precise reference for which relevant styles should be tweaked if further re-sizing is needed.)
Note that this package is a work in progress, and you may find areas I’ve missed where further size tweaking is needed.
Pulling it All Together
Because of the sizing issue with the Blank theme, you should first decide which of the following approaches you want to take with your custom icons:
- Approach A: Size your icons to match the CSS sizing in the Blank theme
- Approach B: Directly extend the Luma theme
- Approach C: Implement CSS to match the more typical icon size
Which approach is best? That probably depends on how many icons you intend to customize with drop-in replacements. If you’re replacing only a few, Approach A may work best for you. If you’re really giving your theme a distinct flavor with a wholesale new icon set, though, Approach B or C may be the way to go.
If you’re using Approach C, obtain this starter icon theme. You can install and extend this theme, or copy its styles directly into your own theme.
- In (IcoMoon, import the SVG font file for your starting icon font (e.g., Luma-Icons). Navigate to the IcoMoon App and use Import Icons. Conveniently, your imported font will be collected into its own set.
- For the icons you want to replace, remove the existing glyphs from the set.
- Choose your replacement icons. Use the Icon Library to add other free or paid icon sets if desired. Then select your replacements and choose Copy Selection to Set from the settings menu of your custom set.
- If you’ve created your own custom icons, use Import to Set from the settings menu of your custom set.
- Switch to the Generate Font tab at the bottom of the IcoMoon interface and make sure to set the correct Unicode character values for all new icons. Use the variable reference in
lib/web/css/source/lib/variables/_icons.less
. (If you’re uncertain which character codes match which icons, you can take note of them in your initial imported font before removing the originals.) - If you’re using Approach A (i.e., sizing icons to match the CSS of the Blank theme), switch to Edit mode in IcoMoon, choose each new icon, and use the “Scale” feature to size the icon down to match the default Blank icons.
- Name your font. Use “Edit Info” from the settings menu of your icon set.
- Download the font package by switching to the Generate Font tab at the bottom of the interface, then choose “Download” from the same tab.
- Get the woff2 file format to round out the five formats Magento makes available for its default fonts. Head to a resource like Everything Fonts and use the conversion tools.
- Copy all font file types from the font directory of your downloaded package into your theme at
web/fonts
. - In
web/css/source/_theme.less
in your theme, set@icons__font-path
and@icons__font-name
appropriately with the file path and name of your new icon font. - If you discover you need any further tweaks to icon CSS sizing, use
web/css/source/_extend.less
to implement these tweaks.