-
-
Notifications
You must be signed in to change notification settings - Fork 83
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
Avoid style recalculation of all elements on each scroll event #592
Avoid style recalculation of all elements on each scroll event #592
Conversation
✅ Deploy Preview for colorjs ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
If we have to set a fixed width, maybe set it in a font-relative unit so we can make CSS changes without having to adjust it. |
9b0c967
to
1860c8b
Compare
The previous code depended on getting the scrolled amount through a custom property on the root element. This caused laggy scrolling and can be avoided by using `position: sticky`, which has the same behavior as the previous code. The best way to do this is by changing the markup to be similar to the `/api` pages, which use a separate stylesheet. It uses a grid that allows the sticky element to have space next to the main content. For the other pages, the submenu is actually inside of the main content container and relies on `position: fixed` to escape it. However such a markup change would need a lot of CSS adaptations. Hence this commit solves it with CSS only instead, in a way that is very unlikely to affect other elements on the page.
1860c8b
to
1471218
Compare
Yeah I tried to preserve the previous behavior as much as possible, the previous fixed value was a quick fix. I was now able to make it have the same behavior as before. Not by making |
@LeaVerou Are the current changes an acceptable way to address the performance issue? I added some info about the improvement in the description. I did not find any regressions due to these changes. So it seems like a safe way to improve performance for all users, while removing the urgency of changing the markup to be similar to the /api page so it can accommodate sticky elements in a cleaner way. Personally, I wouldn't worry too much about it using this 3em, or the exact spacing values, if no regressions are observed. If any later CSS changes need other dynamic values / variables to be in that place, that is something that can also be figured out at that time, and it will be more obvious what needs to go there. Also keep in mind that changing the markup (the better solution) will further simplify the CSS and remove many of the spacing values it now uses. Of course, feel free to solve this in any other way. I mostly created this PR to show what the problem is and that it can be addressed. As long as the solution removes the listener, you will see the same performance improvement. |
I really like the proposed fix—It solves the issue elegantly. 👍 I would suggest minor changes to make the TOC even more responsive to the different screen sizes. Something like this: @media (min-width: 1480px) {
+ --_gap: 1rem;
+ box-sizing: border-box;
/* Stretch out #toc in the margin, so it can be a container for the sticky list. */
position: absolute;
right: 100%;
height: 100%;
+ padding-inline: var(--_gap);
- /* Still sorting what to use for the 3em. */
- max-width: calc(var(--page-margin) - 3em);
+ max-width: calc(var(--page-margin) - 2 * var(--_gap));
width: max-content;
& > ul {
position: sticky;
- top: 1em;
+ top: var(--_gap);
}
} I didn't want to suggest them in the code so that we could discuss them here, but if it's more convenient for you, I can do that. I hope you don't mind. 🙃 TOC.mp4 |
Thanks @DmitrySharabin! Those changes look good to me, I added them to the PR. I guess there are still some reasons to (eventually) use the same approach (or same code) as the TOC elements on the |
Great!
I would do it in another PR—it seems a bit orthogonal to the issue we are trying to solve here. Even with the changes you made, the website works and feels much better. So, I wouldn't hold this PR and ask @LeaVerou to review it. Let's see what she will tell us. 🙂 |
Yes definitely, just mentioning it as a suggestion in case future changes happen to the TOC 🙂 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thank you all!!
Description
Addresses laggy scrolling resulting from unnecessary style recalculations.
The most important thing about this PR is that this listener is removed.
Without the listener, the main thread is almost completely idle during scrolling. With the listener, the main thread is fully occupied with tasks that take hundreds of milliseconds on lower end devices. That means scrolling at a few FPS, 100% of the time.
The only thing this listener is doing is make an element behave as though it has
position: sticky
. So the goal of the PR is to convert it toposition: sticky
and remove the need for any style recalculation.Using
position: sticky
also has better behavior in other ways. The previous code results in the bottom items not being reachable on long lists (such as /spaces).Probably the best solution
The markup should probably be changed to be similar to the /api page.
For
position: sticky
to work, you need to have a container that spans the height you want the element to travel. So you'd want a container which is positioned next to the content and is equally high.However, in the current markup the TOC element is inside of the content, so
position: sticky
cannot produce the intended effect of flowing next to the content.This PRs CSS only solution
When trying out this markup change, I noticed it would cascade into too many other CSS changes and associated regression risk. I preserved a simple attempt at modifying the markup on a separate branch.
So it seemed warranted to try removing the performance issue with an as minimal change as possible while only changing the visual appearance for the better (i.e. it does the same except when the previous behavior was unintended, like the behavior near the bottom of the page).
The "trick":
#toc
absolutely, to allow putting it next to the contentPerformance improvement
The following screenshot compares performance during scrolling on the /spaces pages, before and after these changes. Both are on desktop, with no CPU throttling, so the improvement on lower end devices will be much greater.