与自定义HTML元素共享样式吗? [英] Shared styling with custom HTML elements?
问题描述
我开始使用自定义元素,而我不知道的一件事就是共享样式.例如,如果我有2个自定义元素,分别是< element-1>
和< element-2>
,它们都包含< button>
's,我希望所有按钮都具有某种样式,例如 font-size:20px
.
I'm beginning to use custom elements, and one thing I can't figure out is sharing styling. For example, if I have 2 custom elements, <element-1>
and <element-2>
, both of which contain <button>
's, and i want all buttons to have a certain styling, e.g. font-size:20px
.
我考虑的选项是:
-
在自定义元素中使用
< stylized-button>
自定义元素,而不是< button>
.当从外部采购< element-1>
时,这是有问题的.如果您还希望仅在< element-1>
按钮而不是< element-2>
按钮.
Use a
<stylized-button>
custom element instead of<button>
in the custom elements. This is problematic when externally sourcing<element-1>
. Also problematic if you want other styling as well (e.g.color:red
) on only<element-1>
buttons and not<element-2>
buttons.
据我从Polymer的文档[1]得知,聚合物也没有解决方案.
As far as I could tell from polymer's docs [1], polymer doesn't have a solution for this either.
/dead/
和:shadow
似乎很有希望,但不再受支持.
/dead/
and :shadow
seemed promising but are no longer supported.
类似地 @apply
[2]看起来很有希望,但是该提案被撤回了.
Similarly @apply
[2] seemed promising, but the proposal was withdrawn.
:: part
和 :: theme
[3]似乎更有希望,但尚不支持.
::part
and ::theme
[3] seem even more promising, but aren't yet supported.
使用js支持 :: part
和 :: theme
[4].我想如果不解决所有问题,这将非常脆弱.
Use js to support ::part
and ::theme
[4]. i imagine this would be very brittle without ironing out all cases.
将共享样式明确添加到每个自定义元素.
Explicitly add the shared styling to each custom element.
class Element1 extends HTMLElement {
constructor() {
this.shadowRoot.addElement(sharedStyle);
}
}
这似乎很受限制&手动的.还可能会影响性能吗?如果您从外部采购< element-1>
.
This seems very restricted & manual. Also might affect performance? Also problematic if you externally sourcing <element-1>
.
现在,我认为#5可能是最好的,因为它似乎是最通用/最容易使用的,而无需专门为其构建,另外,在实现时,向#4的过渡也将变得微不足道.但是我想知道是否还有其他方法或建议?
Right now, I'm thinking #5 might be the best as it seems the most generic / easiest to use without building specifically for it, plus it would make transitioning to #4 trivial when it's implemented. But I'm wondering if there are other approaches or suggestions?
[1] https://www.polymer-project.org/3.0/docs/devguide/style-shadow-dom
[2] http://tabatkins.github.io/specs/css-apply-rule/
[3] https://meowni.ca/posts/part-theme-explainer/
[4]天真的实现和使用它的示例: https://gist.github.com/mahhov/cbb27fcdde4ad45715d2df3b3ce7be40
[4] A naive implementation and an example using it: https://gist.github.com/mahhov/cbb27fcdde4ad45715d2df3b3ce7be40
实现:
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>
推荐答案
您可以使用 @import url
将外部样式表导入到不同的自定义元素中.
You can use @import url
to import an external stylesheet into different custom elements.
或者,现在您也可以在自定义元素Shadow DOM中使用< link rel ="stylesheet">
Alternately now you can also use <link rel="stylesheet">
inside a custom element Shadow 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>
这篇关于与自定义HTML元素共享样式吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!