Javascript 与自定义HTML元素共享样式?
我开始使用自定义元素,但有一件事我搞不清楚,那就是共享样式。例如,如果我有两个自定义元素,Javascript 与自定义HTML元素共享样式?,javascript,html,css,custom-element,Javascript,Html,Css,Custom Element,我开始使用自定义元素,但有一件事我搞不清楚,那就是共享样式。例如,如果我有两个自定义元素,和,它们都包含,并且我希望所有按钮都具有特定的样式,例如字体大小:20px 我考虑过的选项有: 使用自定义元素,而不是自定义元素中的。当外部采购时,这是有问题的。如果只在按钮上而不在按钮上使用其他样式(例如颜色:红色),也会出现问题 根据polymer的文档[1],polymer也没有解决方案 /dead/和:shadow似乎很有希望,但不再受支持 同样地,@apply[2]似乎很有希望,但提案被撤回 ::
和
,它们都包含
,并且我希望所有按钮都具有特定的样式,例如字体大小:20px
我考虑过的选项有:
自定义元素,而不是自定义元素中的
。当外部采购
时,这是有问题的。如果只在
按钮上而不在
按钮上使用其他样式(例如颜色:红色),也会出现问题
/dead/
和:shadow
似乎很有希望,但不再受支持@apply
[2]似乎很有希望,但提案被撤回::part
和:theme
[3]似乎更有希望,但尚未得到支持::part
和::theme
[4]。我想如果不把所有的箱子都熨平,这件衣服会很脆class Element1 extends HTMLElement {
constructor() {
this.shadowRoot.addElement(sharedStyle);
}
}
这似乎非常受限&手动。还会影响性能吗?如果您从外部采购
,也会出现问题document.addEventListener('DOMContentLoaded', () => {
// create style sheets for each shadow root to which we will later add rules
let shadowRootsStyleSheets = [...document.querySelectorAll('*')]
.filter(element => element.shadowRoot)
.map(element => element.shadowRoot)
.map(shadowRoot => {
shadowRoot.appendChild(document.createElement('style'));
return shadowRoot.styleSheets[0];
});
// iterate all style rules in the document searching for `.theme` and `.part` in the selectors.
[...document.styleSheets]
.flatMap(styleSheet => [...styleSheet.rules])
.forEach(rule => {
let styleText = rule.cssText.match(/\{(.*)\}/)[1];
let match;
if (match = rule.selectorText.match(/\.theme\b(.*)/))
shadowRootsStyleSheets.forEach(styleSheet => styleSheet.addRule(match[1], styleText));
else if (match = rule.selectorText.match(/\.part\b(.*)/))
shadowRootsStyleSheets.forEach(styleSheet => styleSheet.addRule(`[part=${match[1]}]`, styleText));
});
});
以及用法:
<style>
.my-element.part line-green {
border: 1px solid green;
color: green;
}
.theme .line-orange {
border: 1px solid orange;
color: orange;
}
/*
must use `.part` instead of `::part`, and `.theme` instead of `::theme`
as the browser prunes out invalid css rules form the `StyleSheetList`'s.
*/
</style>
<template id="my-template">
<p part="line-green">green</p>
<p class="line-orange">orange</p>
</template>
<my-element></my-element>
<script>
customElements.define('my-element', class extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'});
const template = document.getElementById('my-template').content.cloneNode(true);
this.shadowRoot.appendChild(template);
}
});
</script>
.my-element.part行绿色{
边框:1px纯绿色;
颜色:绿色;
}
.主题.橙色线条{
边框:1px实心橙色;
颜色:橙色;
}
/*
必须使用“.part”而不是“::part”,必须使用“.theme”而不是“::theme”`
当浏览器从“样式表列表”中删除无效的css规则时。
*/
绿色
橙色
定义('my-element',类扩展HtmleElement{
构造函数(){
超级();
this.attachShadow({mode:'open'});
const template=document.getElementById('my-template').content.cloneNode(true);
this.shadowRoot.appendChild(模板);
}
});
您可以使用@import url
将外部样式表导入到不同的自定义元素中
或者,现在您也可以在自定义元素阴影DOM中使用
:
<template id="element-1">
<style>
@import url( 'button-style.css' )
</style>
<button>B-1</button>
</template>
<template id="element-2">
<link rel="stylesheet" href="button-style.css">
<button>B-2</button>
</template>
@导入url('button style.css')
B-1
B-2
如果您使用的是css,您可以这样做:
button {
/* Put Style Here */
}
您还必须在html的头部添加一个链接:
<link rel=“stylesheet” href=“the address”>
只是想知道:跨浏览器功能对你来说有多重要?好的一点,我忘了提到,就我的使用案例而言,我只关心最新版本的chrome。另请参阅本文:这似乎相当于#7,并且有同样的缺点;e、 g.如果元素2是由依赖项定义的,我将无法使用此方法设置其按钮的样式。但我实际上是在一个项目上尝试这个方法(所有元素都是我的),而且效果很好。我不明白你说的depency,一个第三方自定义元素是什么意思?是的,这是一个限制,但它正是shadow dom功能的目的和预期行为。是的,这就是我所说的依赖性,尽管它可能不是第三方,而是您自己的通用元素包,您希望通过不同的样式重复使用。我不同意这是“目的和预期行为”,这更多的是在执行上的滞后。过去肯定有人尝试用shadow元素来支持这一点(例如/deep/,:shadow和@apply),将来肯定有计划支持(例如::part和::theme),chrome至少正在积极地开发这一功能。不同的尝试由于多种原因(缓慢、无法实现、危险……)而失败. ::part and::theme不会与第三方库一起使用,而且不会很快推出(仍然没有alpha版本)。自定义属性(或自定义实现)是唯一的备选方案(与答案中的限制相同或更多)。这就是为什么说CSS隔离是ShadowDOM的目的是现实的。如果您想要全局样式,我建议您设计没有阴影DOM的自定义元素。有趣的建议是,我在网上发现很少有资源使用没有阴影dom的自定义元素,所以我认为这是一种不好的做法。我将尝试一下我的用例,看看是否有任何问题出现。全局样式不会应用于阴影DOM中