Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Light DOM style leaking into Shadow DOM

I am trying to create a Chrome extension with a floating widget. To do that, I have to isolate my element from the rest of the page. Shadow DOM looks like a perfect fit for that, but it isn't doing what I expected.

Here is my content script:

content.js

var lightDom = document.createElement('style');
lightDom.innerText = 'div { color: red }';

document.body.appendChild(lightDom);

var shadowDom = document.createElement('div');

document.body.appendChild(shadowDom);

var shadowRoot = shadowDom.attachShadow({'mode': 'open'});

shadowRoot.innerHTML = `
    <style>
        div {
            background-color: blue;
        }
    </style>
    <div>Shadow!</div>
`;

The div inside the shadow DOM should have black text, but it has red text instead. Am I doing something wrong?

like image 671
Božo Stojković Avatar asked Apr 07 '18 16:04

Božo Stojković


People also ask

What can be part of the shadow DOM?

Shadow DOM allows hidden DOM trees to be attached to elements in the regular DOM tree — this shadow DOM tree starts with a shadow root, underneath which you can attach any element, in the same way as the normal DOM.

Can you style shadow DOM?

Shadow DOM permits encapsulation of styling rules for custom elements. You can freely define styling information for your elements, such as fonts, text colors, and classes, without fear of the styles applying outside the scope of your element.

How do I get rid of shadow DOM?

In Chrome: Press F12, DevTool will open. Click gear icon in DevTool. Uncheck "show user agent shadow DOM" checkbox.

What is light DOM and shadow DOM?

With shadow DOM, CSS styles defined in a parent component don't apply to a child component. Contrastingly, light DOM enables styling from the root document to target a DOM node and style it. The styles on the following native shadow component cascades into the child component's light DOM.


1 Answers

Why is this happening?

CSS selectors in Light DOM are prevented from reaching elements inside shadow DOM. But when a CSS property has the value inherit, which is the default value of color, the shadow DOM will still inherit those from the light DOM.

From the CSS Scoping specification

3.3.2 Inheritance
The top-level elements of a shadow tree inherit from their host element. The elements in a distribution list inherit from the parent of the content element they are ultimately distributed to, rather than from their normal parent.

How to prevent it from happening?

You can prevent the values of properties form being inherited by using the initial value.

From the CSS Cascading and Inheritance specification

7.3.1. Resetting a Property: the initial keyword
If the cascaded value is the initial keyword, the property’s initial value becomes its specified value.

The initial value of each property is documented in the specification it is defined in. color is documented in the CSS Color specification and its initial value is depends on user agent, for most user agents this will be black.

You can assign initial to each property you don't want to inherit its value. Or you can set the value of all to initial, like so:

.selector 
{
    all: initial;
}

The all property is defined as follows in the same spec as the initial keyword.

3.1. Resetting All Properties: the all property
The all property is a shorthand that resets all CSS properties except direction and unicode-bidi. It only accepts the CSS-wide keywords.

"CSS-wide keywords" is defined in CSS 3 values specification in section 3.1.1, but comes down to the values initial, inherit and unset.

like image 183
Wazner Avatar answered Oct 13 '22 09:10

Wazner