Simplifying icon integration: A Step-by-Step guide to custom icon fonts in JavaScript projects

Table of Contents

Introduction

In our platform, Karelics Cloud, we strive to automate repetitive tasks and improve interactions with robots through our robotic fleet management capabilities. As part of our efforts, we often incorporate custom icons into our platform, particularly for construction site photo documentation UI. To achieve this, we have developed a process for creating and extending a custom icon. In this article, we will outline the algorithm we follow to create a custom icon font that can be applied to various JavaScript projects.

Creation and Installation

We use Material Symbols as our main icon font, but there are times when we need custom icons. To meet this need, we have created our own icon font.

Below is the alghotithm for creating/extending our own icon font:

  1. To start, export the desired icons in SVG format from design tools such as Figma. After exporting, clean up the icons by removing unnecessary attributes like “fill” and adjusting their sizes using Online SVG code editor service.

    Example of SVG code for the “device.svg” icon:

				
					<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
  <path d="M3.6665 9.85742C3.6665 8.75285 4.56193 7.85742 5.6665 7.85742H18.6665C20.3234 7.85742 21.6665 9.20057 21.6665 10.8574V12.5717C21.6665 14.2286 20.3234 15.5717 18.6665 15.5717H5.6665C4.56193 15.5717 3.6665 14.6763 3.6665 13.5717V9.85742Z"></path>
  <path d="M4.95215 5C4.95215 4.44772 5.39986 4 5.95215 4H9.095C9.64729 4 10.095 4.44772 10.095 5V5.57143C10.095 6.12371 9.64729 6.57143 9.09501 6.57143H5.95215C5.39986 6.57143 4.95215 6.12371 4.95215 5.57143V5Z"></path>
  <path d="M10.0952 18.4287C10.0952 18.981 9.6475 19.4287 9.09521 19.4287L5.95236 19.4287C5.40007 19.4287 4.95236 18.981 4.95236 18.4287L4.95236 17.8573C4.95236 17.305 5.40007 16.8573 5.95236 16.8573L9.09521 16.8573C9.6475 16.8573 10.0952 17.305 10.0952 17.8573L10.0952 18.4287Z"></path>
  <path d="M17.8096 18.4287C17.8096 18.981 17.3619 19.4287 16.8096 19.4287L13.6667 19.4287C13.1144 19.4287 12.6667 18.981 12.6667 18.4287L12.6667 17.8573C12.6667 17.305 13.1144 16.8573 13.6667 16.8573L16.8096 16.8573C17.3619 16.8573 17.8096 17.305 17.8096 17.8573L17.8096 18.4287Z"></path>
  <path d="M12.6665 5C12.6665 4.44772 13.1142 4 13.6665 4H16.8094C17.3616 4 17.8094 4.44772 17.8094 5V5.57143C17.8094 6.12371 17.3616 6.57143 16.8094 6.57143H13.6665C13.1142 6.57143 12.6665 6.12371 12.6665 5.57143V5Z"></path>
</svg>
				
			

device.svg

  1. Open IcoMoon and click the “IcoMoon App“ button. As written on their website “The IcoMoon app is free to use. Code files (HTML, CSS, JS) generated by IcoMoon are MIT licensed.”
  2. Create a new empty set:
  1. Import our icons:
  1. Select all icons and click the “Generate Font“ button:
  1. On the next page you can set the names of the icons (file names by default). Click on the gear to open font settings:
  1. Here are the settings we use for our icon font:
  1. Download the generated font files and put them into your JavaScript project:

Make necessary adjustments to the font paths in your project’s CSS file. Additionally, if required, update/add the font import styles in your project’s HTML file using the element.

				
					<head>
  <meta charset="UTF-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>

  <!-- Importing the custom font -->
  <link rel="stylesheet" href="./kc-icons/style.css"/>
...</head>
				
			

Usage

Here is an example of using custom icons:

				
					<body>
  <div>Custom icons</div>
  <span class="kc-icon kc-device"></span>
  <span class="kc-icon kc-lift"></span>
  <span class="kc-icon kc-lift_open"></span>
<script  src="https://karelics.fi/wp-includes/js/jquery/jquery.min.js?ver=3.7.1" id="jquery-core-js"></script><script type="text/javascript" id="albion-main-js-extra">
/* <![CDATA[ */
var dateData = {"endTime":" "};
//# sourceURL=albion-main-js-extra
/* ]]> */
</script><script type='text/javascript' src='https://karelics.fi/wp-content/boost-cache/static/369d61afb0.min.js'></script><script data-borlabs-cookie-script-blocker-handle="google_gtagjs" data-borlabs-cookie-script-blocker-id="site-kit-analytics" type='text/template' data-borlabs-cookie-script-blocker-src="https://www.googletagmanager.com/gtag/js?id=GT-5R6QNL4" id="google_gtagjs-js"></script><script data-borlabs-cookie-script-blocker-handle="google_gtagjs" data-borlabs-cookie-script-blocker-id="site-kit-analytics" type='text/template'  id="google_gtagjs-js-after">
/* <![CDATA[ */
window.dataLayer = window.dataLayer || [];function gtag(){dataLayer.push(arguments);}
gtag("set","linker",{"domains":["karelics.fi"]});
gtag("js", new Date());
gtag("set", "developer_id.dZTNiMT", true);
gtag("config", "GT-5R6QNL4");
//# sourceURL=google_gtagjs-js-after
/* ]]> */
</script><script class="hsq-set-content-id" data-content-id="blog-post">
				var _hsq = _hsq || [];
				_hsq.push(["setContentType", "blog-post"]);
			</script><script data-borlabs-cookie-script-blocker-ignore>
if ('0' === '1' && ('0' === '1' || '1' === '1')) {
    window['gtag_enable_tcf_support'] = true;
}
window.dataLayer = window.dataLayer || [];
if (typeof gtag !== 'function') {
    function gtag() {
        dataLayer.push(arguments);
    }
}
gtag('set', 'developer_id.dYjRjMm', true);
if ('0' === '1' || '1' === '1') {
    if (window.BorlabsCookieGoogleConsentModeDefaultSet !== true) {
        let getCookieValue = function (name) {
            return document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)')?.pop() || '';
        };
        let cookieValue = getCookieValue('borlabs-cookie-gcs');
        let consentsFromCookie = {};
        if (cookieValue !== '') {
            consentsFromCookie = JSON.parse(decodeURIComponent(cookieValue));
        }
        let defaultValues = {
            'ad_storage': 'denied',
            'ad_user_data': 'denied',
            'ad_personalization': 'denied',
            'analytics_storage': 'denied',
            'functionality_storage': 'denied',
            'personalization_storage': 'denied',
            'security_storage': 'denied',
            'wait_for_update': 500,
        };
        gtag('consent', 'default', { ...defaultValues, ...consentsFromCookie });
    }
    window.BorlabsCookieGoogleConsentModeDefaultSet = true;
    let borlabsCookieConsentChangeHandler = function () {
        window.dataLayer = window.dataLayer || [];
        if (typeof gtag !== 'function') { function gtag(){dataLayer.push(arguments);} }

        let getCookieValue = function (name) {
            return document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)')?.pop() || '';
        };
        let cookieValue = getCookieValue('borlabs-cookie-gcs');
        let consentsFromCookie = {};
        if (cookieValue !== '') {
            consentsFromCookie = JSON.parse(decodeURIComponent(cookieValue));
        }

        consentsFromCookie.analytics_storage = BorlabsCookie.Consents.hasConsent('google-analytics') ? 'granted' : 'denied';

        BorlabsCookie.CookieLibrary.setCookie(
            'borlabs-cookie-gcs',
            JSON.stringify(consentsFromCookie),
            BorlabsCookie.Settings.automaticCookieDomainAndPath.value ? '' : BorlabsCookie.Settings.cookieDomain.value,
            BorlabsCookie.Settings.cookiePath.value,
            BorlabsCookie.Cookie.getPluginCookie().expires,
            BorlabsCookie.Settings.cookieSecure.value,
            BorlabsCookie.Settings.cookieSameSite.value
        );
    }
    document.addEventListener('borlabs-cookie-consent-saved', borlabsCookieConsentChangeHandler);
    document.addEventListener('borlabs-cookie-handle-unblock', borlabsCookieConsentChangeHandler);
}
if ('0' === '1') {
    gtag("js", new Date());
    gtag("config", "UA-161591979-1", {"anonymize_ip": true});

    (function (w, d, s, i) {
        var f = d.getElementsByTagName(s)[0],
            j = d.createElement(s);
        j.async = true;
        j.src =
            "https://www.googletagmanager.com/gtag/js?id=" + i;
        f.parentNode.insertBefore(j, f);
    })(window, document, "script", "UA-161591979-1");
}
</script><script data-no-optimize="1" data-no-minify="1" data-cfasync="false" data-borlabs-cookie-script-blocker-ignore>
if ('{{ iab-tcf-enabled }}' === '1' && ('0' === '1' || '1' === '1')) {
    window['gtag_enable_tcf_support'] = true;
}
window.dataLayer = window.dataLayer || [];
if (typeof gtag !== 'function') {
    function gtag() {
        dataLayer.push(arguments);
    }
}
gtag('set', 'developer_id.dYjRjMm', true);
if ('0' === '1' || '1' === '1') {
    if (window.BorlabsCookieGoogleConsentModeDefaultSet !== true) {
        let getCookieValue = function (name) {
            return document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)')?.pop() || '';
        };
        let cookieValue = getCookieValue('borlabs-cookie-gcs');
        let consentsFromCookie = {};
        if (cookieValue !== '') {
            consentsFromCookie = JSON.parse(decodeURIComponent(cookieValue));
        }
        let defaultValues = {
            'ad_storage': 'denied',
            'ad_user_data': 'denied',
            'ad_personalization': 'denied',
            'analytics_storage': 'denied',
            'functionality_storage': 'denied',
            'personalization_storage': 'denied',
            'security_storage': 'denied',
            'wait_for_update': 500,
        };
        gtag('consent', 'default', { ...defaultValues, ...consentsFromCookie });
    }
    window.BorlabsCookieGoogleConsentModeDefaultSet = true;
    let borlabsCookieConsentChangeHandler = function () {
        window.dataLayer = window.dataLayer || [];
        if (typeof gtag !== 'function') { function gtag(){dataLayer.push(arguments);} }

        let getCookieValue = function (name) {
            return document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)')?.pop() || '';
        };
        let cookieValue = getCookieValue('borlabs-cookie-gcs');
        let consentsFromCookie = {};
        if (cookieValue !== '') {
            consentsFromCookie = JSON.parse(decodeURIComponent(cookieValue));
        }

        consentsFromCookie.analytics_storage = BorlabsCookie.Consents.hasConsent('google-analytics-site-kit') ? 'granted' : 'denied';

        BorlabsCookie.CookieLibrary.setCookie(
            'borlabs-cookie-gcs',
            JSON.stringify(consentsFromCookie),
            BorlabsCookie.Settings.automaticCookieDomainAndPath.value ? '' : BorlabsCookie.Settings.cookieDomain.value,
            BorlabsCookie.Settings.cookiePath.value,
            BorlabsCookie.Cookie.getPluginCookie().expires,
            BorlabsCookie.Settings.cookieSecure.value,
            BorlabsCookie.Settings.cookieSameSite.value
        );
    }
    document.addEventListener('borlabs-cookie-consent-saved', borlabsCookieConsentChangeHandler);
    document.addEventListener('borlabs-cookie-handle-unblock', borlabsCookieConsentChangeHandler);
}
if ('0' === '1') {
    document.addEventListener('borlabs-cookie-after-init', function () {
		window.BorlabsCookie.Unblock.unblockScriptBlockerId('site-kit-analytics');
	});
}
</script><script type="speculationrules">
{"prefetch":[{"source":"document","where":{"and":[{"href_matches":"/*"},{"not":{"href_matches":["/wp-*.php","/wp-admin/*","/wp-content/uploads/*","/wp-content/*","/wp-content/plugins/*","/wp-content/themes/albion-child/*","/wp-content/themes/albion/*","/*\\?(.+)"]}},{"not":{"selector_matches":"a[rel~=\"nofollow\"]"}},{"not":{"selector_matches":".no-prefetch, .no-prefetch a"}}]},"eagerness":"conservative"}]}
</script><script type="module" src="https://karelics.fi/wp-content/plugins/borlabs-cookie/assets/javascript/borlabs-cookie.min.js?ver=3.4" id="borlabs-cookie-core-js-module" data-cfasync="false" data-no-minify="1" data-no-optimize="1"></script><script type="module" src="https://karelics.fi/wp-content/plugins/borlabs-cookie/assets/javascript/borlabs-cookie-legacy-backward-compatibility.min.js?ver=3.4" id="borlabs-cookie-legacy-backward-compatibility-js-module"></script><script>
				const lazyloadRunObserver = () => {
					const lazyloadBackgrounds = document.querySelectorAll( `.e-con.e-parent:not(.e-lazyloaded)` );
					const lazyloadBackgroundObserver = new IntersectionObserver( ( entries ) => {
						entries.forEach( ( entry ) => {
							if ( entry.isIntersecting ) {
								let lazyloadBackground = entry.target;
								if( lazyloadBackground ) {
									lazyloadBackground.classList.add( 'e-lazyloaded' );
								}
								lazyloadBackgroundObserver.unobserve( entry.target );
							}
						});
					}, { rootMargin: '200px 0px 200px 0px' } );
					lazyloadBackgrounds.forEach( ( lazyloadBackground ) => {
						lazyloadBackgroundObserver.observe( lazyloadBackground );
					} );
				};
				const events = [
					'DOMContentLoaded',
					'elementor/lazyload/observe',
				];
				events.forEach( ( event ) => {
					document.addEventListener( event, lazyloadRunObserver );
				} );
			</script><script>window.addEventListener( 'load', function() {
				document.querySelectorAll( 'link' ).forEach( function( e ) {'not all' === e.media && e.dataset.media && ( e.media = e.dataset.media, delete e.dataset.media );} );
				var e = document.getElementById( 'jetpack-boost-critical-css' );
				e && ( e.media = 'not all' );
			} );</script><script type="text/javascript" id="xpro-elementor-addons-widgets-js-extra">
/* <![CDATA[ */
var XproElementorAddons = {"ajax_url":"https://karelics.fi/wp-admin/admin-ajax.php","nonce":"fa812c2755"};
//# sourceURL=xpro-elementor-addons-widgets-js-extra
/* ]]> */
</script><script type='text/javascript' src='https://karelics.fi/wp-content/boost-cache/static/2baf0d0940.min.js'></script><script  src="https://karelics.fi/wp-includes/js/dist/i18n.min.js?ver=c26c3dc7bed366793375" id="wp-i18n-js"></script><script  id="wp-i18n-js-after">
/* <![CDATA[ */
wp.i18n.setLocaleData( { 'text direction\u0004ltr': [ 'ltr' ] } );
//# sourceURL=wp-i18n-js-after
/* ]]> */
</script><script  src='https://karelics.fi/wp-content/plugins/contact-form-7/includes/swv/js/index.js?m=1770575396'></script><script  id="contact-form-7-js-before">
/* <![CDATA[ */
var wpcf7 = {
    "api": {
        "root": "https:\/\/karelics.fi\/wp-json\/",
        "namespace": "contact-form-7\/v1"
    },
    "cached": 1
};
//# sourceURL=contact-form-7-js-before
/* ]]> */
</script><script  src="https://karelics.fi/wp-content/plugins/contact-form-7/includes/js/index.js?ver=6.1.5" id="contact-form-7-js"></script><script type="text/javascript" id="leadin-script-loader-js-js-extra">
/* <![CDATA[ */
var leadin_wordpress = {"userRole":"visitor","pageType":"post","leadinPluginVersion":"11.3.45"};
//# sourceURL=leadin-script-loader-js-js-extra
/* ]]> */
</script><script data-borlabs-cookie-script-blocker-id='hubspot-tracking-code' type='text/template' data-borlabs-cookie-script-blocker-handle="leadin-script-loader-js" data-borlabs-cookie-script-blocker-id="hubspot-tracking-code" type='text/template' data-borlabs-cookie-script-blocker-src="https://js-eu1.hs-scripts.com/26112895.js?integration=WordPress&amp;ver=11.3.45" id="leadin-script-loader-js-js"></script><script  src='https://karelics.fi/wp-content/plugins/elementor/assets/js/webpack.runtime.min.js?m=1778092206'></script><script  id="elementor-frontend-modules-js-before">
/* <![CDATA[ */
(function() {
    const allFbWidgets = document.querySelectorAll('div.elementor-widget[data-widget_type^="facebook"]');
    for (let fb of allFbWidgets) {
        fb.dataset.widget_type = 'brlabs_' + fb.dataset.widget_type;
    }
})();
(function() {
    const allYtWidgets = document.querySelectorAll('div.elementor-widget-video[data-widget_type^="video."][data-settings*="youtube_url"]');
    for (let yt of allYtWidgets) {
        if (yt.dataset.brlbsUnblocked === 'true') {
            continue;
        }
        yt.dataset.widget_type = 'brlbs_' + yt.dataset.widget_type;
        yt.dataset.settings = yt.dataset.settings.replace('show_image_overlay', 'brlbs_dont_show_image_overlay');
    }
})();
(function() {
    window.addEventListener( 'elementor/frontend/init', function() {
        let first = true;
        elementorFrontend.hooks.addAction('frontend/element_ready/global', () => {
            if (first === true) {
                first = false;
                const allYoutubeBgs = document.querySelectorAll('[data-brlbs-elementor-bg-video-yt="true"]');
                if (allYoutubeBgs.length > 0) {
                    const ytApiReadyOriginal = elementorFrontend.utils.youtube.onApiReady;
                    let waitingYtCounter = 0;
                    elementorFrontend.utils.youtube.onApiReady = (callback) => {
                        document.addEventListener('brlbs_elementor_bgVideo_yt_unblocked', () => {
                            ytApiReadyOriginal.call(elementorFrontend.utils.youtube, callback);
                        });
                        if (++waitingYtCounter === allYoutubeBgs.length) {
                            elementorFrontend.utils.youtube.onApiReady = ytApiReadyOriginal;
                            window.brlbsElementorBgVideoYtUnblockReady = { state: true };
                        }
                    }
                }

                const allVimeoBgs = document.querySelectorAll('[data-brlbs-elementor-bg-video-vimeo="true"]');
                if (allVimeoBgs.length > 0) {
                    const vimeoApiReadyOriginal = elementorFrontend.utils.vimeo.onApiReady;
                    let waitingVimeoCounter = 0;
                    elementorFrontend.utils.vimeo.onApiReady = (callback) => {
                        document.addEventListener('brlbs_elementor_bgVideo_vimeo_unblocked', () => {
                            vimeoApiReadyOriginal.call(elementorFrontend.utils.vimeo, callback);
                        });
                        if (++waitingVimeoCounter === allVimeoBgs.length) {
                            elementorFrontend.utils.vimeo.onApiReady = vimeoApiReadyOriginal;
                            window.brlbsElementorBgVideoVimeoUnblockReady = { state: true };
                        }
                    }
                }
            }
        });
    });
})();
//# sourceURL=elementor-frontend-modules-js-before
/* ]]> */
</script><script  src="https://karelics.fi/wp-content/plugins/elementor/assets/js/frontend-modules.min.js?ver=4.0.7" id="elementor-frontend-modules-js"></script><script  src='https://karelics.fi/wp-includes/js/jquery/ui/core.min.js?m=1745313328'></script><script  id="elementor-frontend-js-before">
/* <![CDATA[ */
var elementorFrontendConfig = {"environmentMode":{"edit":false,"wpPreview":false,"isScriptDebug":false},"i18n":{"shareOnFacebook":"Share on Facebook","shareOnTwitter":"Share on Twitter","pinIt":"Pin it","download":"Download","downloadImage":"Download image","fullscreen":"Fullscreen","zoom":"Zoom","share":"Share","playVideo":"Play Video","previous":"Previous","next":"Next","close":"Close","a11yCarouselPrevSlideMessage":"Previous slide","a11yCarouselNextSlideMessage":"Next slide","a11yCarouselFirstSlideMessage":"This is the first slide","a11yCarouselLastSlideMessage":"This is the last slide","a11yCarouselPaginationBulletMessage":"Go to slide"},"is_rtl":false,"breakpoints":{"xs":0,"sm":480,"md":768,"lg":1025,"xl":1440,"xxl":1600},"responsive":{"breakpoints":{"mobile":{"label":"Mobile Portrait","value":767,"default_value":767,"direction":"max","is_enabled":true},"mobile_extra":{"label":"Mobile Landscape","value":880,"default_value":880,"direction":"max","is_enabled":false},"tablet":{"label":"Tablet Portrait","value":1024,"default_value":1024,"direction":"max","is_enabled":true},"tablet_extra":{"label":"Tablet Landscape","value":1200,"default_value":1200,"direction":"max","is_enabled":false},"laptop":{"label":"Laptop","value":1366,"default_value":1366,"direction":"max","is_enabled":false},"widescreen":{"label":"Widescreen","value":2400,"default_value":2400,"direction":"min","is_enabled":false}},
"hasCustomBreakpoints":false},"version":"4.0.7","is_static":false,"experimentalFeatures":{"e_font_icon_svg":true,"additional_custom_breakpoints":true,"container":true,"theme_builder_v2":true,"nested-elements":true,"global_classes_should_enforce_capabilities":true,"e_variables":true,"e_opt_in_v4_page":true,"e_components":true,"e_interactions":true,"e_widget_creation":true,"import-export-customization":true,"e_pro_atomic_form":true,"e_pro_variables":true,"e_pro_interactions":true},"urls":{"assets":"https:\/\/karelics.fi\/wp-content\/plugins\/elementor\/assets\/","ajaxurl":"https:\/\/karelics.fi\/wp-admin\/admin-ajax.php","uploadUrl":"https:\/\/karelics.fi\/wp-content\/uploads"},"nonces":{"floatingButtonsClickTracking":"d0d4e9d978","atomicFormsSendForm":"88574eee2b"},"swiperClass":"swiper","settings":{"page":[],"editorPreferences":[]},"kit":{"active_breakpoints":["viewport_mobile","viewport_tablet"],"global_image_lightbox":"yes","lightbox_description_src":"description"},"post":{"id":14341,"title":"A%20Step-by-Step%20guide%20to%20custom%20icon%20fonts%20in%20JavaScript%20projects","excerpt":"In our platform, Karelics Cloud, we strive to automate repetitive tasks and improve interactions with robots through our robotic fleet management capabilities. As part of our efforts, we often incorporate custom icons into our platform, particularly for construction site photo documentation UI. To achieve this, we have developed a process for creating and extending a custom icon. In this article, we will outline the algorithm we follow to create a custom icon font that can be applied to various JavaScript projects.","featuredImage":"https:\/\/i0.wp.com\/karelics.fi\/wp-content\/uploads\/2023\/07\/SVGicons.jpg?fit=640%2C360&ssl=1"}};
//# sourceURL=elementor-frontend-js-before
/* ]]> */
</script><script  src="https://karelics.fi/wp-content/plugins/elementor/assets/js/frontend.min.js?ver=4.0.7" id="elementor-frontend-js"></script><script type='text/javascript' src='https://karelics.fi/wp-content/boost-cache/static/fc0e9d76e4.min.js'></script><script  src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.23.0/components/prism-core.min.js?ver=1.23.0" id="prismjs_core-js"></script><script  src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.23.0/plugins/autoloader/prism-autoloader.min.js?ver=1.23.0" id="prismjs_loader-js"></script><script  src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.23.0/plugins/normalize-whitespace/prism-normalize-whitespace.min.js?ver=1.23.0" id="prismjs_normalize-js"></script><script  src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.23.0/plugins/line-numbers/prism-line-numbers.min.js?ver=1.23.0" id="prismjs_line_numbers-js"></script><script  src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.23.0/plugins/toolbar/prism-toolbar.min.js?ver=1.23.0" id="prismjs_toolbar-js"></script><script  src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.23.0/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js?ver=1.23.0" id="prismjs_copy_to_clipboard-js"></script><script type="text/javascript" id="jetpack-carousel-js-extra">
/* <![CDATA[ */
var jetpackSwiperLibraryPath = {"url":"https://karelics.fi/wp-content/plugins/jetpack/_inc/blocks/swiper.js"};
var jetpackCarouselStrings = {"widths":[370,700,1000,1200,1400,2000],"is_logged_in":"","lang":"en","ajaxurl":"https://karelics.fi/wp-admin/admin-ajax.php","nonce":"16b609b2d2","display_exif":"0","display_comments":"0","single_image_gallery":"1","single_image_gallery_media_file":"","background_color":"black","comment":"Comment","post_comment":"Post Comment","write_comment":"Write a Comment...","loading_comments":"Loading Comments...","image_label":"Open image in full-screen.","download_original":"View full size \u003Cspan class=\"photo-size\"\u003E{0}\u003Cspan class=\"photo-size-times\"\u003E\u00d7\u003C/span\u003E{1}\u003C/span\u003E","no_comment_text":"Please be sure to submit some text with your comment.","no_comment_email":"Please provide an email address to comment.","no_comment_author":"Please provide your name to comment.","comment_post_error":"Sorry, but there was an error posting your comment. Please try again later.","comment_approved":"Your comment was approved.","comment_unapproved":"Your comment is in moderation.","camera":"Camera","aperture":"Aperture","shutter_speed":"Shutter Speed","focal_length":"Focal Length","copyright":"Copyright","comment_registration":"1","require_name_email":"1","login_url":"https://karelics.fi/wp-login.php?redirect_to=https%3A%2F%2Fkarelics.fi%2Fblog%2F2023%2F07%2F26%2Fsimplifying-icon-integration-a-step-by-step-guide-to-custom-icon-fonts-in-javascript-projects%2F","blog_id":"1","meta_data":["camera","aperture","shutter_speed","focal_length","copyright"]};
//# sourceURL=jetpack-carousel-js-extra
/* ]]> */
</script><script type='text/javascript' src='https://karelics.fi/wp-content/boost-cache/static/1f147930a0.min.js'></script><script data-borlabs-cookie-script-blocker-handle="elementor-recaptcha_v3-api" data-borlabs-cookie-script-blocker-id="elementor-recaptcha" type='text/template' data-borlabs-cookie-script-blocker-src="https://www.google.com/recaptcha/api.js?render=explicit&amp;ver=4.0.4" id="elementor-recaptcha_v3-api-js"></script><script  src='https://karelics.fi/wp-content/plugins/elementor-pro/assets/js/webpack-pro.runtime.min.js?m=1777530536'></script><script  id="elementor-pro-frontend-js-before">
/* <![CDATA[ */
var ElementorProFrontendConfig = {"ajaxurl":"https:\/\/karelics.fi\/wp-admin\/admin-ajax.php","nonce":"e2608e0bc8","urls":{"assets":"https:\/\/karelics.fi\/wp-content\/plugins\/elementor-pro\/assets\/","rest":"https:\/\/karelics.fi\/wp-json\/"},"settings":{"lazy_load_background_images":true},"popup":{"hasPopUps":true},"shareButtonsNetworks":{"facebook":{"title":"Facebook","has_counter":true},"twitter":{"title":"Twitter"},"linkedin":{"title":"LinkedIn","has_counter":true},"pinterest":{"title":"Pinterest","has_counter":true},"reddit":{"title":"Reddit","has_counter":true},"vk":{"title":"VK","has_counter":true},"odnoklassniki":{"title":"OK","has_counter":true},"tumblr":{"title":"Tumblr"},"digg":{"title":"Digg"},"skype":{"title":"Skype"},"stumbleupon":{"title":"StumbleUpon","has_counter":true},"mix":{"title":"Mix"},"telegram":{"title":"Telegram"},"pocket":{"title":"Pocket","has_counter":true},"xing":{"title":"XING","has_counter":true},"whatsapp":{"title":"WhatsApp"},"email":{"title":"Email"},"print":{"title":"Print"},"x-twitter":{"title":"X"},"threads":{"title":"Threads"}},
"facebook_sdk":{"lang":"en_US","app_id":"2427671004073367"},"lottie":{"defaultAnimationUrl":"https:\/\/karelics.fi\/wp-content\/plugins\/elementor-pro\/modules\/lottie\/assets\/animations\/default.json"}};
//# sourceURL=elementor-pro-frontend-js-before
/* ]]> */
</script><script  src="https://karelics.fi/wp-content/plugins/elementor-pro/assets/js/frontend.min.js?ver=4.0.4" id="elementor-pro-frontend-js"></script><script  src="https://karelics.fi/wp-content/plugins/elementor-pro/assets/js/elements-handlers.min.js?ver=4.0.4" id="pro-elements-handlers-js"></script><script type="text/javascript" id="xpro-elementor-widgetarea-editor-js-extra">
/* <![CDATA[ */
var XproWidgetAreaEditorParams = {"rest_api_url":"https://karelics.fi/wp-json/","nonce":"8f2d2a7a2c"};
//# sourceURL=xpro-elementor-widgetarea-editor-js-extra
/* ]]> */
</script><script  src='https://karelics.fi/wp-content/plugins/xpro-elementor-addons/inc/controls/assets/js/widgetarea-editor.js?m=1777616930'></script><script type="module">
/* <![CDATA[ */
/*! This file is auto-generated */
const a=JSON.parse(document.getElementById("wp-emoji-settings").textContent),o=(window._wpemojiSettings=a,"wpEmojiSettingsSupports"),s=["flag","emoji"];function i(e){try{var t={supportTests:e,timestamp:(new Date).valueOf()};sessionStorage.setItem(o,JSON.stringify(t))}catch(e){}}function c(e,t,n){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);t=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data);e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(n,0,0);const a=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data);return t.every((e,t)=>e===a[t])}function p(e,t){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);var n=e.getImageData(16,16,1,1);for(let e=0;e<n.data.length;e++)if(0!==n.data[e])return!1;return!0}function u(e,t,n,a){switch(t){case"flag":return n(e,"\ud83c\udff3\ufe0f\u200d\u26a7\ufe0f","\ud83c\udff3\ufe0f\u200b\u26a7\ufe0f")?!1:!n(e,"\ud83c\udde8\ud83c\uddf6","\ud83c\udde8\u200b\ud83c\uddf6")&&!n(e,"\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f","\ud83c\udff4\u200b\udb40\udc67\u200b\udb40\udc62\u200b\udb40\udc65\u200b\udb40\udc6e\u200b\udb40\udc67\u200b\udb40\udc7f");case"emoji":return!a(e,"\ud83e\u1fac8")}return!1}function f(e,t,n,a){let r;const o=(r="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?new OffscreenCanvas(300,150):document.createElement("canvas")).getContext("2d",{willReadFrequently:!0}),s=(o.textBaseline="top",o.font="600 32px Arial",{});return e.forEach(e=>{s[e]=t(o,e,n,a)}),s}function r(e){var t=document.createElement("script");t.src=e,t.defer=!0,document.head.appendChild(t)}a.supports={everything:!0,everythingExceptFlag:!0},new Promise(t=>{let n=function(){try{var e=JSON.parse(sessionStorage.getItem(o));if("object"==typeof e&&"number"==typeof e.timestamp&&(new Date).valueOf()<e.timestamp+604800&&"object"==typeof e.supportTests)return e.supportTests}catch(e){}return null}();if(!n){if("undefined"!=typeof Worker&&"undefined"!=typeof OffscreenCanvas&&"undefined"!=typeof URL&&URL.createObjectURL&&"undefined"!=typeof Blob)try{var e="postMessage("+f.toString()+"("+[JSON.stringify(s),u.toString(),c.toString(),p.toString()].join(",")+"));",a=new Blob([e],{type:"text/javascript"});const r=new Worker(URL.createObjectURL(a),{name:"wpTestEmojiSupports"});return void(r.onmessage=e=>{i(n=e.data),r.terminate(),t(n)})}catch(e){}i(n=f(s,u,c,p))}t(n)}).then(e=>{for(const n in e)a.supports[n]=e[n],a.supports.everything=a.supports.everything&&a.supports[n],"flag"!==n&&(a.supports.everythingExceptFlag=a.supports.everythingExceptFlag&&a.supports[n]);var t;a.supports.everythingExceptFlag=a.supports.everythingExceptFlag&&!a.supports.flag,a.supports.everything||((t=a.source||{}).concatemoji?r(t.concatemoji):t.wpemoji&&t.twemoji&&(r(t.twemoji),r(t.wpemoji)))});
//# sourceURL=https://karelics.fi/wp-includes/js/wp-emoji-loader.min.js
/* ]]> */
</script><script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-TXVK6QV');</script><script>
(function() {
    if (!document.querySelector('script[data-borlabs-cookie-script-blocker-id="contact-form-seven-recaptcha"]')) {
        return;
    }

    const template = document.querySelector("#brlbs-cmpnt-cb-template-contact-form-seven-recaptcha");
    const formsToInsertBlocker = document.querySelectorAll('form.wpcf7-form');

    for (const form of formsToInsertBlocker) {
        const blocked = template.content.cloneNode(true).querySelector('.brlbs-cmpnt-container');
        form.after(blocked);

        const btn = form.querySelector('.wpcf7-submit')
        if (btn) {
            btn.disabled = true
        }
    }
})();
</script><script>
(function() {
    const template = document.querySelector("#brlbs-cmpnt-cb-template-contact-form-seven-turnstile");
    const divsToInsertBlocker = document.querySelectorAll('body:has(script[data-borlabs-cookie-script-blocker-id="contact-form-seven-turnstile"]) .wpcf7-turnstile');
    for (const div of divsToInsertBlocker) {
        const cb = template.content.cloneNode(true).querySelector('.brlbs-cmpnt-container');
        div.after(cb);

        const form = div.closest('.wpcf7-form');
        const btn = form?.querySelector('.wpcf7-submit');
        if (btn) {
            btn.disabled = true
        }
    }
})()
</script><script>
(function () {
    const allBackgroundContainerVimeo = document.querySelectorAll('[data-brlbs-elementor-bg-video-vimeo="true"]:not(:has(.brlbs-cmpnt-content-blocker))');

    const getVimeoId = url => (url.match(/vimeo\.com\/(?:.*\/)?([0-9]+)/) || [])[1] || null;
    const getThumbnailBackgroundImageUrl = (videoContainer) => {
        const bgImageCss = window.getComputedStyle(videoContainer).backgroundImage;
        if (bgImageCss != null && bgImageCss.startsWith('url(')) {
            return bgImageCss;
        }
        if (true !== true) {
            return null;
        }
        const settings = JSON.parse(videoContainer.dataset.settings)
        if (settings == null || !settings.hasOwnProperty('background_video_link')) {
            return null;
        }
        const vimeoId = getVimeoId(settings.background_video_link);
        if (vimeoId == null) {
            return null;
        }
        return 'url("https://karelics.fi/wp-content/uploads/borlabs-cookie/1/vimeo_' + vimeoId + '.jpg")';
    };

    const template = document.getElementById('brlbs-cmpnt-cb-template-vimeo-content-blocker');
    for (let videoContainer of allBackgroundContainerVimeo) {
        const id = videoContainer.dataset.id
        if (videoContainer && template) {
            const videoEmbed = videoContainer.querySelector('.elementor-background-video-embed');
            const cb = template.content.cloneNode(true).querySelector('.brlbs-cmpnt-container');
            cb.dataset.borlabsCookieContent = 'PHNjcmlwdD4KKGZ1bmN0aW9uKCkgewogICAgaWYgKHR5cGVvZiB3aW5kb3cuYnJsYnNFbGVtZW50b3JCZ1ZpZGVvVmltZW9VbmJsb2NrZWQgPT09ICd1bmRlZmluZWQnKSB7CiAgICAgICAgd2luZG93LmJybGJzRWxlbWVudG9yQmdWaWRlb1ZpbWVvVW5ibG9ja2VkID0gdHJ1ZTsKICAgICAgICBCb3JsYWJzQ29va2llLlRvb2xzLm9uRXhpc3QoJ2JybGJzRWxlbWVudG9yQmdWaWRlb1ZpbWVvVW5ibG9ja1JlYWR5JywgKCkgPT4gewogICAgICAgICAgICBkb2N1bWVudC5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudCgnYnJsYnNfZWxlbWVudG9yX2JnVmlkZW9fdmltZW9fdW5ibG9ja2VkJykpOwogICAgICAgIH0pOwogICAgfQp9KSgpCjwvc2NyaXB0Pg==';
            if (videoEmbed.nextSibling) {
                videoEmbed.parentNode.insertBefore(cb, videoEmbed.nextSibling);
            } else {
                videoEmbed.parentNode.appendChild(cb);
            }

            const bgImageCss = getThumbnailBackgroundImageUrl(videoContainer);
            const thumb = cb.querySelector('.brlbs-cmpnt-cb-thumbnail')
            if (bgImageCss != null && thumb != null) {
                thumb.style.backgroundImage = bgImageCss;
            }
        }
    }
})();
</script><script>
(function () {
    const allBackgroundContainerYt = document.querySelectorAll('[data-brlbs-elementor-bg-video-yt="true"]:not(:has(.brlbs-cmpnt-content-blocker))');

    const getYouTubeId = url => (url.match(new RegExp("(?:youtube\.com\/(?:[^\/\n\s]+\/\S+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([a-zA-Z0-9_-]{11})")) || [])[1] || null;
    const getThumbnailBackgroundImageUrl = (videoContainer) => {
        const bgImageCss = window.getComputedStyle(videoContainer).backgroundImage;
        if (bgImageCss != null && bgImageCss.startsWith('url(')) {
            return bgImageCss;
        }
        const thumbnailQuality = 'hqdefault';
        if (thumbnailQuality === 'none' || videoContainer.dataset.settings == null) {
            return null;
        }
        const settings = JSON.parse(videoContainer.dataset.settings)
        if (settings == null || !settings.hasOwnProperty('background_video_link')) {
            return null;
        }
        const ytId = getYouTubeId(settings.background_video_link);
        if (ytId == null) {
            return null;
        }
        return 'url("https://karelics.fi/wp-content/uploads/borlabs-cookie/1/yt_' + ytId + '_' + thumbnailQuality + '.jpg")';
    };

    const template = document.getElementById('brlbs-cmpnt-cb-template-youtube-content-blocker');
    for (let videoContainer of allBackgroundContainerYt) {
        const id = videoContainer.dataset.id
        if (videoContainer && template) {
            const videoEmbed = videoContainer.querySelector('.elementor-background-video-embed');
            const cb = template.content.cloneNode(true).querySelector('.brlbs-cmpnt-container');
            cb.dataset.borlabsCookieContent = 'PHNjcmlwdD4KKGZ1bmN0aW9uKCkgewogICAgaWYgKHR5cGVvZiB3aW5kb3cuYnJsYnNFbGVtZW50b3JCZ1ZpZGVvWXRVbmJsb2NrZWQgPT09ICd1bmRlZmluZWQnKSB7CiAgICAgICAgd2luZG93LmJybGJzRWxlbWVudG9yQmdWaWRlb1l0VW5ibG9ja2VkID0gdHJ1ZTsKICAgICAgICBCb3JsYWJzQ29va2llLlRvb2xzLm9uRXhpc3QoJ2JybGJzRWxlbWVudG9yQmdWaWRlb1l0VW5ibG9ja1JlYWR5JywgKCkgPT4gewogICAgICAgICAgICBkb2N1bWVudC5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudCgnYnJsYnNfZWxlbWVudG9yX2JnVmlkZW9feXRfdW5ibG9ja2VkJykpOwogICAgICAgIH0pOwogICAgfQp9KSgpCjwvc2NyaXB0Pg==';
            if (videoEmbed.nextSibling) {
                videoEmbed.parentNode.insertBefore(cb, videoEmbed.nextSibling);
            } else {
                videoEmbed.parentNode.appendChild(cb);
            }

            const bgImageCss = getThumbnailBackgroundImageUrl(videoContainer);
            const thumb = cb.querySelector('.brlbs-cmpnt-cb-thumbnail')
            if (bgImageCss != null && thumb != null) {
                thumb.style.backgroundImage = bgImageCss;
            }
        }
    }
})();
</script><script>
(function() {
    const template = document.querySelector("#brlbs-cmpnt-cb-template-elementor-recaptcha");
    const divsToInsertBlocker = document.querySelectorAll('.elementor-field-type-recaptcha_v3 .elementor-field,.elementor-field-type-recaptcha .elementor-field');
    for (const div of divsToInsertBlocker) {
        const cb = template.content.cloneNode(true).querySelector('.brlbs-cmpnt-container');
        div.appendChild(cb);

        const elementorForm = div.closest('form.elementor-form');
        if (elementorForm != null) {
            elementorForm.querySelectorAll('.elementor-field-type-submit button').forEach(btn => btn.disabled = true);
        }
    }
})()
</script><script>
(function() {
    const template = document.querySelector("#brlbs-cmpnt-cb-template-hubspot-form");
    const divsToInsertBlocker = document.querySelectorAll('body:has(script[data-borlabs-cookie-script-blocker-id="hubspot-regular-form"]) :is(.hs-form-frame,.hs-form-html)[data-form-id]');
    for (const div of divsToInsertBlocker) {
        const cb = template.content.cloneNode(true).querySelector('.brlbs-cmpnt-container');
        div.appendChild(cb);
    }
})()
</script><script>
(function() {
    const template = document.querySelector("#brlbs-cmpnt-cb-template-hubspot-meetings");
    const divsToInsertBlocker = document.querySelectorAll('body:has(script[data-borlabs-cookie-script-blocker-id="hubspot-meetings"]) .meetings-iframe-container[data-src*=".hubspot.com/"]');
    for (const div of divsToInsertBlocker) {
        const cb = template.content.cloneNode(true).querySelector('.brlbs-cmpnt-container');
        div.appendChild(cb);
    }
})()
</script></body>
				
			

Usage in Angular

We use the MatIcon module to embed icons into our application. By default, expects the Material icons font. Example:

				
					<mat-icon fontIcon="layers"></mat-icon>
				
			

To use our icons, we register the kc alias through the MatIconRegistry service during application initialization:

				
					@Injectable({
  providedIn: 'root',
})
export class KcIconsService {
  private readonly matIconRegistry = inject(MatIconRegistry);

  initializeKcIcons(): Promise<void> {
    return new Promise((res) => {
      this.matIconRegistry.registerFontClassAlias('kc', 'kc-icon');
      res();
    });
  }
}</void>
				
			

Usage in a template (you just need to add the fontSet attribute with the registered alias):

				
					<mat-icon fontSet="kc" fontIcon="kc-device"></mat-icon>
				
			

Conclusion

In conclusion, this article has provided a comprehensive guide to creating a custom icon font for JavaScript projects. Whether you are developing a robotic fleet management system or any other project, incorporating custom icons can greatly enhance the user interface and overall user experience. By following the outlined steps, you can create a unique icon font that adds a personal touch and improves visual appeal.

Facebook
Twitter
LinkedIn
Picture of Nikita Zhidov
Nikita Zhidov

I'm a frontend developer, passionate about creating user-friendly interfaces for the web. Joining Karelics in 2022, I'm excited to contribute to the "Karelics cloud" project. My expertise lies in Angular, and I take pride in creating visually appealing and dynamic web applications. It's an honor to be part of a team that's at the forefront of building the future with robots. Together, we're making remarkable strides in the world of technology.

All Posts

Simplifying icon integration: A Step-by-Step guide to custom icon fonts in JavaScript projects

request

Pipe Inspection request

Photo Documentation
request