w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.5k stars 668 forks source link

Add ::top-layer pseudo element #10963

Open rejhgadellaa opened 1 month ago

rejhgadellaa commented 1 month ago

This is a continuation of #7319.

I request that a ::top-layer pseudo element is added. As Bramus proposed:

What if we had a top-layer pseudo element, i.e. ::top-layer? It would be a pseudo-element that’s only available on the html element.

You wouldn’t use it (or be able) to style the top-layer itself, but could use it to target elements that are inside the top-layer by use of a combinator, e.g.

::top-layer * = All elements that appear in the top-layer ::top-layer dialog = Only dialog elements that appear in the top-layer

With this, it would also be possible to target the top-most element or even the top-most dialog, as detailed here.

:nth-last-child(1 of ::top-layer dialog) {
  /* topmost modal dialog in the top-layer, yay! */
}

This would require for ::top-layer to report its (virtual) children in the order in which they got added, though. This is info which I suppose is internally already available, because otherwise top-layer wouldn’t be able to stack it’s contents properly.

Bramus, #7319

I've created a codepen that demonstrates a use case for being able select the top-most <dialog /> and prevent 'stacking' of multiple ::backdrops:

https://codepen.io/rejh/pen/LYKPvNr

Thank you!

Edit: CC @bramus

tabatkins commented 1 month ago

Having it be a pseudo-element with children seems a little more complex than needed, I think? I think we can get the same functionality with a pseudo-class that matches elements in the top-layer list. We can make it functional as well, taking an an+b argument selecting based on top-layer index.

That is, dialog:top-layer would match when the dialog was in the top layer; dialog:top-layer(last 1) would match the last one in the list (which is topmost).

Am I missing something that makes this not work?

rejhgadellaa commented 1 month ago

I think that the benefit of going with a pseudo-element would be that it automatically enables the use of any existing 'state' CSS selector (:nth-child, :has, etc) instead of having to spec and implement that for the pseudo-class?

For example, this should automatically work if ::top-layer would be a pseudo-element:

/* Style popovers if a dialog is also present */
::top-layer:has( dialog ) [popover] {
  ...
}
bramus commented 1 month ago

# Am I missing something that makes this not work?

The discussion in #7319 started with the suggestion to add :top-layer but eventually we moved away from that. This comment summarizes it nicely:

The TL/DR is that OpenUI roughly agreed with CSSWG that perhaps :top-layer isn't a good name. We discussed alternatives like :popup-open (specific to the Pop-up API), or just :open (which should apply to other cases like <summary>/<details>). We also discussed the ::top-layer pseudo element https://github.com/w3c/csswg-drafts/issues/7319#issuecomment-1168531437, but found it too non-standard and confusing for developers.

jpzwarte commented 2 days ago

@bramus Given https://nerdy.dev/have-a-dialog, if we want to style the <body> that way when a modal dialog is open, but the <dialog> is in (nested) shadow DOM, having the ability to do body:has(::top-layer dialog) { scale: 0.8 } etc would be awesome. Otherwise you'd have to use JS to add a class on the body when a dialog is open.

I'm thinking of web component design systems that would benefit from this CSS ability.