Reputation: 4159
Created a web component with a shadow DOM. When the button is clicked it adds the open
attribute to the web component.
I would like to show the hidden div in the CSS when the open
is added with CSS styling. Is it possible for the shadow DOM styles to reference attributes on the web component root? Otherwise, I have to add a superfluous class or attribute within the shadow DOM.
class CustomComponent extends HTMLElement {
constructor() {
super();
this.element = this.attachShadow({mode: 'open'});
}
static get observedAttributes() {
return ['open'];
}
attributeChangedCallback(attrName, oldValue, newValue) {
if (newValue !== oldValue) {
this[attrName] = this.hasAttribute(attrName);
}
}
connectedCallback() {
const template = document.getElementById('custom-component');
const node = document.importNode(template.content, true);
this.element.appendChild(node);
this.element.querySelector('button').addEventListener('click', () => {
this.setAttribute('open', '');
});
}
}
customElements.define('custom-component', CustomComponent);
<template id="custom-component">
<style>
div {
display: none;
}
[open] div {
display: block;
}
</style>
<button>Open</button>
<div>Content</div>
</template>
<custom-component></custom-component>
Upvotes: 1
Views: 1055
Reputation: 4159
It appears the host
CSS pseudo selector is designed to handle this precise situation.
class CustomComponent extends HTMLElement {
constructor() {
super();
this.element = this.attachShadow({mode: 'open'});
}
static get observedAttributes() {
return ['open'];
}
attributeChangedCallback(attrName, oldValue, newValue) {
if (newValue !== oldValue) {
this[attrName] = this.hasAttribute(attrName);
}
}
connectedCallback() {
const template = document.getElementById('custom-component');
const node = document.importNode(template.content, true);
this.element.appendChild(node);
this.element.querySelector('button').addEventListener('click', () => {
this.setAttribute('open', '');
});
}
}
customElements.define('custom-component', CustomComponent);
<template id="custom-component">
<style>
div {
display: none;
}
:host([open]) div {
display: block;
}
</style>
<button>Open</button>
<div>Content</div>
</template>
<custom-component></custom-component>
Upvotes: 1