You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[css-position] Events for stickiness changes #1660
Since the suggestion in #1656 for a :stuck pseudo-class is not feasible, the next best alternative would be for browsers to fire events (e.g. stuck, unstuck), similar to those of CSS Transitions, whenever a position: sticky; element changes its stuckedness. Then the same styling abilities become possible at the cost of a teeny bit of JS and a teeny associated processing delay:
.some-class.is-stuck {
/* cool stuck-specific styles here */
}
For robustness, the relevant event also needs to be fired when the element changes between the posititon: <anything but sticky> and (position:sticky-and-currently-stuck) states.
Couldn't you use an IntersectionObserver, narrowing your viewport to the area where the element will end up stuck (either top or bottom of the screen)?
I tried, and was not able to use IntersectionObserver to fix this. It doesn't seem to work with sticky elements when they are sticking to the top of the viewport. Not sure if this is a bug or not.
Unfortunately, i deleted the buggy code. So i tried to replicate the issue in a simpler setup, but then it actually worked! So maybe the bug is more specific than I thought, or maybe I simply made an error in my original code. I am sorry that I can't be of more help than that.
The good part about this is that we can use it. And I am actually using it on a new small project. It's a slightly more advanced implementation, but if anyone wants to use it in their projects, they are very welcome to take a look at it here: [broken link].
Note that the function only works when the page is viewed on a real/emulated mobile phone.
Also note that i am still working on this project for a few days to come, so the site is subject to changes or breaking, but i will not be removing the IntersectionObserver feature.
Great to see that it's actually working for you!
FWIW I just tried this in Edge Insider Preview with position:sticky support and it worked like a charm.
While the IntersectionObserver solution is working, it looks a bit like a hack in regard of the rootMargin value and is much more verbose than using events.
Sebastian
Reacted by 流采, Armin Makovec, Nguyễn Huỳnh Lợi and woody-li
The Working Group just discussed Events for stickiness changes, and agreed to the following resolutions:
RESOLVED: Close issue 1660 no change.
The full IRC log of that discussion
<dael> Topic: Events for stickiness changes
<dael> github: https://github.com//issues/1660
<dael> Rossen_: Summary, issue is someone asked if we can have an event to be able to know when the element goes into a stuck state and if it transitions to unstuck.
<dael> Rossen_: There were a few suggestions given, fremy pointed out if you use intersection observer everything works. After a little while people confirmed this is the case. They proposed to close no change.
<dael> Rossen_: I want to hear if you agree with this.
<dael> smfr: I agree
<dael> Rossen_: Objections to close, no change?
<dael> RESOLVED: Close issue 1660 no change.
I would say that I'm also for the native stickiness events and against using hacks or any non-trivial code for that.
More than that, I also totally disagree with any arguments against the :stuck in CSS, but well, it seems that there is no way devs would persuade spec-writers to add it.
I've cloned the most common usage of sticky header in my own way. I had to use 2 indicators with 2 Observer. Summary: I still vote to the :stuck pseudo, because this code is not my favorite, however works:
If someone knows how to make it simpler, I'll appreciate that.
Actually my problem with my code if it is against the separation theory of style and html structure.
So I'm still looking for a solution without extra html elements.
I've reduced the code to 1 indicator only, but now no reverse animation effect. I think this the max we can do for it with intersectionObserver. Other stuff is: position sticky element has reserved space int he flowed content, so resize made a layout jump. Workaround adding a margin-bottom to :stuck styled header.
Sure you can use JS+DOM hacks (based on IntersectionObserver) to figure out when something started to stuck. The exact same argument could be given for position:sticky itself. Plenty of websites implement(ed) it with JS+DOM hacks. And yet, browsers decided to support position:sticky natively to make it more convenient, less hacky, and more robust.
Does anyone have any better argument against the proposal in this issue than "it can be done with JS+DOM hacks"? Or at least one that is consistent with the decision to implement position:sticky in the first place?
Reacted by Armin Makovec, Nguyễn Huỳnh Lợi, Teagan Atwater, Ariane-B, Eric Michel and Chris Rebert
It seems people have been aware of the FAQ item. Sorry for the noise. For the proposal in the issue itself, the event approach, I don't think that's infeasible.
Thought about it a bit more, I guess even if we want something more convenient to get notified from stuck / unstuck, that's probably better also be an observer-like thing, rather than an event. I don't think we want to add more event into the layout pipeline, since event needs to be synchronous, which makes it easier to slow down pages, and it doesn't seem to me that the usecase here requires being synchronous. So using an asynchronous observer mechanism should be preferred over events.
On the other hand, it seems adding one observer type for each thing we want to listen to feels heavier than adding an event, where we can just share the whole mechanism.
Maybe we should invent a new LayoutObserver-ish thing and design an API similar to the event listener, but make it async. That way we can add new observing type easily. Some of the existing events can probably also be added there for performance etc. (Maybe there has been some idea like this proposed in WICG?)
Re :stuck: btw, I don't find the wiki FAQ answer in any way sufficient. The toggle states part should be plain removed, as something that we would never have for similar reasons, and having something that would never matter as an arguments against something else is a circularity issue by itself, haha.
And I never heard any arguments why white-listing properties can't be used. There is a finite amount of properties that are used in most of the use cases for the :stuck, and almost none of those touch layout in any way. Shadows, background, color etc. — in most cases the design needs for :stuck touches on those.
Whitelisting some of the properties would be enough for start, and then we could start to think about the proper global solution for any circularity issues.
Reacted by Radek Šerý, Armin Makovec, Nguyễn Huỳnh Lợi, superlou, Riley Shaw, Teagan Atwater, Ariane-B, Kaleidea and Scott C Romack -AI-
What exactly happens when a layout event fires that slows down pages? Is it that the layout algorithm gets blocked until the event handler completes? I thought that event handlers had to run in tasks within the event loop, independently of the layout code of the browser. Or is this an implementation detail of some particular browser?
Oh, I think I got it - minus means inwards, shrink bounding rectangle inwards..
But that doesn't work when sticky element is the very first inside it's root, and it has top: 0.
Because it doesn't move anywhere on scroll, it becomes sticky immediately, but intention actually to add shadow only after user starts scrolling to show that sticky element has started hovering the following content.
Hack with adding sentinel elements to the top and the bottom of the scrolling root like this one has limitations.
In certain cases I can't add extra elements inside container and when I can it become not possible to use some pseudo-classes like :first-child for a meaningful content.
In general this way adds cumbersome code and difficulties for other team member to reason about it.
So I'm not sure why The Working Group decided that intersectionObserver hack is well enough. It is not in real life.
Reacted by Anton, Radek Šerý, roman, Nguyễn Huỳnh Lợi, Erik Bročko, Adrien Leloup, woody-li, Adam Tulloss, Or'el and Anoesj Sadraee
There is a problem with sentinel elements when we use position: sticky for sticking table parts (column, header, ...). In that case, there are actually several problems. Starting with we are unable to add <div> inside table <tr> element, or dealing with unknown column width. I'm unable to solve this without CSS :stuck or similar JS event or intersetion observer. Only solution for me in this case would be scroll events.
Reacted by Pavel Klimashkin, Roman Komarov, Ariane-B, Or'el and Tim Paul
Activity
jhpratt commentedon Jul 29, 2017
Agreed 100%. If a pseudoclass isn't feasible (and I agree it isn't for the reason Tab stated), there should still be some way of knowing.
FremyCompany commentedon Aug 31, 2017
Couldn't you use an IntersectionObserver, narrowing your viewport to the area where the element will end up stuck (either top or bottom of the screen)?
atjn commentedon Sep 14, 2017
I tried, and was not able to use
IntersectionObserverto fix this. It doesn't seem to work withstickyelements when they are sticking to the top of the viewport. Not sure if this is a bug or not.FremyCompany commentedon Sep 14, 2017
Seems like a bug. Do you have a test case? That would be super valuable!
atjn commentedon Sep 14, 2017
Unfortunately, i deleted the buggy code. So i tried to replicate the issue in a simpler setup, but then it actually worked! So maybe the bug is more specific than I thought, or maybe I simply made an error in my original code. I am sorry that I can't be of more help than that.
The good part about this is that we can use it. And I am actually using it on a new small project. It's a slightly more advanced implementation, but if anyone wants to use it in their projects, they are very welcome to take a look at it here: [broken link].
Note that the function only works when the page is viewed on a real/emulated mobile phone.
Also note that i am still working on this project for a few days to come, so the site is subject to changes or breaking, but i will not be removing the
IntersectionObserverfeature.FremyCompany commentedon Sep 15, 2017
Great to see that it's actually working for you!
FWIW I just tried this in Edge Insider Preview with position:sticky support and it worked like a charm.
FremyCompany commentedon Sep 15, 2017
Agenda+ to close as NoChange if no one else has a strong opinion on this
SebastianZ commentedon Sep 20, 2017
While the
IntersectionObserversolution is working, it looks a bit like a hack in regard of therootMarginvalue and is much more verbose than using events.Sebastian
css-meeting-bot commentedon Sep 20, 2017
The Working Group just discussed
Events for stickiness changes, and agreed to the following resolutions:RESOLVED: Close issue 1660 no change.The full IRC log of that discussion
<dael> Topic: Events for stickiness changes<dael> github: https://github.com//issues/1660
<dael> Rossen_: Summary, issue is someone asked if we can have an event to be able to know when the element goes into a stuck state and if it transitions to unstuck.
<dael> Rossen_: There were a few suggestions given, fremy pointed out if you use intersection observer everything works. After a little while people confirmed this is the case. They proposed to close no change.
<dael> Rossen_: I want to hear if you agree with this.
<dael> smfr: I agree
<dael> Rossen_: Objections to close, no change?
<dael> RESOLVED: Close issue 1660 no change.
SebastianZ commentedon Sep 21, 2017
Unfortunately my comment was not addressed in the discussion. Could this be reconsidered?
Sebastian
atjn commentedon Sep 22, 2017
I completely agree with @SebastianZ that using the
IntersectionObserveris a hack, that would never work as well as a native solution.And since this issue is very directly linked to any native sticky headline, i think something should be done to make a more native solution.
kizu commentedon Sep 22, 2017
I would say that I'm also for the native stickiness events and against using hacks or any non-trivial code for that.
More than that, I also totally disagree with any arguments against the
:stuckin CSS, but well, it seems that there is no way devs would persuade spec-writers to add it.8 remaining items
hunboy commentedon Jan 22, 2018
I've cloned the most common usage of sticky header in my own way. I had to use 2 indicators with 2 Observer. Summary: I still vote to the :stuck pseudo, because this code is not my favorite, however works:
https://jsfiddle.net/utasir/92L8L85q/12/
If someone knows how to make it simpler, I'll appreciate that.
Actually my problem with my code if it is against the separation theory of style and html structure.
So I'm still looking for a solution without extra html elements.
I've reduced the code to 1 indicator only, but now no reverse animation effect. I think this the max we can do for it with intersectionObserver. Other stuff is: position sticky element has reserved space int he flowed content, so resize made a layout jump. Workaround adding a margin-bottom to :stuck styled header.
https://jsfiddle.net/utasir/92L8L85q/17/
geoken commentedon Jan 22, 2018
So to summarize;
Why is #2 undesirable vs. having us infer that same thing in an indirect way?
rubenlg commentedon Mar 20, 2018
Sure you can use JS+DOM hacks (based on IntersectionObserver) to figure out when something started to stuck. The exact same argument could be given for position:sticky itself. Plenty of websites implement(ed) it with JS+DOM hacks. And yet, browsers decided to support position:sticky natively to make it more convenient, less hacky, and more robust.
Does anyone have any better argument against the proposal in this issue than "it can be done with JS+DOM hacks"? Or at least one that is consistent with the decision to implement position:sticky in the first place?
upsuper commentedon Mar 20, 2018
There is a comprehensive explanation about why
:stuckis not feasible in CSSWG's FAQ: https://wiki.csswg.org/faq#selectors-that-depend-on-layoutupsuper commentedon Mar 20, 2018
It seems people have been aware of the FAQ item. Sorry for the noise. For the proposal in the issue itself, the event approach, I don't think that's infeasible.
upsuper commentedon Mar 20, 2018
Thought about it a bit more, I guess even if we want something more convenient to get notified from stuck / unstuck, that's probably better also be an observer-like thing, rather than an event. I don't think we want to add more event into the layout pipeline, since event needs to be synchronous, which makes it easier to slow down pages, and it doesn't seem to me that the usecase here requires being synchronous. So using an asynchronous observer mechanism should be preferred over events.
upsuper commentedon Mar 20, 2018
On the other hand, it seems adding one observer type for each thing we want to listen to feels heavier than adding an event, where we can just share the whole mechanism.
Maybe we should invent a new LayoutObserver-ish thing and design an API similar to the event listener, but make it async. That way we can add new observing type easily. Some of the existing events can probably also be added there for performance etc. (Maybe there has been some idea like this proposed in WICG?)
kizu commentedon Mar 20, 2018
Re
:stuck: btw, I don't find the wiki FAQ answer in any way sufficient. Thetoggle statespart should be plain removed, as something that we would never have for similar reasons, and having something that would never matter as an arguments against something else is a circularity issue by itself, haha.And I never heard any arguments why white-listing properties can't be used. There is a finite amount of properties that are used in most of the use cases for the
:stuck, and almost none of those touch layout in any way. Shadows, background, color etc. — in most cases the design needs for:stucktouches on those.Whitelisting some of the properties would be enough for start, and then we could start to think about the proper global solution for any circularity issues.
rubenlg commentedon Mar 20, 2018
Thanks for the details @upsuper
What exactly happens when a layout event fires that slows down pages? Is it that the layout algorithm gets blocked until the event handler completes? I thought that event handlers had to run in tasks within the event loop, independently of the layout code of the browser. Or is this an implementation detail of some particular browser?
klimashkin commentedon Jan 7, 2019
I don't really get how does intersectionObserver with
rootMarginhack work here http://htx.antonjuulnaber.dk/afsaltningsanlaegget/ ?How to read
rootMargin: "0px 0px -99% 0px"? What does it mean?It doesn't work in my case.
klimashkin commentedon Jan 7, 2019
Oh, I think I got it - minus means inwards, shrink bounding rectangle inwards..
But that doesn't work when sticky element is the very first inside it's root, and it has
top: 0.Because it doesn't move anywhere on scroll, it becomes sticky immediately, but intention actually to add shadow only after user starts scrolling to show that sticky element has started hovering the following content.
klimashkin commentedon Jan 7, 2019
Hack with adding sentinel elements to the top and the bottom of the scrolling root like this one has limitations.
In certain cases I can't add extra elements inside container and when I can it become not possible to use some pseudo-classes like :first-child for a meaningful content.
In general this way adds cumbersome code and difficulties for other team member to reason about it.
So I'm not sure why
The Working Groupdecided thatintersectionObserverhack is well enough. It is not in real life.zipper commentedon Feb 26, 2019
There is a problem with sentinel elements when we use
position: stickyfor sticking table parts (column, header, ...). In that case, there are actually several problems. Starting with we are unable to add<div>inside table<tr>element, or dealing with unknown column width. I'm unable to solve this without CSS :stuck or similar JS event or intersetion observer. Only solution for me in this case would be scroll events.tayloraucoin commentedon Sep 9, 2019
IntersectionObserver is also non-compatible with IE. So any implementation with it will not be backward compatible with the relic browser.
atjn commentedon Sep 10, 2019
@tayloraucoin true, but any new spec also won't be compatible, and IE doesn't have support for the sticky position anyways.