自定义字体是个好东西啊,FontAwesome/Remixicon等优秀的图标都是用自定义字体来实现的,非常省事好用。如此让人上瘾的东西,可惜碰到了web components之后麻烦就来了。

首先,web components是自隔离的,父页面中的样式是不能作用于组件的,所以按照常规方法是把样式嵌入到组件中。非常遗憾的是,css加载是没问题的,但是它并没有于我们预期想象的一样把图标显示出来。

这个看起来就像是字体缺失,打开网路请求检查一下,的确就是没有字体请求!但是,令人意外的是,如果在父页面中引入自定义字体,在组件内部使用自定义字体,居然是行得通的!

所以这个丑陋的方案就出来了,把他们拆成两个部分:

  1. 字体定义部分放在父页面中,通过父页面来请求自定义字体;
  2. 样式部分放在web components中,因为样式是隔离的。

当然,我们可以通过js来在父页面中注入自定义字体:

const FONT_FACES = `@font-face {
  font-family: "remixicon";
  src: url('remixicon.eot?t=1590207869815'); /* IE9*/
  src: url('remixicon.eot?t=1590207869815#iefix') format('embedded-opentype'), /* IE6-IE8 */
  url("remixicon.woff2?t=1590207869815") format("woff2"),
  url("remixicon.woff?t=1590207869815") format("woff"),
  url('remixicon.ttf?t=1590207869815') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
  url('remixicon.svg?t=1590207869815#remixicon') format('svg'); /* iOS 4.1- */
  font-display: swap;
}`;

function setupFontFaces() {
  const description = 'web-components-font-faces'
  if (document.querySelector(`style[data-description="${description}"]`)) {
    return;
  }
  const style = document.createElement('style');
  style.dataset.description = description;

  style.appendChild(document.createTextNode(FONT_FACES));
  document.head.appendChild(style);
}

不论如何,这个方案还是有点丑陋。

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.