Twig Rendering
When to Use
Rendering an icon directly in a custom Twig template (block, paragraph, layout).
Pattern
Use core's icon(pack_id, icon_id, settings), from Drupal\Core\Template\IconsTwigExtension. It is the general-purpose renderer and needs no contrib module:
{# Render with pack defaults #}
{{ icon('my_theme_icons', 'menu') }}
{# Render with overrides #}
{{ icon('my_theme_icons', 'menu', {
size: 32,
color: '#0066cc',
decorative: true,
}) }}
It returns the #type: icon render array below, so cache metadata bubbles correctly.
icon_preview() is not the same function
UI Icons also registers icon_preview(pack_id, icon_id, settings), but it is the admin-preview renderer behind the Library page and the picker — not the one to reach for in a theme template. It returns IconPreview::getPreview(), which forces a size of 48 when you omit the settings argument, rather than using the pack's own defaults: IconPreview::ICON_DEFAULT_SIZE is 48 on the preview:-template path, and templates/icon-preview.html.twig writes {{ settings.size|default(48) }} on the fallback path.
(The ?? ['size' => 32] in IconPreviewTwigExtension::getIconPreview() is dead code from Twig's point of view — the parameter default is [], not NULL, so ?? never fires on a two-argument call.)
Decision
| Twig context | Approach |
|---|---|
| Static, theme-author-defined icon | {{ icon(...) }} with literal arguments |
| Rendering a preview in an admin/config UI | {{ icon_preview(...) }} |
| Icon from a field on the entity | Pass through field rendering — the field formatter handles it |
| Icon from a UI Patterns prop | Pattern templates render the prop automatically |
Pattern: Programmatic Render Array (PHP)
$build = [
'#type' => 'icon',
'#pack_id' => 'my_theme_icons',
'#icon_id' => 'menu',
'#settings' => ['size' => 32],
];
The property is #icon_id. #icon is not a recognized property of core's Icon element — it is ignored, #icon_id stays empty, and the element renders nothing.
Or via the plugin manager:
$icon = \Drupal::service('plugin.manager.icon_pack')->getIcon('my_theme_icons:menu');
$build = $icon->getRenderable(['size' => 32]);
Common Mistakes
- Wrong: calling
icon()oricon_preview()with the full ID string (my_theme_icons:menu) → Right: both expect(pack_id, icon_id, settings)as separate arguments - Wrong: using
icon_preview()as the general renderer in theme templates → Right: it's the admin preview helper and forcessize: 48when settings are omitted - Wrong: hardcoding the SVG content from the source file → Right: bypasses settings, accessibility templating, and cache metadata
See Also
- UI Patterns Integration
- Field API Integration
- Reference:
\Drupal\Core\Template\IconsTwigExtension - Reference:
src/Template/IconPreviewTwigExtension.php