Nathan Ridley
Nathan Ridley

Reputation: 34396

How can I share a single stylesheet reference, css variables or css rules among multiple shadow roots?

I have a page composed of many instances of the same type of web component. When I hover over one component instance, I'd like to apply an effect to every other component of the same type. To do this, I thought perhaps I could have each component reference the same stylesheet, then I could programatically remove a common class from the hovered-over element, then load the stylesheet, extract the relevant selector and modify the associated styles, thus hypothetically affecting all of the other custom element instances using that same stylesheet. Unfortunately it seems each separate use of the stylesheet is locally-isolated, which means modifying the rules for one element has no effect on the others.

It's possible I'm doing something wrong; if I uncheck a rule in the shared stylesheet using Chrome's developer tools, it does in fact disable it for all elements. I'm not sure if this is just special behaviour provided by Chrome, or if my method of finding the stylesheet instance in the DOM and modifying it is the wrong approach.

What's an efficient solution that would allow me to apply a shared set of styles to all custom elements / shadow roots of a particular custom element type, and then be able to make a single style rule change that affects all of them?

Support for older browsers is not required. I can pretty much focus on the latest version of Chrome in this case.

Upvotes: 2

Views: 204

Answers (2)

Intervalia
Intervalia

Reputation: 10965

If you are only supporting the latest browsers, (No internet Explorer) then you can also use CSS variables.

In your JS file you just set the CSS variable on <body> and it will be used in the CSS of all of your elements.

this.addEventListener('mouseenter', () => {
  document.body.style.setProperty('--my-el-background-color', 'red');
});

this.addEventListener('mouseleave', () => {
  document.body.style.setProperty('--my-el-background-color', '');
});
.my-el__some-css {
  background-color: var(--my-el-background-color, white);
}

Upvotes: 1

Nathan Ridley
Nathan Ridley

Reputation: 34396

Solved it through the use of the :host-context() pseudo-selector that I found in the CSSWG spec.

In the custom element constructor:

this.addEventListener('mouseenter', () => {
  this._containerEl.classList.remove('not-focused');
  this.parentElement.classList.add('has-focused-node');
});

this.addEventListener('mouseleave', () => {
  this._containerEl.classList.add('not-focused');
  this.parentElement.classList.remove('has-focused-node');
});

In the shared stylesheet:

:host-context(.layout-container.has-focused-node) .stream-node.not-focused {
  /* styles for all other elements */
}

Upvotes: 2

Related Questions