Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[css-shadow-parts-2] Add part-name CSS property #10988

Open
Westbrook opened this issue Oct 1, 2024 · 3 comments
Open

[css-shadow-parts-2] Add part-name CSS property #10988

Westbrook opened this issue Oct 1, 2024 · 3 comments

Comments

@Westbrook
Copy link

Currently to surface a part for consumption the name of the part needs to originate from an HTML attribute:

<shadow-host>
  <template shadowrootmode="open">
    <button part="button">Click me!</button>
  </template>
</shadow-host>

Then later, in CSS, the element can be selected as follows:

::part(button) {
   /* ... styles ... */
}

I have realized that this is very close to the syntax for View Transitions:

::view-transition-group(...) {
  /* ... styles ... */
}

However, View Transitions are not required to use a attribute to make this association, they are given the view-transition-name property to do this instead.

.element-to-transition {
   view-transition-name: ...;
}

This maintenance of the application and consumption of values in the same language space is quite nice...

The part-name property

Can CSS Parts have a reciprocal part-name property?

With a new property along these lines, the previous example would look as follows, with the consumption of the part remaining the same:

<shadow-host>
  <template shadowrootmode="open">
    <style>
      button {
        part-name: button;
      }
    </style>
    <button>Click me!</button>
  </template>
</shadow-host>

While it may initially seem more verbose, in most cases elements that are exported as parts are already getting some sort of default styling so adding one line to that would be much more akin to the code require for part="...". What's more, the part being bound to a CSS construct would simplify the need seen in a lot of part="..." usage of paralleling that with a class or other attribute values for styling.

Possibilities

With this move export parts could also be moved into the CSS realm, and work something like:

<shadow-host>
  <template shadowrootmode="open">
    <style>
      ::part(button) {
        part-name: button;
      }
    </style>
    <custom-button>
      <template shadowrootmode="open">
        <style>
          button {
            part-name: button;
          }
        </style>
        <button>Click me!</button>
      </template>
    </custom-button>
  </template>
</shadow-host>

This may also open the door for more flexible syntaxes in this are as requested/planned in WICG/webcomponents#1051 and #3422 et al.

What other possibilities do you see coming from such an addition to the ::part(...) API?

Potential issues

CSS Parts can be addressed "internally" from the outside via :host::part(...). What happens when you rename such a part?

<shadow-host>
  <template shadowrootmode="open">
    <style>
      :host::part(button) {
        part-name: not-button;
      }
    </style>
    <button part="button">Click me!</button>
  </template>
</shadow-host>
  • Is this a weird cycle that blocks the whole idea?
  • Is this the element leveraging the external nature of the :host selector (reminder :host doesn't technically exist in the shadow root) to self name the part for reexporting into the grandparent DOM tree?
  • Is this a reason to not allow part-name in :host selectors?
  • Is this a reason to not allow part-name in ::part(...) selectors?

What other potential issues do you see getting in the way of such an addition to the ::part(...) API?

@lukewarlow
Copy link
Member

The part attribute currently takes a list of values, would part-name allow that?

There's also a .part property which returns a DOMTokenList, if we allow this to be set in CSS that would require a style lookup for this property to work.

@Westbrook
Copy link
Author

A style lookup to resolve .part would certainly be unfortunate...though would it be prohibative?

Multiple parts is a great point, an approach like this would need to not reduce the API surface, meaning it would need to accept multiple. This of course adds a couple of new "Potential issues":

  • there's no such thing as merged property values, to the best of my knowledge, so if you wanted <button class="thing-1 thing-2"> to have multiple parts, one because of the class thing-1 and another because of thing-2, there is likely no path to making that possible, at least not without additional changes to the underlying APIs of CSS
  • in practice this approach to applying multiple part names would likely also suffer from the same issue that lead to transform being broken in scale, translate, et al, the inability to easily edit one of the many values of the property.

Hrm...but the symmetry with view-transition-name is so nice.

@jsebrech
Copy link

jsebrech commented Oct 2, 2024

There's another symmetry to consider and that is symmetry with the slot attribute. It might be confusing to a web developer that you use attributes to identify a slot or slot name, but a CSS property to identify a part.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants