Registering and Rendering SVG Icons in WordPress 7.1: A Deep Dive into the New Public API

Registering and Rendering SVG Icons in WordPress 7.1: A Deep Dive into the New Public API

The Evolution of Icon Management in WordPress

While WordPress 7.0 introduced an internal set of SVG icons for the block editor and the core Icon block, WordPress 7.1 elevates this system into a fully realized, public API. Developers can now register custom icons, organize them into namespaces called collections, render them on the server using PHP, and access them programmatically via the REST API. This unified system ensures that custom icons from themes, plugins, and third-party libraries can coexist seamlessly alongside core assets, providing a standardized workflow for icon registration and rendering.

Registering and Managing Icon Collections

To prevent naming collisions between different plugins, themes, and core assets, the Icon API groups every icon into a collection. A collection acts as a namespace prefix (for example, my-plugin/star vs. core/star). Before you can register an icon, its parent collection must exist.

To register a collection, use the wp_register_icon_collection() function during the init hook. The function accepts a unique collection name and an array of arguments:

function my_plugin_register_icon_collection() {
    wp_register_icon_collection( 
        'my-plugin', 
        array(
            'label'       => __( 'My Plugin Icons', 'my-plugin' ),
            'description' => __( 'Icons provided by My Plugin.', 'my-plugin' ),
        ) 
    );
}
add_action( 'init', 'my_plugin_register_icon_collection' );

Naming Rules for Collections

The collection name must strictly follow these naming rules:

  • It must start and end with a lowercase letter or a digit.
  • It can only contain lowercase letters, digits, hyphens, and underscores in between.

Removing Collections

If you need to unregister a collection, use wp_unregister_icon_collection(). Unregistering a collection automatically removes all icons registered within it, eliminating the need to tear down individual icons one by one. This should be executed on the init hook at a later priority than registration:

function my_plugin_unregister_icon_collection() {
    wp_unregister_icon_collection( 'my-plugin' );
}
add_action( 'init', 'my_plugin_unregister_icon_collection', 20 );

Registering Individual SVG Icons

Once a collection is registered, you can add individual icons to it using wp_register_icon(). Each icon name must follow the pattern collection/icon-name (e.g., my-plugin/star). The icon name portion must follow the same character restrictions as the collection name.

When registering an icon, you must provide a label and either the raw SVG string via the content argument, or an absolute path to an .svg file via the file_path argument. You cannot use both.

function my_plugin_register_icons() {
    // Register the collection first
    wp_register_icon_collection( 'my-plugin', array(
        'label' => __( 'My Plugin Icons', 'my-plugin' ),
    ) );

    // Register an icon using an inline SVG string
    wp_register_icon( 'my-plugin/star', array(
        'label'   => __( 'Star', 'my-plugin' ),
        'content' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 2l2.9 6.9 7.1.6-5.4 4.7 1.6 7L12 18l-6.2 3.2 1.6-7L2 9.5l7.1-.6z" /></svg>',
    ) );

    // Register an icon using an absolute file path
    wp_register_icon( 'my-plugin/heart', array(
        'label'     => __( 'Heart', 'my-plugin' ),
        'file_path' => plugin_dir_path( __FILE__ ) . 'icons/heart.svg',
    ) );
}
add_action( 'init', 'my_plugin_register_icons' );

Lazy Loading of SVG Files

A key performance optimization in the Icon API is that the file_path argument is read lazily. WordPress does not open or parse the physical .svg file when wp_register_icon() is called. Instead, the file is only read when the icon is rendered on the front end or requested via the REST API. While this improves performance, it means that invalid file paths will not trigger a registration error; instead, they will fail silently later, returning empty content. Developers must ensure that paths resolve correctly in all target environments.

Strict Sanitization and SVG Element Limitations

Security is a primary concern when handling SVG files in WordPress. To prevent cross-site scripting (XSS) and code injection, the Icon API passes all registered SVG markup through wp_kses against a highly restrictive allowlist.

Currently, the sanitization rules enforce the following limitations:

  • Only the <svg>, <path>, and <polygon> elements are preserved.
  • Common shape elements like <circle>, <rect>, <ellipse>, <line>, and <polyline> are stripped.
  • Attributes are limited to a strict, pre-approved subset.
  • All inline styles, scripts, and event handlers are entirely removed.

Because of these strict rules, complex SVGs containing unsupported elements or stroke-based styling will not render correctly. Developers must design or convert their custom icons to use fill-based <path> or <polygon> shapes.

Server-Side Rendering with wp_get_icon()

To render any registered icon on the server, WordPress 7.1 provides the wp_get_icon() helper function. This function returns the sanitized SVG markup as a string, ready to be printed in your templates:

// Render a decorative icon with default 24px dimensions
echo wp_get_icon( 'core/plus' );

// Render a custom 32px icon with an accessible label and custom class
echo wp_get_icon( 'my-plugin/star', array(
    'size'  => 32,
    'label' => __( 'Featured', 'my-plugin' ),
    'class' => 'my-plugin-star',
) );

Supported Arguments

The second argument of wp_get_icon() accepts an associative array of configuration options:

  • size: (int|null) The width and height of the icon in pixels. Defaults to 24. Pass null to preserve the SVG’s original dimensions.
  • class: (string) Additional CSS classes to append to the outer <svg> element.
  • label: (string) An accessible label for screen readers. If provided, the icon is announced to assistive technologies. If omitted, the icon is treated as decorative and hidden from screen readers via aria-hidden="true".

Styling and Color Inheritance Strategies

Styling SVGs returned by wp_get_icon() requires understanding how sanitization affects color properties. While React-rendered icons from the @wordpress/icons package automatically declare fill="currentColor" on their outer <svg> element, server-side rendered icons do not. The sanitization allowlist strips the fill attribute from the outer <svg>, keeping it only on individual <path> and <polygon> elements. It also strips the stroke attribute entirely.

Because of this, a standalone call to wp_get_icon() will output markup that defaults to the SVG’s native fill color (usually black) rather than inheriting the surrounding text color. To make your server-side icons follow the text color, you can use one of two strategies:

Strategy 1: Apply CSS to a Custom Class

Pass a custom class to wp_get_icon() and define its fill color in your stylesheet. Because the fill property is inherited, it will cascade down to the child paths:

// PHP Template
echo wp_get_icon( 'my-plugin/star', array( 'class' => 'my-icon' ) );

/* CSS Stylesheet */
.my-icon {
    fill: currentColor;
}

Strategy 2: Inline fill=”currentColor” on the Path

Since the sanitization allowlist permits the fill attribute on <path> and <polygon> elements, you can hardcode fill="currentColor" directly onto the shapes when registering the icon:

wp_register_icon( 'my-plugin/star', array(
    'label'   => __( 'Star', 'my-plugin' ),
    'content' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M12 2l2.9 6.9 7.1.6-5.4 4.7 1.6 7L12 18l-6.2 3.2 1.6-7L2 9.5l7.1-.6z" /></svg>',
) );

Block Editor Integration and UI Enhancements

The registration of custom icons immediately enhances the user interface of the block editor. In WordPress 7.1, the core Icon block’s picker has been redesigned to group icons by their registered collections.

  • Tabbed Interface: Each collection receives its own dedicated tab in the picker, alongside an “All” tab that aggregates all registered icons.
  • Preserved Search: Users can search within a specific collection or across all collections using the “All” tab. The search query is preserved when switching between tabs.
  • Toolbar Controls: The Icon block toolbar now features controls to flip the icon horizontally or vertically, as well as a button to rotate it in 90-degree increments.
  • Default Fallback: Newly inserted Icon blocks now default to the core/info icon instead of starting as an empty placeholder.
  • Unified Rendering: The server-side rendering path of the Icon block now delegates directly to wp_get_icon(), ensuring consistent output across both block and manual implementations.

Querying Icons via the REST API

The block editor and external applications can query registered collections and icons via read-only REST API endpoints. All endpoints reside under the wp/v2 namespace and require an authenticated user with the edit_posts capability (or equivalent permissions for any REST-visible post type).

Collection Endpoints

  • GET /wp/v2/icon-collections — Retrieve all registered collections.
  • GET /wp/v2/icon-collections/<collection> — Retrieve a single collection.

Example response for GET /wp/v2/icon-collections/core:

{
    "slug": "core",
    "label": "WordPress",
    "description": "Default icon collection."
}

Icon Endpoints

  • GET /wp/v2/icons — Retrieve all registered icons.
  • GET /wp/v2/icons/<collection> — Retrieve all icons belonging to a specific collection.
  • GET /wp/v2/icons/<collection>/<name> — Retrieve a single icon.

Example response for GET /wp/v2/icons/core/plus:

{
    "name": "core/plus",
    "label": "Plus",
    "content": "<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z" /></svg>",
    "collection": "core"
}

Filtering Results

The /wp/v2/icons endpoint accepts query parameters to filter results. You can use the collection parameter to isolate a specific namespace, and the search parameter to filter icons by name or label:

GET /wp/v2/icons?collection=my-plugin&search=star

Frequently asked questions

What happens if I register an icon with both content and file_path?

Registration will fail and return false. The wp_register_icon() function requires either content or file_path, but not both. It will emit a _doing_it_wrong() notice explaining the error.

Why did my SVG icon lose its circles and rectangles after registration?

WordPress 7.1 uses a highly restrictive wp_kses allowlist for SVG sanitization. Currently, only , , and elements are preserved. Other shape elements like and are stripped. You must convert these shapes into paths before registering.

Does wp_get_icon() validate if the file_path exists during registration?

No. The file_path is read lazily when the icon is first rendered or requested via the REST API. If the file path is incorrect, registration will still succeed, but the rendering output will be empty.

How do I make my server-rendered PHP icons inherit the text color?

You can either pass a custom class in the wp_get_icon() arguments and apply 'fill: currentColor' to that class in your CSS, or you can register the icon with 'fill="currentColor"' directly on its internal or elements.

Primary reference: Review the original announcement for exact release details. This article is an independent explanation and does not reproduce the source text.

Leave a Comment

Your email address will not be published. Required fields are marked *

*
*