自定义字体是个好东西啊,FontAwesome/Remixicon等优秀的图标都是用自定义字体来实现的,非常省事好用。如此让人上瘾的东西,可惜碰到了web components之后麻烦就来了。
首先,web components是自隔离的,父页面中的样式是不能作用于组件的,所以按照常规方法是把样式嵌入到组件中。非常遗憾的是,css加载是没问题的,但是它并没有于我们预期想象的一样把图标显示出来。
这个看起来就像是字体缺失,打开网路请求检查一下,的确就是没有字体请求!但是,令人意外的是,如果在父页面中引入自定义字体,在组件内部使用自定义字体,居然是行得通的!
所以这个丑陋的方案就出来了,把他们拆成两个部分:
- 字体定义部分放在父页面中,通过父页面来请求自定义字体;
- 样式部分放在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);
}
不论如何,这个方案还是有点丑陋。