CSS 属性通过 Shadow DOM 传递的极端情况,即使 :host {all:initial}

问题描述 投票:0回答:1

这可能是我在 Stack 上的第一个问题!我发现我认为 CSS 属性通过影子 DOM 传递的一个极端情况,尽管提出了著名的修复方案here

一般背景 我正在构建一个 chrome 扩展,在网站中注入一个弹出窗口。我发现,尽管弹出窗口有 Shadow DOM,但根据它显示的页面,弹出窗口可以有不同的字体。

Shadow DOM 和可继承属性

我了解到可继承的属性往往会通过影子 DOM,这有点道理。例如,如果您有

{font-weight: bold}
,它将传递给影子 DOM 中的所有元素,除非您为影子 DOM 中的元素指定不同的
font-weight
值。

我找到的解决方案是将影子根主机的所有元素设置为其默认值。这样,就不会发生任何泄漏。下面是我们如何保护主 DOM 中的属性

font-weight
color
不泄露到影子 DOM 的示例。

<head>
    <style>
        #mainbod {
            font-weight: bold;
            color: red;
        }
    </style>

    <script>
        document.addEventListener('DOMContentLoaded', function () {
            let wr = document.getElementById('tata-wrapper');
            let shadow = wr.attachShadow({ mode: 'open' });
            wr.shadowRoot.innerHTML = `<style> :host { all : initial} !important </style>`
            let xp = document.createElement('div')
            xp.id = 'explainAI'
            xp.innerHTML = `
            <style>
                .cbd {
                    background-color: rgb(190, 218, 228);
                }
            </style>

            <div id="popup-container">
                <div class="cbd first">
                    <span>Something else here, maybe this or that.</span>
                </div>
            </div>
            `
            wr.shadowRoot.appendChild(xp)
        });
    </script>
</head>

<body>
    <div id="mainbod">
        <div>
            <p> Some other text</p>
        </div>
        <div id="tata-wrapper">
        </div>
    </div>
</body>

边缘案例

到目前为止都很棒!事实证明,这并不稳健。如果主机中的某个属性(在本例中为

tata-wrapper
)碰巧设置为
inherit
,则该值将会泄漏。这是一个示例,我们将
tata-wrapper
的所有属性设置为继承。该
:host { all: initial}
修复不再有效。我们将看到 Shadow DOM 内的元素将是红色且粗体

<head>
    <style>
        #mainbod {
            font-weight: bold;
            color: red;
        }

        #tata-wrapper {
            all: inherit
        }
    </style>

    <script>
        document.addEventListener('DOMContentLoaded', function () {
            let wr = document.getElementById('tata-wrapper');
            let shadow = wr.attachShadow({ mode: 'open' });
            wr.shadowRoot.innerHTML = `<style> :host { all : initial} !important </style>`
            let xp = document.createElement('div')
            xp.id = 'explainAI'
            xp.innerHTML = `
            <style>
                .cbd {
                    background-color: rgb(190, 218, 228);
                }
            </style>

            <div id="popup-container">
                <div class="cbd first">
                    <span>Something else here, maybe this or that.</span>
                </div>
            </div>
            `
            wr.shadowRoot.appendChild(xp)
        });
    </script>
</head>

<body>
    <div id="mainbod">
        <div>
            <p> Some other text</p>
        </div>
        <div id="tata-wrapper">
        </div>
    </div>
</body>

暂定解决方案

我找到的唯一解决方案是实际将实际父级的

all
的值设置为
initial
(即
tata-wrapper
。我按如下方式操作

// start of the code ... 
let wr = document.getElementById('tata-wrapper');
wr.style.all = 'initial';
let shadow = wr.attachShadow({ mode: 'open' });
wr.shadowRoot.innerHTML = `<style> :host { all : initial} !important </style>`
let xp = document.createElement('div')
xp.id = 'explainAI'
// rest of the code 

我认为这不是一个很好的解决方案,并且可能存在潜在危险。想知道是否有人有解决方案。

javascript html css inheritance shadow-dom
1个回答
0
投票

这里有一个较短的

all:initial
游乐场可供学习,
看看当您删除
!important
(在两种设置中)

时会发生什么

请注意上面代码中的 your

!important
符号不是正确的语法

<style>
  my-component {
    background: red;
    color: blue !important;
  }
</style>

<my-component></my-component>

<script>
  customElements.define("my-component", class extends HTMLElement {
    constructor() {
        super()
          .attachShadow({ mode: "open" })
          .innerHTML = `
            <style>
             :host {
                display: inline-block;
                all: initial !important; /* correct notation for your goal */
                color: green;
              }
              h1 {
                background:gold;
              }
            </style>
            <h1>Hello Web Component World!</h1>`;
    }
  })
</script>

© www.soinside.com 2019 - 2024. All rights reserved.