[WICG/webcomponents] custom pseudo elements like ::before ::after, but using custom elements (Issue #983)

I *might* be interesting to define custom pseudo elements that can be custom elements. (This is not a duplicate of the old [custom pseudo elements](https://github.com/WICG/webcomponents/blob/gh-pages/proposals/Custom-Pseudo-Elements.md) proposal, which has been replaced with `:part`)

f.e.

```css
.foo::custom-element-pseudo('my-element') { /* <my-element> is a custom element */ 
  /* ... style the custom element that is "injected" into the DOM similar to ::before or ::after. */
}
```

The idea here is that we want to be able to use custom elements in a way similar to `::before` and `::after` to "inject" custom content into an app purely with CSS, and we want this content to be that which is defined by a custom element, plus additional styling.

----


More advanced example:

```html
<!-- With HTML composition (WET): -->
<lume-mesh position="1 2 3">
 <phong-material color="red"></phong-material>
 <sphere-geometry wireframe></sphere-geometry>

 <lume-mesh position="1 2 3">
  <!-- not DRY (WET): repeat the same elements to give the sub-mesh the same look and shape -->
  <phong-material color="red"></phong-material>
  <sphere-geometry wireframe></sphere-geometry>
 </lume-mesh>
</lume-mesh>

<!-- With CSS custom pseudo elements (DRY): -->
<lume-mesh position="1 2 3">
 <!-- children in the scene graph -->
 <lume-mesh position="1 2 3"></lume-mesh>
</lume-mesh>
<style>
 /* style both meshes with the same geometry and material */
 lume-mesh::custom-element-pseudo('sphere-geometry') {
  wireframe: enable;
 }
 lume-mesh::custom-element-pseudo('phong-material') {
  color: red;
 }
</style>
```

Maybe it should be more generic, like `::element-pseudo('any')`, including built-ins?

What do you think of this idea?

---

# problem that it solves

Besides making the above example more DRY (plus the amazing fact that CSS could enable so much), another way to implement the mesh styling is with [`element-behaviors`](https://github.com/lume/element-behaviors), as I have currently done with [LUME 3D HTML](https://lume.io):

```html
<lume-mesh position="1 2 3" has="phong-material sphere-geometry" color="red" wireframe>
 <lume-mesh position="1 2 3" has="phong-material sphere-geometry" color="red" wireframe>
 </lume-mesh>
</lume-mesh>
```

The advantage of this is I can easily map CSS Custom Properties like `--material: phong; --color: red; --wireframe: enable` to the JS properties (that back the HTML attributes), because CSS Custom Properties are accessible from JavaScript (for example, the simple way to detect their changes would be in an animation frame loop, and without looping we need more-complicated DOM observation).

However, when everything is in attributes, this is a lot less composable. Having child elements like `<sphere-geometry>` is highly composable because the elements can be in the shadow DOM of higher-level custom elements. F.e.:

```html
<lume-mesh>
  <my-mesh-style></my-mesh-style>
</lume-mesh>
```

where `<my-mesh-style>` is a custom element whose ShadowRoot contains:

```html
 <phong-material color="red"></phong-material>
 <sphere-geometry wireframe></sphere-geometry>
```

This ability to compose is very useful. However, a CSS implementation with CSS Custom Properties can no longer simply map properties to all meshes, so the composition version of my example is not so CSS implementation friendly, because selectors targeting meshes are not targeting the children that have the styling features.

I think it *might* be possible to hack this with CSS Custom Properties, but maybe it would be less ideal than an official syntax. For example:

```html
lume-mesh {
  --pseudo-sphere-geometry: ;
  --geometry-wireframe: enable;

  --pseudo-phong-material: ;
  --material-color: red;
}
```

The implementation that reads these custom CSS properties can map those to essentially the same child elements inside the ShadowDOM of the targetted `<lume-mesh>` elements, or something.

# solution

But having an official syntax for it would feel nicer. Elements would perhaps have a new property like `.pseudoElements` which is similar to `.children`, but lists only pseudo elements added via CSS.

Then, an implementation of `<lume-mesh>` only needs to look in one list or the other, but otherwise the logic that wires the style of the mesh would be essentially the same.

-- 
Reply to this email directly or view it on GitHub:
https://github.com/WICG/webcomponents/issues/983
You are receiving this because you are subscribed to this thread.

Message ID: <WICG/webcomponents/issues/983@github.com>

Received on Monday, 13 February 2023 00:44:33 UTC