问题
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
.
The options I've considered are:
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.As far as I could tell from polymer's docs [1], polymer doesn't have a solution for this either.
/dead/
and:shadow
seemed promising but are no longer supported.Similarly
@apply
[2] seemed promising, but the proposal was withdrawn.::part
and::theme
[3] seem even more promising, but aren't yet supported.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); } }
This seems very restricted & manual. Also might affect performance? Also problematic if you externally sourcing
<element-1>
.
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] A naive implementation and an example using it: https://gist.github.com/mahhov/cbb27fcdde4ad45715d2df3b3ce7be40
implementation:
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));
});
});
and the usage:
<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>
回答1:
You can use @import url
to import an external stylesheet into different custom elements.
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>
回答2:
If you are using css, you can just do this:
button {
/* Put Style Here */
}
You also have to add a link in the head on html:
<link rel=“stylesheet” href=“the address”>
来源:https://stackoverflow.com/questions/53089691/shared-styling-with-custom-html-elements