Reputation: 3792
I have this component:
index.html
<html>
<head>
<title></title>
<meta charset="UTF-8">
<script src="clock.js"></script>
<style>
clock-digital div {
background-color: green;
}
</style>
</head>
<body>
<clock-digital></clock-digital>
</body>
</html>
clock.js
customElements.define('clock-digital', class extends HTMLElement {
constructor() {
super();
var shadowRoot = this.attachShadow({
mode: 'open'
});
this._clockID = setInterval(function () {
var currentdate = new Date();
var hours = ( (currentdate.getHours() < 10) ? '0' : '') + currentdate.getHours();
var minutes = ( (currentdate.getMinutes() < 10) ? '0' : '') + currentdate.getMinutes();
var seconds = ( (currentdate.getSeconds() < 10) ? '0' : '') + currentdate.getSeconds();
shadowRoot.innerHTML = `
<style>
div {
display: inline-block;
width: 65px;
text-align: center;
background-color: whitesmoke;
font-style: italic;
border: 1px solid lightgray;
border-radius: 3px;
box-shadow: 2px 2px 3px;
}
</style>
<div>
${hours}:${minutes}:${seconds}
</div>`;
}, 500);
}
});
I want that user of component can define his style on clock. I tried with:
<style>
clock-digital div {
background-color: green;
}
</style>
but it doesn't work. Should I use the slot tag somewhere in shadow root? What is best practice to achieve that?
Upvotes: 1
Views: 507
Reputation: 31171
You can also take profit of the priority of the user defined CSS rules over the :host selector that represents the Shadow DOM root (i.e. the custom element itself).
In your custom element, use :host
to style the content:
shadowRoot.innerHTML = `
<style>
:host {
display: inline-block;
width: 65px;
text-align: center;
background-color: whitesmoke;
font-style: italic;
border: 1px solid lightgray;
border-radius: 3px;
box-shadow: 2px 2px 3px;
}
</style>
<div>
${hours}:${minutes}:${seconds}
</div>`
Now the user can define its own styles with standard CSS notation, like for any HTML elements. This will override the styles defined by the :host
rule.
<style>
clock-digital {
background-color: green;
color: white;
}
</style>
customElements.define('clock-digital', class extends HTMLElement {
constructor() {
super();
var shadowRoot = this.attachShadow({ mode: 'open' });
this._clockID = setInterval(function () {
var currentdate = new Date();
var hours = ('0'+currentdate.getHours()).substr(-2,2)
var minutes = ('0'+currentdate.getMinutes()).substr(-2,2)
var seconds = ('0'+currentdate.getSeconds()).substr(-2,2)
shadowRoot.innerHTML = `
<style>
:host {
display: inline-block;
width: 65px;
text-align: center;
background-color: whitesmoke;
font-style: italic;
border: 1px solid lightgray;
border-radius: 3px;
box-shadow: 2px 2px 3px;
}
</style>
${hours}:${minutes}:${seconds}`;
}, 500);
}
});
clock-digital {
background-color: green;
color: white;
font-weight: bold;
}
<clock-digital></clock-digital>
Upvotes: 2
Reputation: 138276
You could expose CSS properties in your custom element that could be set externally.
In your example, your element could define --clock-background-color
, which sets the div
's background color:
shadowRoot.innerHTML =
`<style>
div {
background-color: var(--clock-background-color, whitesmoke);
/* ... */
}
</style>
<div>
${hours}:${minutes}:${seconds}
</div>`;
Then, your element's users could change the background color to green with this:
<style>
clock-digital {
--clock-background-color: green;
}
</style>
<clock-digital></clock-digital>
Note the Codepen demo uses Web Components polyfills for non-Chrome browsers, but you can comment it out to see that it still works vanilla in Chrome.
Upvotes: 2