The Icon block arrived in WordPress 7.0, but it only let you pick from the icons that ship with WordPress. Starting with WordPress 7.1, themes and plugins can register their own icons, which then show up in the Icon block’s icon library next to the built-in ones.
In this tutorial, we’re going to take a look at how you can add a set of custom icons to your block theme, and use them in the editor, in your patterns and templates, and in PHP.
I’ve been looking forward to this one. In my Pulitzer theme, I added custom icons as CSS masks, so that they could be given any color with the color settings in the editor. On client sites, I’ve often used The Icon Block by Nick Diego, which is very similar to what shipped in WordPress 7.1. Both still work, but they’re workarounds that are no longer needed. Icons registered with the new API work with the color settings of the Icon block out of the box.
Preparing your icons
Before we write any code, we need to make sure that the icons will survive the trip into WordPress. WordPress cleans up the SVG markup of every icon you register, and it’s pretty strict about what it lets through:
- Only three elements are allowed:
svg,pathandpolygon. Anything else, likecircle,rect,lineorg, is removed. - Strokes are removed too. A
pathkeeps itsd,fill,fill-ruleandtransformattributes, butstrokeandstroke-widthare stripped. Outline-style icons drawn with strokes end up invisible.
These rules will probably be loosened in WordPress 7.2. In the current development version, rect and circle are allowed as well, and strokes are kept. I’m looking forward to this, since I tend to use stroke icons where the thickness is tied to the font size of the elements around the icon. Until 7.2 is out, it’s safest to prepare your icons as described below, unless you’re fine with parts of your icons disappearing.
WordPress doesn’t warn you when this happens. The icon is registered, but parts of it (or all of it) are missing in the editor. To avoid that, prepare your icons like this before you export them:
- Convert strokes to fills. In Figma, select the icon and choose “Outline stroke” in the “Object” menu.
- Convert any circles, rectangles and lines to paths. The icon can have several paths, so it doesn’t need to be a single shape. In Figma, the quickest way to do that is “Flatten” in the same menu.
- Export the icon as SVG, and check that it has a
viewBoxattribute, likeviewBox="0 0 24 24". - Remove any hard-coded fill colors, or set them to
currentColor. That way, the icon picks up the text color you set on the Icon block. The Icon block colors the icon by setting the fill of thesvgelement to the current text color, but a fill set directly on a path takes precedence. Without this step, the icon keeps its original color whatever color you pick in the editor.
Save each icon as a separate .svg file in a folder in your theme, like assets/icons/. The file names can be anything, but it’s easiest if they match the names you’ll register the icons with, like mountains.svg and tent.svg.
Registering the icons
Icons in WordPress are grouped into collections. Every icon belongs to a collection, and each collection gets its own section in the Icon block’s icon library. WordPress’s own icons are in a collection called core, so let’s start by registering a collection for our theme, and then add our icons to it.
Add the following code to the functions.php file of your theme. Replace mytheme with the slug of your theme, and the icon names and labels with your own:
function mytheme_register_icons() { // The icon API was added in WordPress 7.1. if ( ! function_exists( 'wp_register_icon' ) ) { return; } wp_register_icon_collection( 'mytheme', array( 'label' => __( 'My Theme', 'mytheme' ), 'description' => __( 'Icons included with My Theme.', 'mytheme' ), ) ); $icons = array( 'mountains' => __( 'Mountains', 'mytheme' ), 'tent' => __( 'Tent', 'mytheme' ), ); foreach ( $icons as $name => $label ) { wp_register_icon( 'mytheme/' . $name, array( 'label' => $label, 'file_path' => get_theme_file_path( 'assets/icons/' . $name . '.svg' ), ) ); }}add_action( 'init', 'mytheme_register_icons' );
Let’s go through it. First, we check that the icon functions exist, so that the theme doesn’t break on sites running a version of WordPress older than 7.1. Then, we register a collection called mytheme, with a label that will be shown as the name of the collection in the icon library.
Next, we list our icons with their names and labels, and register each of them with wp_register_icon(). The icon name always includes the collection slug, like mytheme/mountains. The file_path points to the SVG file in our icons folder. WordPress only reads the file when the icon is actually used, so you don’t have to worry about adding a lot of icons to the list.
Using get_theme_file_path() for the file path has a nice side effect: if someone creates a child theme of your theme, they can replace any of your icons by adding a file with the same name to the same folder in the child theme.
Using the icons
With the icons registered, they’re available everywhere the Icon block is.
In the editor
- Add an Icon block to a post, page or template.
- Click the “Replace” button in the block toolbar to open the icon library.
- Select your collection, “My Theme” in our example, in the list on the left, and click the icon you want to use.

You can change the color, size and spacing of the icon with the options in the “Styles” tab of the block sidebar, just like with the built-in icons.

If the icon carries meaning on its own, like an icon-only link, describe it in the “Label” field under the “Settings” tab in the block sidebar. Leave it blank for decorative icons, and the icon will be hidden from screen readers.
In patterns and templates
In your theme’s patterns and templates, you can add an icon with the Icon block markup and the full name of the icon:
<!-- wp:icon {"icon":"mytheme/mountains"} /-->
To give the icon a label in the markup, add an ariaLabel:
<!-- wp:icon {"icon":"mytheme/tent","ariaLabel":"Campsites"} /-->
In PHP
If you need an icon somewhere outside of the block editor, like in a PHP template or a custom block, you can output it with wp_get_icon():
echo wp_get_icon( 'mytheme/mountains', array( 'size' => 32 ) );
To give the icon a label, pass a label:
echo wp_get_icon( 'mytheme/tent', array( 'label' => __( 'Campsites', 'mytheme' ) ) );
That’s it!
One thing to keep in mind: icons registered in a theme are only available while that theme is active. If a site switches to a different theme, any Icon blocks using your icons in posts and pages will output nothing. That’s fine for icons used in the theme’s own patterns and templates, but if you want site owners to use the icons in their content, a plugin is a safer home for them. The WordPress Developer Blog has a good walkthrough of building an icon plugin, and the registration code is the same as in this tutorial.




