Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
257 views
in Technique[技术] by (71.8m points)

css - How to style slotted parts from the parent downwards

How can I style parts which have been slotted into a web component?

My goal is to create 'functional' components which only renders some parts based on the state that they are in (using Redux). These components are then rendered in a container. This containers knows which kinds of children it can expect and should style the parts from the children accordingly.

An example is a feed of posts, in which all posts are the same web component which only render some parts. Then there is a grid feed component and renders these posts in a grid. Another chronological feed might simple render the posts underneath each other. In both cases the post itself is not aware in the context that it is in. I want the container component to be responsible for the layout/styling.

I kinda want the inverse of host-context. With host-context the post component knowns in which containers it can be in and style themself accordingly. But I would like to keep my post component purely functional without any styling. (and host-context is not well supported)

This snippet shows my attempts to make the title of the post red when it is in a my-grid element. But none of my attempts work.

customElements.define('my-grid', class extends HTMLElement {
  constructor() {
    super().attachShadow({
        mode: 'open'
      })
      .append(document.getElementById(this.nodeName).content.cloneNode(true));
  }
});
customElements.define('my-post', class extends HTMLElement {
  constructor() {
    super().attachShadow({
        mode: 'open'
      })
      .append(document.getElementById(this.nodeName).content.cloneNode(true));
  }
});
<template id="MY-GRID">
  <style>
:host {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
  grid-auto-rows: minmax(auto, 100px);
}

::slotted(my-post) {
  display: contents;
}

/* Attempts at styling the parts withing the slotted posts */
my-post h1,
 ::slotted(my-post) h1 {
  background-color: red;
}

my-post ::part(test),
 ::slotted(my-post) ::part(test) {
  background-color: red;
}

my-post::part(test),
 ::slotted(my-post)::part(test) {
  background-color: red;
}
  </style>
  <slot></slot>
</template>
<template id="MY-POST">
  <h1 part="title">Title</h1>
</template>
<my-grid>
  <my-post></my-post>
  <my-post></my-post>
  <my-post></my-post>
  <my-post></my-post>
  <my-post></my-post>
</my-grid>
question from:https://stackoverflow.com/questions/65540853/how-to-style-slotted-parts-from-the-parent-downwards

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You had multiple issues

  • Typos: You are mixing title and test for your ::part(x) references
  • ::slotted is a very simple selector, so you can discard all those tries
  • (per above link) Slotted content remains in lightDOM; so your elements in lightDOM:
<my-grid>
  <my-post></my-post>
  <my-post></my-post>
  <my-post></my-post>
  <my-post></my-post>
  <my-post></my-post>
</my-grid>

must be styled from its container.... in this case the main document DOM

So all global style required is:

  my-post::part(title) {
    background: red;
  }

You can not do this in <my-grid> because <my-post> is not inside <my-grid> lightDOM
<my-grid> can not style its slotted content (only the 'outer' skin with ::slotted)

I added extra styling, slots and a nested <my-post> element to make things clear

<script>
  class GridElements extends HTMLElement {
    constructor() { super().attachShadow({mode: 'open'})
      .append(document.getElementById(this.nodeName).content.cloneNode(true)) }}
  customElements.define('my-grid', class extends GridElements {});
  customElements.define('my-post', class extends GridElements {});
</script>
<template id="MY-GRID">
  <style>
    :host{display:grid;grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)) }
    ::slotted(my-post) { background: green }
  </style>
  <slot></slot>
</template>
<style id="GLOBAL_STYLE!!!">
  body { font: 14px Arial; color: blue }
  my-post::part(title) { background: red }
  my-grid > my-post::part(title) { color: gold }
  my-post > my-post::part(title) { background:lightcoral }
</style>
<template id="MY-POST">
  <h1 part="title"><slot name="title">[Title]</slot></h1>
  <slot>[post body]</slot>
</template>
<my-grid>
  <my-post><span slot="title">One</span></my-post>
  <my-post>Two</my-post>
  <my-post></my-post>
  <my-post>
    <my-post><span slot="title">SUB</span></my-post>
  </my-post>
</my-grid>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...