我有一个带有 Shadow DOM 的 HTML 5 WebComponent,它显示的内容必须根据组件中显示的内容类型加载样式。样式表列表是从服务器获取的。
我可以像这样加载样式表:
for (const style of styles) {
const stylesheet = document.createElement('link');
stylesheet.setAttribute('rel', 'stylesheet');
stylesheet.setAttribute('href', style);
stylesheet.setAttribute('type', 'text/css');
this.root.appendChild(stylesheet);
}
然而,样式表有时还包括@font-face
规则,这些规则不会添加到组件中。浏览器永远不会创建对字体引用的请求@font-face
规则。如何动态加载这些规则?
原来浏览器不支持loading@font-face
自 2020 年 9 月起,CSS 在影子 DOM 中占据主导地位。不过,Chrome 团队似乎正在努力解决这个问题。
我采取的方法是寻找@font-face
动态创建的样式表中的规则,稍微修改它们以使相对路径正常工作,然后将它们添加到<head>
带有脚本的页面。如果您添加@font-face
规则到头andShadow DOM,字体将被加载和应用。
这是代码:
for (const style of styles) { // styles is an array of urls
const stylesheet = document.createElement('link');
stylesheet.setAttribute('rel', 'stylesheet');
stylesheet.setAttribute('href', style);
stylesheet.setAttribute('type', 'text/css');
stylesheet.onload = (event) => {
for (
let i = 0;
i < event.currentTarget.sheet.cssRules.length;
i++
) {
if (event.currentTarget.sheet.cssRules[i].type == 5) { // type 5 is @font-face
const split = style.split('/');
const stylePath = split
.slice(0, split.length - 1)
.join('/');
let cssText =
event.currentTarget.sheet.cssRules[i].cssText;
cssText = cssText.replace(
// relative paths
/url\s*\(\s*[\'"]?(?!((\/)|((?:https?:)?\/\/)|(?:data\:?:)))([^\'"\)]+)[\'"]?\s*\)/g,
`url("${stylePath}/$4")`
);
const st = document.createElement('style');
st.appendChild(document.createTextNode(cssText));
document
.getElementsByTagName('head')[0]
.appendChild(st);
}
}
};
this.root.appendChild(stylesheet);
}
它在 Edge 85(基于 Chromium)上运行良好。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)