Create an icon pack for TinyMCE
Overview
This guide provides comprehensive coverage of creating, building, and deploying custom icon packs, including solutions to common issues.
How Icons Work in TinyMCE
A TinyMCE icon pack is a .js
file containing strings of SVG’s. An icon pack can be used: to include one or more custom icons; or to replace some or all of the default TinyMCE icons.
An icon pack only requires the custom icons to be included; the default TinyMCE icons are used as a fallback for icons missing from the custom icon pack.
Icon Pack Structure and Loading
Understanding Icon Pack Loading: TinyMCE loads icon packs from the path
Example Directory Structure: js/tinymce/ โโโ tinymce.min.js โ TINYMCE_BASE marker file โโโ icons/ โ โโโ default/ โ โ โโโ icons.js โ Default TinyMCE icons โ โโโ my_icon_pack/ โ Your custom pack โ โโโ icons.js โ Must be exactly this filename โโโ ... (other TinyMCE files) |
Icon Pack File Format
The generated icons.js
file in the dist/icons/${iconPackName}/icons.js
directory follows this exact format:
tinymce.IconManager.add('your-pack-name', {
icons: {
'bold': '<svg width="24" height="24">...</svg>', // this is automatically generated from the 'bold.svg' file in the 'src/svg' directory
'italic': '<svg width="24" height="24">...</svg>',
'custom-icon': '<svg width="24" height="24">...</svg>',
// ... more icons
}
});
Creating a TinyMCE Icon Pack
To create a custom icon pack:
Download and Setup the Icon Pack Template
To use the TinyMCE icon pack template project:
-
Download the TinyMCE Oxide Icon Pack Template by either:
-
Downloading the
.zip
file from the Oxide Icon Pack Template GitHub page and extract the contents. -
From a terminal or command prompt, use git to clone the GitHub repository:
git clone https://github.com/tinymce/oxide-icon-pack-template.git
-
-
Open a terminal or command prompt, navigate to the
oxide-icon-pack-template
directory. -
Install the project dependencies by executing:
npm install
-
When prompted, enter a name for the icon pack. The icon pack name should only contain:
-
Numbers
-
Letters
-
Hyphens (
-
) -
Underscores (
_
)
-
-
Verify that the
iconPackName
field has been added to yourpackage.json
file:{ "iconPackName": "my_icon_pack", }
The icon pack name will be used with the icons option to apply the icons in TinyMCE.
The
Example:
|
Add the SVG Files
Each SVG files placed in /src/svg
will be converted to an icon. The file names of the SVG files are used to set the icon identifier used by TinyMCE.
For example: bold.svg
will have the identifier bold
. Such as:
tinymce.init({
selector: '#tiny_custom_button', // change this value according to your HTML
toolbar: 'myButton',
icons: 'my_icon_pack',
setup: (editor) => {
editor.ui.registry.addButton('myButton', {
icon: 'bold', // the 'bold' icon created from 'bold.svg'
onAction: (_) => {
editor.insertContent(' <strong>It\'s my icon button!</strong> ');
}
});
}
});
For a list of default icon identifiers, see: Available icons. If using a custom icon pack, the icon identifiers will be the file names of the SVG files.
|
SVG File Organization
Organize your SVG files in the src/svg/
directory:
src/svg/
โโโ bold.svg โ Overrides default bold icon
โโโ italic.svg โ Overrides default italic icon
โโโ underline.svg โ Overrides default underline icon
โโโ my-custom-icon.svg โ Creates new 'my-custom-icon' identifier
โโโ company-logo.svg โ Creates new 'company-logo' identifier
โโโ save-action.svg โ Creates new 'save-action' identifier
Icon Identifier Rules:
-
Filename becomes the identifier:
bold.svg
โ'bold'
-
Hyphens are preserved:
my-custom-icon.svg
โ'my-custom-icon'
Build the Icon Pack
To build the icon pack using Gulp:
-
Open a terminal or command prompt and navigate to the root directory of the icon pack (such as:
oxide-icon-pack-template/
). -
Build the icon pack by executing the
npx gulp
command:npx gulp
A
dist/
directory containing the icon pack will be automatically created.Example:dist/icons/my-icon-pack/icons.js
automatically generated from the SVG files in thesrc/svg
directory.tinymce.IconManager.add('my-icon-pack', { icons: { 'audio': '<svg width="24" height="24"><path d="M10.8 19q.9 0 1.5-.7t.7-1.5V13h3v-2h-4v3.9l-.6-.3-.6-.1q-1 0-1.7.7t-.6 1.6q0 .9.7 1.5t1.6.7ZM6 22q-.8 0-1.4-.6T4 20V4q0-.8.6-1.4T6 2h8l6 6v12q0 .8-.6 1.4T18 22H6Zm7-13h5l-5-5v5Z"/></svg>', 'bold': '<svg width="24" height="24"><path fill-rule="evenodd" d="M3.6 2.3a1.4 1.4 0 0 0-1.4 1.3v16.8c0 .7.7 1.4 1.4 1.4h16.8a1.4 1.4 0 0 0 1.4-1.4V3.6a1.4 1.4 0 0 0-1.4-1.3H3.6Zm6 4a1.4 1.4 0 0 0-1.3 1.3v9.3c0 .7.6 1.4 1.3 1.4H12v-.8.8a2.5 2.5 0 0 0 .2 0 4.6 4.6 0 0 0 1.6-.5c.5-.2 1-.5 1.3-1 .4-.5.7-1.2.7-2 0-.9-.3-1.6-.7-2a3.2 3.2 0 0 0-.8-.9 2.8 2.8 0 0 0 .4-.5c.4-.5.5-1.1.5-1.9s-.1-1.4-.5-1.9a3 3 0 0 0-1.1-1 3.9 3.9 0 0 0-1.6-.3H9.6Zm.1 6.5H12a3.2 3.2 0 0 1 1.2.2l.7.6c.2.2.4.6.4 1.1s-.2 1-.4 1.2a1.8 1.8 0 0 1-.7.6 3.2 3.2 0 0 1-1.1.2H9.7v-4Zm2.3 4Zm0-5.6H9.7V7.8H12l1 .2.5.5c.1.2.3.5.3 1s-.2.8-.3 1a1.4 1.4 0 0 1-.6.5 2.3 2.3 0 0 1-.9.2Z" clip-rule="evenodd"/></svg>', 'italic': '<svg width="24" height="24"><path fill-rule="evenodd" d="M3.6 2.3a1.4 1.4 0 0 0-1.4 1.3v16.8c0 .7.7 1.4 1.4 1.4h16.8a1.4 1.4 0 0 0 1.4-1.4V3.6a1.4 1.4 0 0 0-1.4-1.3H3.6ZM16 6.8h-1.5L11 17.1h1a.8.8 0 0 1 0 1.6H8a.8.8 0 0 1 0-1.6h1.5L13 6.8h-1a.8.8 0 0 1 0-1.5h4a.8.8 0 0 1 0 1.5Z" clip-rule="evenodd"/></svg>', } });
-
Using a web browser, open
dist/html/icons.html
to preview the icons.
Troubleshooting Information for Building Icon Packs
The SVG files are optimized during the build process with SVGO. The optimization can result in distorted graphics due to rounding errors. The graphics may be fixed by providing new SVGO options. To change the SVGO options used:
-
Using a text editor, open
gulpfile.js
. -
Add the
svgo
option to theiconPackager
function, such as:iconPackager({ name: 'my-icon-pack', svgo: { floatPrecision: 3 } //Increase the rounding precision })
All user defined options, including SVGO options, will merge with the default options. For information on SVGO options, see: SVGO on GitHub.
Deploying an Icon Pack
An icon pack can be served either:
Deploy the Icon Pack with TinyMCE
On initialization, TinyMCE will try to load any icon pack specified by the icons option. The icons in the icon pack will be merged with TinyMCE’s default icons and icons in the icon pack will overwrite the default icons with the same identifier.
TinyMCE loads icon packs from the path TINYMCE_BASE/icons/${iconPackName}/icons.js
; where:
-
TINYMCE_BASE
is the TinyMCE root directory (the directory containingtinymce.min.js
). -
${iconPackName}
is the name of the icon pack.
Available icon packs
TinyMCE includes both community and premium icon packs:
-
Community:
default
(always required) -
Premium:
bootstrap
,jam
,material
,small
,thin
(available with paid subscriptions)
For information on creating custom icon packs, see: Create an icon pack for TinyMCE.
Usage
To use a TinyMCE icon pack:
-
If required, create a new
icons
directory inTINYMCE_BASE
. -
Copy the icon pack into the
icons
directory. For example:$ cp -r dist/icons/my_icon_pack TINYMCE_BASE/icons/
-
Add the
icons
option totinymce.init
.
For custom icon packs:
tinymce.init({
selector: 'textarea',
icons: 'my_icon_pack' // TINYMCE_BASE/icons/my_icon_pack/icons.js
});
Deploy the Icon Pack and TinyMCE Separately
On initialization, TinyMCE will try to load any icon pack specified by the icons_url option. The icons in the icon pack will be merged with TinyMCE’s default icons and icons in the icon pack will overwrite the default icons with the same identifier.
icons_url
is used to specify the location of an icon pack when TinyMCE and the icon pack are loaded from different locations. For example: When loading TinyMCE from Tiny Cloud, the icon pack can be loaded from a different web server.
Understanding When using
Example:
The |
Usage
To use a TinyMCE icon pack from a separate location:
-
Ensure the icon pack is available at the specified URL.
-
Add the
icons_url
option totinymce.init
.
For custom icon packs:
tinymce.init({
selector: 'textarea', // change this value according to your HTML
icons_url: 'dist/icons/my_icon_pack/icons.js', // Path to custom icon pack
icons: 'my_icon_pack' // Use custom icon pack
});
Common Development Scenarios
Local Development with Custom Icon Pack
When developing locally with a custom icon pack:
tinymce.init({
selector: 'textarea',
icons_url: 'dist/icons/my_icon_pack/icons.js', // Path to custom icon pack
icons: 'my_icon_pack', // Use custom icon pack
toolbar: 'myButton',
setup: (editor) => {
editor.ui.registry.addButton('myButton', {
icon: 'bold', // Uses your custom bold icon
onAction: (_) => {
editor.insertContent(' <strong>Custom icon clicked!</strong> ');
}
});
}
});
Interactive Demo
See the custom icon pack in action with our interactive demo:
-
TinyMCE
-
HTML
-
JS
-
Edit on CodePen
Default TinyMCE Icons
Custom Icon Pack
<div style="display: flex; gap: 20px; width: 100%; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px;">
<h2>Default TinyMCE Icons</h2>
<textarea id="default-editor" style="width: 100%;">
<h2>Default Icons Editor</h2>
<p>This editor uses the <strong>default TinyMCE icons</strong>.</p>
<p>Notice the standard appearance of the toolbar buttons.</p>
<ul>
<li>Bold, italic, underline buttons</li>
<li>Link and image buttons</li>
<li>List and code buttons</li>
</ul>
</textarea>
</div>
<div style="flex: 1; min-width: 300px;">
<h2>Custom Icon Pack</h2>
<textarea id="custom-editor" style="width: 100%;">
<h2>Custom Icons Editor</h2>
<p>This editor uses a <strong>custom icon pack</strong> created with our icon pack system.</p>
<h3>How It Works:</h3>
<p><strong>Demo Setup:</strong> For this live demo, the custom icons are defined using <code>tinymce.IconManager.add()</code> directly in the JavaScript file.</p>
<p><strong>Production Setup:</strong> In normal usage, you would:</p>
<ul>
<li>Build your icon pack using the template (see our guide)</li>
<li>Place the generated <code>icons.js</code> file in <code>dist/icons/your-pack-name/</code></li>
<li>Use <code>icons_url: 'path/to/icons.js'</code> to load it</li>
</ul>
<p>The editor is configured with <code>icons: 'my-icon-pack'</code> to use the custom icons. <strong>Try the custom buttons:</strong> Look for the custom bold, italic, and audio buttons in the toolbar above.</p>
</textarea>
</div>
</div>
<div style="margin-top: 20px; padding: 15px; background: #f8f9fa; border-radius: 4px; font-size: 14px; color: #666;">
<strong>Icon Credits:</strong> Custom icons in this demo are sourced from <a href="https://freesvgicons.com/" target="_blank" rel="noopener">FreeSVGIcons.com</a> - a collection of 250k+ open-source SVG icons.
</div>
// Load custom icon pack inline (for live demo compatibility)
tinymce.IconManager.add('my-icon-pack', {
icons: {
'audio': '<svg width="24" height="24"><path d="M10.8 19q.9 0 1.5-.7t.7-1.5V13h3v-2h-4v3.9l-.6-.3-.6-.1q-1 0-1.7.7t-.6 1.6q0 .9.7 1.5t1.6.7ZM6 22q-.8 0-1.4-.6T4 20V4q0-.8.6-1.4T6 2h8l6 6v12q0 .8-.6 1.4T18 22H6Zm7-13h5l-5-5v5Z"/></svg>',
'bold': '<svg width="24" height="24"><path fill-rule="evenodd" d="M3.6 2.3a1.4 1.4 0 0 0-1.4 1.3v16.8c0 .7.7 1.4 1.4 1.4h16.8a1.4 1.4 0 0 0 1.4-1.4V3.6a1.4 1.4 0 0 0-1.4-1.3H3.6Zm6 4a1.4 1.4 0 0 0-1.3 1.3v9.3c0 .7.6 1.4 1.3 1.4H12v-.8.8a2.5 2.5 0 0 0 .2 0 4.6 4.6 0 0 0 1.6-.5c.5-.2 1-.5 1.3-1 .4-.5.7-1.2.7-2 0-.9-.3-1.6-.7-2a3.2 3.2 0 0 0-.8-.9 2.8 2.8 0 0 0 .4-.5c.4-.5.5-1.1.5-1.9s-.1-1.4-.5-1.9a3 3 0 0 0-1.1-1 3.9 3.9 0 0 0-1.6-.3H9.6Zm.1 6.5H12a3.2 3.2 0 0 1 1.2.2l.7.6c.2.2.4.6.4 1.1s-.2 1-.4 1.2a1.8 1.8 0 0 1-.7.6 3.2 3.2 0 0 1-1.1.2H9.7v-4Zm2.3 4Zm0-5.6H9.7V7.8H12l1 .2.5.5c.1.2.3.5.3 1s-.2.8-.3 1a1.4 1.4 0 0 1-.6.5 2.3 2.3 0 0 1-.9.2Z" clip-rule="evenodd"/></svg>',
'italic': '<svg width="24" height="24"><path fill-rule="evenodd" d="M3.6 2.3a1.4 1.4 0 0 0-1.4 1.3v16.8c0 .7.7 1.4 1.4 1.4h16.8a1.4 1.4 0 0 0 1.4-1.4V3.6a1.4 1.4 0 0 0-1.4-1.3H3.6ZM16 6.8h-1.5L11 17.1h1a.8.8 0 0 1 0 1.6H8a.8.8 0 0 1 0-1.6h1.5L13 6.8h-1a.8.8 0 0 1 0-1.5h4a.8.8 0 0 1 0 1.5Z" clip-rule="evenodd"/></svg>',
}
});
// Default Icons Editor
tinymce.init({
selector: '#default-editor',
icons: 'material', // use material icon pack
plugins: 'lists link image code',
toolbar: 'undo redo | bold italic underline | bullist numlist | link image code',
height: 500,
// license_key: 'gpl'
});
// Custom Icons Editor
tinymce.init({
selector: '#custom-editor',
icons: 'my-icon-pack',
plugins: 'lists link image code',
toolbar: 'undo redo | myButton1 myButton2 myButton3 | bullist numlist | link image code',
height: 500,
setup: (editor) => {
editor.ui.registry.addButton('myButton1', {
icon: 'bold', // the 'bold' icon created from 'bold.svg'
onAction: (_) => {
editor.insertContent(' <strong>It\'s my custom bold icon button!</strong> ');
}
});
editor.ui.registry.addButton('myButton2', {
icon: 'italic', // the 'italic' icon created from 'italic.svg'
onAction: (_) => {
editor.insertContent(' <strong>It\'s my custom italic icon button!</strong> ');
}
});
editor.ui.registry.addButton('myButton3', {
icon: 'audio', // the 'audio' icon created from 'audio.svg'
onAction: (_) => {
editor.insertContent(' <strong>It\'s my custom audio icon button!</strong> ');
}
});
}
});