Can a font be imported from within the shadow dom and have it apply to its children?
When trying to do something like
class MyCustomElement extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.innerHTML = `
<style>
@import url('https://fonts.googleapis.com/css?family=Open+Sans');
:host {
font-family: 'Open Sans';
}
</style>
<h1>Hello font?</h1>
`;
}
}
customElements.define('my-custom-element', MyCustomElement);
The font isn’t being applied to the <h1>
. The CSS inspector shows <h1>
‘s font computed as "Open Sans"
. In the network tab, Chrome requests the stylesheet, but Firefox does not. In both browsers it renders with a system default font.
What’s missing to make this work?
The full HTML file is,
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Font test</title>
</head>
<body>
<script>
class MyCustomElement extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: "open" });
shadowRoot.innerHTML = `
<style>
@import url('https://fonts.googleapis.com/css?family=Open+Sans');
:host {
font-family: 'Open Sans';
}
</style>
<h1>Hello font?</h1>
`;
}
}
customElements.define("my-custom-element", MyCustomElement);
</script>
<my-custom-element></my-custom-element>
</body>
</html>
Firefox
Chrome
3
Answers
When you use ‘@import’ within a Shadow DOM, it doesn’t always work as expected due to the timing of when the styles are applied.
In your case, the ‘@import’ rule might not be applied in time for the font-family declaration .
You have to register an external Font both in the Global Scope and in the Web Component
As a workaround you may also add a new font via CSS font loading API method
FontFace()
like so.Keep in mind, this method actually adds the font to the global scope – see 2nd heading in example also using "Open Sans".
This approach also requires to extract the actual font file URL from the google fonts API query.
However, we can quite reliably check if/when the font is loaded – which is handy for many rendering tasks e.g drawing text with a custom font to canvas.