Icon Pack Format
When to Use
Authoring
*.icons.ymlat the root of a module or theme.
Pattern
File location: {module|theme}/{module|theme_name}.icons.yml
Canonical schema:
pack_id: # machine name; appears as `pack_id:icon_id` in references
enabled: true # optional, default true
label: "Pack label" # optional, translatable
description: "Pack description" # optional, translatable
links: # optional reference URLs
- https://my-icon-source.example
version: "1.0.0" # optional
license: # optional
name: "MIT"
url: "https://opensource.org/licenses/MIT"
gpl-compatible: true
extractor: svg # REQUIRED — one of path | svg | svg_sprite | font
config: # REQUIRED — extractor-specific
sources:
- icons/*.svg
library: my_theme/icon-styles # optional — asset library attached whenever
# an icon of this pack renders. Format is
# `extension/library_name`. This is the ONLY
# way to ship @font-face or icon CSS with a pack
settings: # optional per-icon configurable properties
size:
title: "Size"
type: integer
default: 24
template: > # REQUIRED — Twig string interpolated at render time
<svg xmlns="http://www.w3.org/2000/svg"
width="{{ size|default(24) }}" height="{{ size|default(24) }}">
{{ content|raw }}
</svg>
preview: "" # optional — distinct template for admin preview
Naming Convention
- pack_id: lowercase, underscored, prefixed with theme/module name (
my_theme_icons, noticons) - icon_id: derived from filename, codepoint key, or symbol id (lowercase, hyphens preferred)
Discovery
Core's IconPackManager::getDiscovery() builds a YamlDiscovery('icons', …), which resolves to exactly EXTENSION.icons.yml at module/theme root (not subdirectories). Cache must be cleared after adding/changing pack files.
*.ui_icons.yml is not discovered. That name was dropped before 1.0.0 stable and there is no fallback — a pack declared in my_theme.ui_icons.yml simply never appears.
Common Mistakes
- Wrong: putting the YAML file in a subdirectory (
icons/my_theme.icons.yml) → Right: place it at the extension root; subdirectories are not discovered - Wrong: using the old
*.ui_icons.ymlfilename → Right: rename to*.icons.yml; the old name is silently ignored - Wrong: using a generic
pack_idlikeicons→ Right: prefix with the theme/module name to avoid collisions - Wrong: omitting
template→ Right: an exception, not blank output.extractorandtemplateare both in the schema'srequiredlist (core/assets/schemas/v1/icon_pack.schema.json). Withjustinrainbow/json-schemainstalled,IconPackManager::validateDefinition()throwsIconPackConfigErrorExceptionat discovery — a WSOD on cache rebuild. Without that library the validator is skipped and the throw simply moves to render time, fromIconExtractorBase::createIcon()("Missingtemplatein your definition…"). Either way, look for the exception, not for empty markup - Wrong: declaring a CSS library in
*.libraries.ymlbut not wiring it into the pack → Right: the library is never attached. Point the pack'slibrary:key at it;Icon::preRenderIcon()attaches only whatIconDefinition::getLibrary()returns
See Also
- Extractors
- Settings & Rendering
- Authoring & Distribution
- Reference:
core/lib/Drupal/Core/Theme/IconPackManager.php - Reference:
core/assets/schemas/v1/icon_pack.schema.json