webfer / custom_bootstrap_icon_font
Drupal module that generates a custom WOFF2 icon font from a selected subset of Bootstrap Icons and publishes matching CSS classes.
Package info
github.com/webfer/custom_bootstrap_icon_font
Type:drupal-module
pkg:composer/webfer/custom_bootstrap_icon_font
Requires
- drupal/core: ^10 || ^11
Suggests
- drush/drush: Required to run the build command (drush di-font:build).
- npm:fantasticon: Required to generate the font assets; install via npm (e.g. `npm i -D fantasticon`) and use `npx fantasticon` (or set generator_command accordingly).
README
A Drupal module that generates a custom icon font (WOFF2 + optional WOFF) from a selected subset of Bootstrap Icons and/or Font Awesome Free SVGs, and publishes matching CSS classes.
π Why? Keep your frontend lightweight: instead of shipping entire icon sets, you can select only the icons your site actually uses and generate a small, focused font + CSS just for those.
π¦ Module Overview
- Name: Custom Bootstrap Icon Font
- Package: Media
- Compatibility: Drupal 10, 11
This module:
- Provides an admin page to select icons and configure the build.
- Builds the font either via Drush (recommended) or via a UI button (handy for local/dev).
- Writes generated assets to
public://custom_bootstrap_icon_font/font/. - Automatically attaches the generated CSS on the frontend (only if it exists).
- Provides Twig helpers to render icon markup.
Key features
- Split icon configuration by source
- Separate lists for Bootstrap Icons and Font Awesome Free.
- Select icons by name, by class, or by pasted HTML snippets
- Bootstrap accepts lines like
arrow-right-circle-fill,bi-arrow-right-circle-fill,bi bi-arrow-right-circle-fill, or<i class="bi bi-arrow-right-circle-fill"></i>. - Font Awesome accepts lines like
<i class="fa-solid fa-arrow-down"></i>,fa-arrow-down, orfa-solid-arrow-down.
- Bootstrap accepts lines like
- Stable glyph codepoints across rebuilds
- Codepoints are stored in config so previously-used icons keep the same Unicode value when re-added.
- Bootstrap-like CSS output
- Generates a small CSS file that maps
.di-<icon>to a glyph via::before { content: "\\e001"; }.
- Generates a small CSS file that maps
- Composer/CI friendly
- Bootstrap Icons live in
web/libraries/bootstrap-icons/icons. - Font Awesome SVGs live in
web/libraries/fontawesome/icons. - Fantasticon is installed at the project level (or globally) and executed via Drush.
- Bootstrap Icons live in
π Installation
β Install with Composer (recommended) π§°
From your Drupal project root:
composer require webfer/custom_bootstrap_icon_font
Composer will install the module into your Drupal codebase (commonly under web/modules/contrib/ in standard Drupal Composer templates). π¦
Then enable the module:
- π Admin > Extend β enable Custom Bootstrap Icon Font, or
- π»
drush en custom_bootstrap_icon_font -y
π§© Install without Composer (development only)
If youβre developing locally, you can still place the module folder under:
web/modules/custom/custom_bootstrap_icon_font
β Requirements
Drupal
- Drupal core 10/11.
- Ability to write to
public://(this module stores generated assets underpublic://custom_bootstrap_icon_font/).
Bootstrap Icons SVG sources
The build needs access to the Bootstrap Icons SVG files (*.svg).
Recommended location (Drupal libraries):
web/libraries/bootstrap-icons/icons
You can install Bootstrap Icons there by either:
- Downloading a release from https://github.com/twbs/icons/releases and extracting to
web/libraries/bootstrap-icons, or - Using a build/CI step to fetch it.
Font Awesome Free SVG sources
Font Awesome icons are not bundled by this module. You provide the SVGs.
Recommended location (Drupal libraries):
web/libraries/fontawesome/icons
Where to obtain icons:
- Browse/search the Free collection: https://fontawesome.com/search?ic=free
Recommended workflow:
- Find an icon in the Free collection.
- Download the SVG.
- Upload it into
web/libraries/fontawesome/icons.- You can use the admin UI βUpload SVG icons (optional)β section.
- Note: some hosts do not allow writing to
DRUPAL_ROOT/librariesfrom the web UI; in that case upload via SFTP/CI.
- Paste the corresponding snippet into the Font Awesome list (example:
<i class="fa-solid fa-arrow-down"></i>).
Node tooling (required for building assets)
Asset generation uses Fantasticon, typically via npx fantasticon.
You need:
node,npm,npx- Fantasticon available to the same environment that runs
drush.
Tip π‘: If you plan to build from the admin UI (βSave and build nowβ), the same Node tooling must also be available to the PHP/web user, and the request must be allowed to run long enough.
Recommended (project-level, deterministic):
cd /path/to/project/root # the folder you run drush from # Only needed if you don't already have a root package.json. npm init -y npm install --save-dev fantasticon # Verify it is available without prompting/downloading. npx --no-install fantasticon --version
Alternative (global install):
npm install -g fantasticon fantasticon --version
Important:
- If Fantasticon is not installed locally/globally,
npx fantasticonmay try to download it interactively (not suitable for non-interactive servers/CI). - If you use Yarn or pnpm, install Fantasticon in your project and set
generator_commandaccordingly.
β Configuration
1) Permissions
The admin UI requires:
- Permission:
administer custom bootstrap icon font
Assign it under People > Permissions.
2) Build / update the font
Go to:
- Admin path:
/admin/config/media/bootstrap-icon-font
On this page you can:
- Enter Bootstrap icons (one per line).
- Names may include or omit the
bi-prefix; it is normalized automatically. - You can also paste full HTML snippets and the module will extract the icon name automatically (example:
<i class="bi bi-basket-fill"></i>).
- Names may include or omit the
- Enter Font Awesome Free icons (one per line).
- Paste snippets like
<i class="fa-solid fa-arrow-down"></i>. - Or use shorthand
fa-arrow-down/fa-solid-arrow-down. - Ensure the matching SVG exists under
web/libraries/fontawesome/icons(see Requirements above).
- Paste snippets like
- Pick a
font_name(thefont-familyname used in CSS). - Configure where Bootstrap Icons live (
icons_source_dir). - Configure where Font Awesome SVGs live (
fontawesome_icons_source_dir). - Configure the generator command (
generator_command). - Use the Icons preview section to browse your selected icons.
- The preview is paginated (configure Icons per page on the form).
Optional: Upload SVG icons from the UI
The admin page also includes an Upload SVG icons (optional) section.
- Step 1: Upload one or more
.svgfiles (they are stored temporarily). - Step 2: Click Copy uploaded SVGs into libraries/ to copy them into either:
web/libraries/fontawesome/icons(recommended for Font Awesome), or- your configured Bootstrap Icons source directory.
If your server does not allow writing to DRUPAL_ROOT/libraries from PHP, upload icons via SFTP/CI instead.
β Build assets (two options)
Option A: Build from the UI (friendly) π±οΈ
- Click Save and build now.
- The module generates the CSS + font files under
public://custom_bootstrap_icon_font/font/.
This is great for local/dev. On production, Drush is usually safer (no web timeouts and doesnβt require Node to run during a web request).
Option B: Build via Drush (recommended) π§βπ»
drush di-font:build
Aliases are kept for backwards compatibility:
drush custom-bootstrap-icon-font:build drush ci-font:build drush cbi-font:build
When the build completes, the module:
- Saves the selected icons to config (
custom_bootstrap_icon_font.settings). - Maintains a stable
codepointsmapping so glyphs donβt change between regenerations. - Writes:
public://custom_bootstrap_icon_font/font/<font_name>.woff2public://custom_bootstrap_icon_font/font/<font_name>.woff(optional)public://custom_bootstrap_icon_font/font/custom-bootstrap-icon-font.css
- Updates
versionfor cache-busting. - Invalidates render cache.
π§© Usage
Option A: CSS classes (Bootstrap-like)
After generating assets, you can render icons using classes and a pseudo-element:
<span class="di di-arrow-right-circle-fill" aria-hidden="true"></span> <span class="di di-fa-solid-arrow-down" aria-hidden="true"></span> <span class="di-youtube" aria-hidden="true"></span>
Notes:
- The generated CSS includes Bootstrap-icons style selectors:
.di::before, [class^="di-"]::before, [class*=" di-"]::before { ... }
- The icon is rendered by
::before { content: "\\e001"; }.
Option B: Twig helper
This module provides:
{{ di_font_icon('arrow-right-circle-fill') }}
{{ di_font_icon('fa-solid-arrow-down') }}
{{ di_font_icon('youtube', { class: 'text-danger me-2' }) }}
Backwards-compatible Twig function names are also available (if you used older templates):
{{ ci_font_icon('arrow-right-circle-fill') }}
{{ cbi_font_icon('arrow-right-circle-fill') }}
π§± Fantasticon specification
This module is a thin wrapper around the Fantasticon CLI.
Inputs
- Bootstrap Icons list: stored in
custom_bootstrap_icon_font.settings:bootstrap_icons - Font Awesome list: stored in
custom_bootstrap_icon_font.settings:fontawesome_icons- Backwards compatibility: older installs may still have a merged
custom_bootstrap_icon_font.settings:iconslist; the build keeps it in sync.
- Backwards compatibility: older installs may still have a merged
- Bootstrap Icons source directory: stored in
custom_bootstrap_icon_font.settings:icons_source_dir- Default:
libraries/bootstrap-icons/icons(relative toDRUPAL_ROOT)
- Default:
- Font Awesome source directory: stored in
custom_bootstrap_icon_font.settings:fontawesome_icons_source_dir- Default:
libraries/fontawesome/icons(relative toDRUPAL_ROOT)
- Default:
- Generator command: stored in
custom_bootstrap_icon_font.settings:generator_command- Default:
npx fantasticon - Note: it is split on whitespace (simple tokenization). If you need complex quoting, use a small wrapper script and point
generator_commandat it.
- Default:
Generated Fantasticon config
During drush di-font:build, the module stages the selected SVGs into a temporary folder and generates a Fantasticon JSON config equivalent to:
{
"name": "<font_name>",
"inputDir": "<temporary>/icons",
"outputDir": "<public_files>/custom_bootstrap_icon_font/font",
"fontTypes": ["woff2", "woff"],
"assetTypes": [],
"normalize": true,
"fontHeight": 512,
"descent": 0,
"codepoints": {
"arrow-right-circle-fill": 57345,
"fa-solid-arrow-down": 57346
}
}
Important details:
codepointsare provided explicitly to keep glyphs stable between builds.- Only the currently selected icons are emitted into the font/CSS, but the module keeps a historical mapping in config so re-adding an icon later can reuse the same codepoint.
normalize/fontHeight/descentare set to keep icon sizes consistent when mixing Bootstrap Icons (typically 16Γ16 viewBox) with Font Awesome (typically 512Γ512 viewBox).
Outputs
Files written to public://custom_bootstrap_icon_font/font/:
<font_name>.woff2<font_name>.woff(optional fallback)custom-bootstrap-icon-font.css(uses relative./<font_name>.woff2?v=<version>URLs)
π¨ Styling
Because this is a font:
- Icon color is controlled by
color. - Icon size is controlled by
font-size.
Example:
.di, [class^='di-'], [class*=' di-'] { color: currentColor; }
π¨ Troubleshooting
-
βIcon not found: β¦β
- For Bootstrap Icons: confirm the icon exists in your Bootstrap Icons version. Example:
youtube.svgshould exist. - For Font Awesome: confirm the SVG exists under
web/libraries/fontawesome/icons.- Some downloads have non-canonical filenames; the module attempts a best-effort match, but itβs still safest to keep filenames close to the icon name (example:
arrow-down.svg).
- Some downloads have non-canonical filenames; the module attempts a best-effort match, but itβs still safest to keep filenames close to the icon name (example:
- Ensure the configured source directories exist:
icons_source_dir(recommended:web/libraries/bootstrap-icons/icons)fontawesome_icons_source_dir(recommended:web/libraries/fontawesome/icons)
- For Bootstrap Icons: confirm the icon exists in your Bootstrap Icons version. Example:
-
Build fails
- Ensure Node.js + npm + npx are installed.
- Ensure Fantasticon is available on PATH (or set
generator_commandaccordingly). - Run the build from the same environment where
drushruns. - If you use the UI build, confirm the web/PHP user can run the generator command and that the request wonβt time out.
-
I clicked βSave configurationβ but nothing was generated
- That button only saves settings.
- To generate the CSS + fonts, click Save and build now (or run
drush di-font:build).
-
CSS loads but icons show as empty squares
- Font files are missing or blocked. Check the network tab for
.woff2. - Confirm the CSS and fonts are in the same directory (so relative
./<font>.woff2resolves).
- Font files are missing or blocked. Check the network tab for
-
Icons changed after regeneration
- Stable glyphs require stable codepoints. This module stores
codepointsin config; avoid deleting that config between runs.
- Stable glyphs require stable codepoints. This module stores
π File Structure
custom_bootstrap_icon_font/
βββ composer.json
βββ LICENSE
βββ custom_bootstrap_icon_font.info.yml
βββ custom_bootstrap_icon_font.module
βββ custom_bootstrap_icon_font.routing.yml
βββ custom_bootstrap_icon_font.permissions.yml
βββ custom_bootstrap_icon_font.links.menu.yml
βββ custom_bootstrap_icon_font.services.yml
βββ custom_bootstrap_icon_font.libraries.yml
βββ drush.services.yml
βββ css/
β βββ custom_bootstrap_icon_font.admin.css
βββ config/
β βββ install/
β β βββ custom_bootstrap_icon_font.settings.yml
β βββ schema/
β βββ custom_bootstrap_icon_font.schema.yml
βββ src/
βββ Commands/
β βββ CustomBootstrapIconFontCommands.php
βββ Form/
β βββ CustomBootstrapIconFontGenerateForm.php
βββ Helper/
β βββ CustomBootstrapIconFontHelper.php
βββ Service/
β βββ CustomBootstrapIconFontBuilder.php
βββ Twig/
βββ CustomBootstrapIconFontTwigExtension.php
π License
This project is licensed under the GNU General Public License, version 2 or (at your option) any later version.
- SPDX identifier:
GPL-2.0-or-later - Created by: WebFer
_Created and maintained by WebFer