Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shadow DOM styling from the outside

Tags:

I am searching a way to styling shadow DOM from the outside. For example, I would like to set the color of all text in all 'span.special' elements as RED. Including 'span.special' elements from shadow DOM. How I can do this?

Previously there were ::shadow pseudo-element and /deep/ combinator aka >>> for this purpose. So I could write something like

span.special, *::shadow span.special {
    color: red
}

But now ::shadow, /deep/ and >>> are deprecated. So, what do we have as a replacement of them?

like image 263
Okavango Avatar asked May 20 '16 17:05

Okavango


People also ask

How do you style inside shadow DOM?

Shadow DOM provides a mechanism for encapsulation, meaning that elements inside the shadow DOM don't match selectors outside the shadow DOM. Likewise, styling rules inside the shadow DOM can't "leak" out to affect elements outside the shadow DOM. Shadow DOM permits encapsulation of styling rules for custom elements.

What is shadow DOM piercing?

As written in the spec: The top-level elements of a shadow tree inherit from their host element. What this means is that inheritable styles, like color or font-family among others, continue to inherit in shadow DOM, will pierce the shadow DOM and affect your component's styling.

Which selector can work for shadow DOM element?

The :host selector allows to select the shadow host (the element containing the shadow tree).


2 Answers

I did try many methods, including those described here. Since I'm using an external Web Component lib, I don't have access to modify these components. So, the only solution that worked for me was using JS querySelector, like this:

document.querySelector("the-element.with-shadow-dom")
  .shadowRoot.querySelector(".some-selector").setAttribute("style", "color: black");

Not the best solution, not suitable for large stylings, but does work for little enchancements.

@John this was tested with Chrome 83.0.4103.116 (still going to test in Safari) and I did for Ionic (v5) ion-toast component. Here is the (almost) real code I used:

  import { toastController } from '@ionic/core';

  let toastOpts = {
    message: "Some message goes here.",
    cssClass: "toast-with-vertical-buttons",
    buttons: [
      {
        text: "Button 1",
        side: 'end'
      },
      {  
        text: "Button2",
        side: 'end'
      },
      {
        icon: "close",
        side: "start"
      }
    ]
  }
  toastController.create(toastOpts).then(async p => {
    let toast = await p.present(); // this renders ion-toast component and returns HTMLIonToastElement
    toast.shadowRoot.querySelector('div.toast-button-group-end').setAttribute("style", "flex-direction: column");
  });
like image 110
Bruno Polo Avatar answered Sep 20 '22 15:09

Bruno Polo


You could use @import css as explained in this answer to another question on SO.

Include the rule inside the style element in the shadow tree.

 <style>
   @import url( '/css/external-styles.css' )
 </style>

Note that the >>> combinator is still part of the CSS Scoping Module Draft.

like image 33
Supersharp Avatar answered Sep 19 '22 15:09

Supersharp