Use CSS selectors like :first-child inside shadow dom

旧街凉风 提交于 2020-04-30 06:32:45

问题


Is there any way to use css selectors like :first-child, :not(:last-child) inside of the shadow dom?

The example is like this

CustomElement.html

<div id="parent-div>
 <slot></slot>
</div>

App.html

<div>
 <custom-element>
   <div class="heading">Main Heading</div>
   <div class="item">item 1</div>
   <div class="item">item 1</div>
   <div class="item">item 1</div>
   <div class="heading">Second Heading</div>
   <div class="item">item 1</div>
   <div class="item">item 1</div>
   <div class="item">item 1</div>
 </custom-element>
</div>

what i want to do is find out the first .heading element and add custom styles to it. Since <div class=heading"> is actually a component, i can't add custom styling to it thinking only as the first heading.

P.S.:- I'm using angular-elements, if it helps


回答1:


The same answer as I gave in your question yesterday

Slotted content is not moved to shadowDOM,

it remains (invisible) in lightDOM

and is REFLECTED in the shadowDOM <SLOT>

So SLOTTED content styling is done in the CSS scope where <custom-element> resides.

or with ::slotted( x )

From the docs:

::slotted can only take a compound selector (in the parenthesis). The reason of this > restriction is to make a selector style-engine friendly, in terms of performance.

So with your structure you can do:

 ::slotted(.heading) { }
or
 ::slotted(:first-child) { }

but not:

 ::slotted(.heading:first-child)

Because it is a complex selector, not a (simple) compound selector

So your headings can be styled in global CSS, and will REFLECT to slotted content:

my-element div.heading{
  background:blue;
  color:white;
}

If you want to encapsulate this styling you have to wrap everything in (another) component

You can target all UNnamed slotted content with:

    ::slotted(:not([slot])){
      font-weight:bold;
    }

Here is another JSFiddle to play with slotted styling:

https://jsfiddle.net/CustomElementsExamples/aLezyh35/




回答2:


I found a workaround for this in JS way.

For each slot, we have a eventHandler called (slotchange). By using that we can get the DOM event for the slot whenever the slot changes. Like this (HTML)

<custom-element (slotchange)="onSlotChanged($event)"></custom-element>

JS

onSlotChanged($event) {
 console.log($event) // Go and research yourself about this event, you'll find many things usefull.
 $event.target.assignedNodes() // This will give you the array of every elements, that are in side of the shadow dom
 // Example usage, adding the margin-bottom to only first time (css :firsh-child)
 $event.target.assignedNodes()[0].shadowRoot.getElementById('some-id').style.marginBottom = '10px'
}

If you only need to add a property to the element, you don't have to query shadowDom like "node.shadowRoot". But, if you want to access the element inside the shadowRoot of that element, you have to use that



来源:https://stackoverflow.com/questions/61237571/use-css-selectors-like-first-child-inside-shadow-dom

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!