I can't manage to change a css variable (--color
) because the shadowRoot querySelector won't return :host
or html
<style>
:host {display: block;
--color: ${this.color};
}
.colored {
color: var(--color);
}
</style>
This breaks (querySelector returns null
)
this.shadowRoot.querySelector(':host').style.setProperty('--color', value);
This changes the color
but is not want I want
this.shadowRoot.querySelector('.colored').style.setProperty('color', value);
And finally, this attempt does the trick, but it will only work as long as :host
is the first rule and it is in the first stylesheet.
this.shadowRoot.styleSheets[0].rules[0].style.setProperty('--color', value);
<!DOCTYPE html>
<body>
<my-element></my-element>
<script>
class MyElement extends HTMLElement {
constructor() {
super();
this._color = "green";
this._shadowRoot = this.attachShadow({ mode: "open" });
this._shadowRoot.innerHTML = '';
this._shadowRoot.appendChild(this.template().content.cloneNode(true));
}
template() {
const template = document.createElement("template");
template.innerHTML = `
<style>
:host {display: block;
--color: ${this.color};
}
.colored {
color: var(--color);
}
</style>
<p>The color will change in 2 seconds: <span id="color" class="colored">${this.color}</span></p>
`;
return template;
}
get color() {
return this._color;
}
set color(value) {
this._color = value;
this.shadowRoot.getElementById('color').innerHTML = value;
// ▼ 👉🏻 Uncomment below. Cannot change --color variable; selector returns null
// this.shadowRoot.querySelector(':host').setProperty('--color', value);
// ▼ This works but is not what I want. I need to change the variable
//this.shadowRoot.querySelector('.colored').style.setProperty('color', value);
// ▼ This is subject to the firts stylesheet and :host being first rule
this.shadowRoot.styleSheets[0].rules[0].style.setProperty('--color', value);
}
}
customElements.define("my-element", MyElement);
setTimeout(() => {
document.querySelector('my-element').color = 'blue';
}, 2000);
</script>
</body>
</html>
Thanks!
:host
refers to your <my-element>
So set properties on your my-element
with: this.style.setProperty('--color', value);
<my-element></my-element>
<script>
customElements.define("my-element", class extends HTMLElement {
constructor() {
super()
.attachShadow({mode: "open"})
.innerHTML =
`<style>
:host { --color: red }
.colored { color: var(--color) }
</style>
<p>The color will change in 2 seconds: <span class="colored">${this.color}</span></p>`;
this.color = "green";
}
get color() {
return this._color;
}
set color(value) {
this._color = value;
this.shadowRoot.querySelector('.colored').innerHTML = value;
this.style.setProperty('--color', value);
}
});
setTimeout(() => document.querySelector('my-element').color = 'blue', 2000);
</script>