A pseudo-class for when an element is stickily (spec term) positioned

What I posted has nothing to do with the name we use.

1 Like

Oh crap, I read that horribly wrong. I thought it said why not use :stuck. Holly crap how the hell did I read that. Wow my bad that was dumb. :confused:

renders the whole thing useless.

I disagree. If we’d allow only those properties that don’t affect layout to be redefined for the :stuck pseudoclass, we’ll get infinitely more control over what we have now (nothing).

And those properties that don’t affect layout are those that are used for sticky elements in real world use cases. I guess the most popular property to redefine on the stuck state would be a box-shadow.

The layout-changing properties could be useful too, but why can’t we go iteratively and allow just a subset of properties from the start, and think out the solutions to enhance it later?

Developers need position sticky already and need this pseudoclass for them too, saying “there are issues, so you won’t get it in any form” is not productive.

Can we use the behavior for when other pseudo-classes get into infinite loops? For example:

div {
  position: fixed;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;

div:hover {
  height: 0;
  width: 0;

I’m having flashbacks to Web Pages for Dummies where they warn against using font-size for a:hover for this exact reason. Is it still an unsolved problem?

That’s not sufficient; or rather, it’s only sufficient once. As soon as you add a second selector linked to properties, even if relies on a disjoint set of properties, you can force a circularity by having :A set the B property, and have :B respond to that and set the A property. You have to exclude all properties that affect selectors from being used in a style rule using any selector affected by properties. That quickly rules out most/all of CSS, and requires breaking old content that (correctly at the time) used some property that affects the new selector.

The right thing is to just avoid the problem. Find tricksy ways to make it not screw with things, or just leave it and use JS.

No. :hover-based loops are “wide” - they start at style computation, move through layout and rendering, and get all the way to user interaction before they loop back around. The entire page is “done” by the time the loop spins around, so, while the flicker is annoying, it doesn’t prevent the rest of the page from working.

These kinds of property/selector loops are “tight” - they start and end within style computation, and prevent the browser from moving on to layout/rendering/etc at all.

1 Like

Can you provide a meaningful example for the conflicting behaviour you’re mentioning in regards of this example:

.sticky {
  position: sticky;
  top: 0;
  background: red;
  box-shadow: 0 1px #000;

.sticky:stuck {
  background: lime;
  box-shadow: 0 10px 10px -7px rgba(0, 0, 0, 0.5);

How this (or any other external styles) could trigger any kind of circularity there? What do I miss?

Also, there is no way to avoid this using CSS only, and it far from trivial when trying to emulate using JS (btw, would there be/are there already any events in JS to tell when the element become stuck or not?).

Again, the issue is that we can’t ever introduce a second selector that’s affected by properties. (And we can’t ever add a layout-affecting value to one of the “safe” properties.)

Something that we can only do once, ever, and that will affect our ability to evolve CSS in the future, is probably a bad idea for the language.

we can’t ever introduce a second selector that’s affected by properties

I still think this could be handled in some way (like using only one pass (I don’t remember how this mechanism is called now), as we already do for fit-to-content blocks with more than one line). This looks like “this is hard, we won’t ever try”.

we can’t ever add a layout-affecting value to one of the “safe” properties.

We can, if we’d make those values not to work in this context.

All of the solutions I can think of start getting into procedural territory, and I doubt that’s a road the CSSWG wants to go down. Unless we can mark a declaration as “nonvital” or something, and even then I’m not sure that would actually accomplish the right thing.

What if :sticky selects elements which are within a position: sticky element that has been stuck, but does not match the position: sticky element itself?

#sticker {
  position: sticky;
#sticker div {
  background: red;
  border-radius: 50%;
  height: 100px;
  width: 100px;
#sticker div:sticky {
  border-radius: 0;
  1. would it run into any looping issues?
  2. would it still be useful enough to be worthwhile?

If the main problem is creating tight loops, instead of a CSS class, we could have events. For example: Element.onEnterSticky Element.onLeaveSticky

Now javascript code can still create loops, but wide ones, that don’t block the style computation.

Adding and removing CSS classes on the event handlers would be trivial. Much simpler and therefore less error prone than the alternative of computing manually whether the element is stuck or not.

I’m wondering if we could perhaps also allow :stuck in the JS profile for use with querySelector. This wouldn’t have the tight loop issues of allowing it in a stylesheet and there’s precedent for allowing selectors in the JS only profile already (:matches() I believe).

Any update on this feature? This feature is really important, because we can finally get rid off onScroll event for adding .is-stuck classes.

1 Like

Trying the hopefully-more-palatable event-based route:

Couldn’t we just ignore position: inside :sticky-pseudo-class? We already ignore content: outside of pseudo-selectors anyway.

Another way of tackling this issue would be to create a stuck at-rule that accepts a white-listed set of properties:

thead {
    position: sticky;
    top: 0;
    @stuck {
        /* White-Listed: */
        box-shadow: 0 0.25rem 0.25rem hsl(0deg 0% 0% / 0.5);
        /* Not White-Listed (Does Nothing): */
        position: static;

An at-rule doesn’t change anything to the circular dependency.

Why this is not something that can be added to CSS is covered in the CSSWG’s FAQ: https://wiki.csswg.org/FAQ

1 Like

Why we can’t detect cycles when the style is computing, and just drop those rules that causing cycling + warn user in console?

Detecting cycles can get very tricky once you add in a couple selectors. I don’t have examples on hand, but I’ve seen many in the mailing list.