polymershadow-domcustom-elementtypekit

Using web fonts with Polymer custom elements


I was having issues with loading Typekit fonts into a Polymer component.

What I had initially in my-element.js:

import {html, PolymerElement} from "../node_modules/@polymer/polymer/polymer-element.js";

export class MyElement extends PolymerElement {
  static get template() {
    return html`
      <style>
        @import url(https://use.typekit.net/mykit.css)
        .my-class { font-family: "typekit-font-family"; }
      </style>

      <div class$="my-class">
        <slot/>
      </div>
    `;
  }
}

window.customElements.define("my-element", MyElement);

I learned that @import url() is not a good approach, so I replaced this with how polymerelements/paper-styles imports Roboto:

typekit-loader.js:

// Based on https://github.com/PolymerElements/font-roboto/blob/master/roboto.js
// and https://github.com/PolymerElements/paper-styles

export {}; // ensure this file can only be parsed as a module.

// Give the user the choice to opt out of font loading.
if (!window.polymerSkipLoadingFontRoboto) {
  const link = document.createElement("link");
  link.rel = "stylesheet";
  link.type = "text/css";
  link.crossOrigin = "anonymous";
  link.href = "https://use.typekit.net/mykit.css";
  document.head.appendChild(link);
}

my-element.js:

import {html, PolymerElement} from "../node_modules/@polymer/polymer/polymer-element.js";
import "./typekit-loader.js";


export class MyElement extends PolymerElement {
  static get template() {
    return html`
      <style>
        .my-class { font-family: "typekit-font-family"; }
      </style>

      <div class$="my-class">
        <slot/>
      </div>
    `;
  }
}

window.customElements.define("my-element", MyElement);

What typekit-loader.js essentially ends up doing is adding a <link rel="stylesheet" /> tag to the <head> of the document that links to and makes use of my-element.js. This seems to work, as I can see my typekit fonts being used.

But my question is why does it work? Shadow DOM isn't supposed to have access to the host page's own styles, so how is my div getting the custom font? How is linking to a web font different from linking to any random css file in the <head> of the document? If I added a style rule to the host document saying that .my-class should be red, it doesn't apply.


Solution

  • Shadow DOM will isolate user-defined CSS styles only.

    Default CSS styles - CSS styles applied to every new document - will style be applied. For example: background, text color, padding...

    The default CSS background-color is inherit. So if you define it globally as blue then it will be displayed blue even inside a Shadow DOM.

    That's quite the same with fonts: the font defined or loaded globally is inherited in the Shadow DOM and can be displayed in it.