Custom fonts can be used for much more than just styling text. Let’s take, for example, one of the most popular fonts for including custom icons.
Font Awesome is … well… awesome. It opens a whole new world for developers where they can build a decent-looking web application without being aesthetically gifted. Just include the CSS and you can start using a selection of over 7000 icons. Font Awesome is a selection of external stylesheets and fonts, which normally have to be included in the header of a web application. And if we use web components, we start getting problems.
Web components are self-isolated components with their own DOM tree, called shadow DOM. If you are interested in Web Components I included a link about this relatively new technology in the references below.
They also have their own style, that is completely unaffected from the parent page. This means that any styles included in the head will not be available inside a web component. Yes, even Font Awesome. I guess it is not that awesome after all.
Let us assume you have this DOM structure:
As you can see Font Awesome is included over a CDN link inside the head tag of the parent page. If you add an icon on the page, it does show up and everything is as it is supposed to be.
However, we also included a web component. Inside this component, we try to use Font Awesome. It does not work and the icon never shows up:
This can be a problem if you want to build a component, that wants to use icons like an aesthetically more pleasing button.
While styles embedded in the parent document can not affect the inner body of a web component, fonts are an entirely different story. If you want to use them you have to embed them in the root document.
It gets even more complicated. They can not be embedded directly in the web component. The browser will not load any fonts that are included directly in your web component. This weird behavior can cause some headaches if you don’t know what to look for. So, how do we solve this problem? Basically, there are two solutions you:
1. Do not use Shadow DOM
2. Embed your custom font in the root document and embed the required styles in your web component.
Let us have a closer look at both possible solutions.
Solution 1: Get Rid of the Shadow DOM
Styles embedded in the root of a document do not apply inside Shadow DOM. We already know that. But web components do not need to use it to work.
Although shadow DOM is recommended, you do not need it to work with web components. If you disable shadow DOM, the parent assets will be available and you will be able to use Font Awesome as you did up until now.
This can be a good solution and if you do not intend to build a web component, that can be repackaged and used by others probably the one you should use. In this case, everyone who uses your custom font will need to explicitly include font-awesome on their page. So this is not a good solution for repackageable web components.
There is one big drawback though. If you do not use shadow DOM, you will not be able to use slots. Slots are another nifty little feature that was introduced together with shadow DOM. They enable you to populate your web component with custom data. If you want to learn more about slots I included a link in the references below.
Let’s try this on a simple example. We made a web component, that does not use shadow dom:
the HTML gets injected directly into the DOM of the website. This way it obeys the same rules and the parent’s style sheet also applies to the web component. Neat huh?
However, what’s the point of using a web component if we will not isolate it through the use of shadow DOM. Now how could we use it and still use shadow DOM?
Solution 2: Include Your Font Globally and Your Style Locally
Web components are, through the use of shadow DOM, completely isolated entities. So parent styles will not be available inside a web component, but what if we include fonts directly inside the web component?
It turns out, this is (partially) possible. You can include your fonts globally. But for them to work inside a web component you will have to include the styles locally.
Let’s take again Font Awesome for example. The simplest solution for it to work inside your web component is to just include it twice, once in the head of your document and once in your web component. This example shows how it can be done:
At first glance, this looks like a pretty good solution. It is not as optimal as one would think though. We have a duplicated include statement and although modern browsers are equipped to deal with such things, it still looks kind of ugly.
We can also quickly see that the portability of the web component is gone. This is not the Plug&Play solution we were hoping for. Both problems can be solved, however. Let us tackle one at a time.
The first problem we face is the duplicated include statement. Font Awesome, like every other icon library, consists of two parts. The fonts and the styling.
What we want to do is separate those to and only include the fonts in the root document. The rest will be included in our web component. We would have two files, looking like this:
Keep in mind you have to set the right paths to the font files.
The second file would be everything else. So we are basically splitting Font Awesome into two parts and include each part where it is needed:
I included here the CSS directly inside style elements but you can just as easily create two files and include them with the <link> tag.
Now that we have solved both problems we can see that this could be the right way to combine custom fonts with your web components.
External resources and web components can be an issue if you do not know how to best use both hand-in-hand. I hope with this short article I could shed a little light on that issue.
Some Other Resources
Here you can find a more detailed explanation about a few themes that were mentioned in this article, but weren’t explained in detail:
A tale about web components: