Lead Software Engineer & 3× Umbraco MVP

The quickest way to add a custom font to the new Umbraco backoffice

When dealing with fonts and the Shadow DOM, font files have to be loaded at the outermost possible layer so that they can cascade (thanks to the C in CSS) down to Web Components.

If you are using BlockPreview in Umbraco 14+, you will likely find that any custom fonts you have loaded against your previews—whether loaded in your Block datatype or with BlockPreview—that custom fonts don't render at all.

BlockPreview in use on my own Umbraco Cloud site, with only system fonts in use.

BlockPreview in use on my own Umbraco Cloud site, with only system fonts in use.

The preview should be using IBM Plex Sans, the same font as the front end of my site, and the CSS does declare this, scoped to :host.

:host {
--font-stack: "IBM Plex Sans", -apple-system, 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'Helvetica Neue', 'Arial', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
font-family: var(--font-stack);
}

With that in mind, we need to hook into an event or extension point that loads as soon as possible.

Firstly, let's set up an umbraco-package.json

App_Plugins/BackofficeFontLoader/umbraco-package.json
{
"name": "BackofficeFontLoader",
"alias": "BackofficeFontLoader.Package",
"extensions": [
{
"type": "backofficeEntryPoint",
"alias": "BackofficeFontLoader.EntryPoint",
"js": "/App_Plugins/BackofficeFontLoader/index.js"
}
]
}

By using backofficeEntryPoint, we are hooking in to one of the first times we can actually do something with the Umbraco backoffice. As per the Umbraco docs (emphasis mine):

This manifest declares a single JavaScript file that will be loaded and run when the Backoffice starts. In other words, this can be used as an entry point for a package.

The backofficeEntryPoint extension is also the way to go if you want to load in external libraries such as jQuery, Angular, React, etc. You can use the backofficeEntryPoint to load in the external libraries to be shared by all your extensions. Additionally, global CSS files can also be used in the backofficeEntryPoint extension.

Let's create the index.js this is referencing. This needs to very simply just load in an external CSS file, create a style element and inject it into the page.

App_Plugins/BackofficeFontLoader/index.js
/**
* Perform any initialization logic when the Backoffice starts
*/
export const onInit = () => {
let styleElement = document.createElement('link');
styleElement.rel = 'stylesheet';
styleElement.href = "https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:ital,wght@0,100..700;1,100..700&display=swap";
document.head.appendChild(styleElement);
}

Now we have a reference to the font, let's restart the backoffice and see what we have...

Umbraco backoffice showing the custom font being rendered

Umbraco backoffice showing the custom font being rendered

Hey presto! Houston, we have webfonts. 🚀

So far this is the best way I've found, and one that is supported by the Umbraco Docs, to get these global styles in for custom block views.

Give it a try!