How do I select the :first-child of a shadow-dom ::part() of a web component
Unfortunately the spec (https://drafts.csswg.org/css-shadow-parts-1/#part) states that using 'structural pseudo-classes', such as :first-child
is not supported with part
:
The ::part() pseudo-element can take additional pseudo-classes after it, such as x-button::part(label):hover, but never matches the structural pseudo-classes or any other pseudo-classes that match based on tree information rather than local element information.
Can the CSS :part pseudo-selector be used to style nested web components?
Nope. It is not possible. It kind a breaks the encapsulation principle. The right way is to use proper theming. That means using a combination of:
::part - For direct theming of the component
:host-context - for theming based on the context
::slotted - For styling the slotted element inside the styling
For more dynamic theming, you can use above styles in combination with Element.matches
API. Whatever the class/context that the user of the component has set, you can then change the styling of nested children component.
On a side note, modifying the styling of a decadent component (children of children) is a bad practice even when not using Shadow DOM or Web Components. It will result in a brittle non-maintainable CSS.
Edit Note:
:host-context
is not implemented in all browsers and probably never will.
Use CSS selectors like :first-child inside shadow dom
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
Related Topics
How to Dynamically Size Multi-CSS Sprite Image
Making HTML Content Unbreakable (In One Line)
Display Optgroup Label as Initial Option
Performance of Jquery Selectors Vs CSS3 Selectors
HTML5 Vs HTML4 - H1 Tag Rendered with Extra Space - How to Remove
Radio Button Show/Hide Content
How to Easily Change a Font-Sizing from Px to Em for a Big, Existing Site
Asp.Net Mvc: How to Use Razor Variable in CSS File
Timing Within a CSS Image Slider
How to Stop a CSS Keyframe Animation
Svg Pattern and Gradient Together
How to Get CSS Pseudo Element: Checked to Work in Ie7 + Ie8
Background with Radius-Top Inside
How to Fix Background Image Inside Div
How to Seamlessly Align Block Divs of Different Sizes