-
Notifications
You must be signed in to change notification settings - Fork 267
Scroll Timing API proposal #1222
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
Scroll Timing API proposal #1222
Conversation
|
Can you add "Authors" and "Participate" sections? https://github.com/w3ctag/explainer-explainer/blob/main/template.md |
…ructured table of contents; outline goals and non-goals for the Scroll Timing Performance API.
…I and clarify accessibility, internationalization, privacy, and security considerations.
…demo.html and polyfill.js
…sers in demo.html
…when API is ready
Done. See latest iteration. Scroll Timing Performance APIA proposal to standardize scroll performance measurement on the web. Authors
Participate |
PerformanceScrollTiming/explainer.md
Outdated
| readonly attribute DOMHighResTimeStamp duration; | ||
| readonly attribute unsigned long framesExpected; | ||
| readonly attribute unsigned long framesProduced; | ||
| readonly attribute double checkerboardTime; |
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.
Why not DOMHighResTimeStamp for checkerboardTime so that the unit (ms) is baked into the type?
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.
Right. Updated.
PerformanceScrollTiming/explainer.md
Outdated
| readonly attribute long distanceX; | ||
| readonly attribute long distanceY; |
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.
NIT on naming - 'distance' implies a non-negative number. What about deltaX like the wheel event, or scrollX?
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.
Makes sense. Updated.
PerformanceScrollTiming/explainer.md
Outdated
| interface PerformanceScrollTiming : PerformanceEntry { | ||
| // Inherited from PerformanceEntry | ||
| readonly attribute DOMString entryType; // Always "scroll" | ||
| readonly attribute DOMString name; // Empty string |
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.
Based on the name values returned by other sub-classes of PerformanceEntry, it sounds like "scroll" would be more appropriate than an empty string.
https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry/name
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.
Makes sense. It is only set empty for LargestContentfulPaint. Perhaps if we will have different scroll metrics that can be produced we would need different name. I'll set it to scroll.
PerformanceScrollTiming/explainer.md
Outdated
| |-----------|------|-------------| | ||
| | `entryType` | DOMString | Always `"scroll"` (inherited from PerformanceEntry) | | ||
| | `name` | DOMString | Empty string (inherited from PerformanceEntry) | | ||
| | `startTime` | DOMHighResTimeStamp | Timestamp of the first input event that initiated the scroll | |
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.
I'm assuming here, but I would guess "or 0 for programmatic invocation" is the intention? If so, consider adding that as a callout if you don't think it's makes it too long.
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.
My thinking was the startTime for programmatic scrolls should be the timestamp of the scroll invocation (e.g. time of scrollTo call).
Updated the description.
| | `checkerboardTime` | double | Total duration (ms) that unpainted areas were visible during scroll | | ||
| | `distanceX` | long | Horizontal scroll distance in pixels (positive = right, negative = left) | | ||
| | `distanceY` | long | Vertical scroll distance in pixels (positive = down, negative = up) | | ||
| | `scrollSource` | DOMString | Input method: `"touch"`, `"wheel"`, `"keyboard"`, `"other"`, or `"programmatic"` | |
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.
Mostly just curious, but what value gets used when scrolling to a header, via a # in the URL?
I'm thinking primarily about the typical table-of-contents pattern where the user might click on a link and get scrolled down the page - would it make sense to make "mouse" an option for that, rather than "other", given the widespread usage of that design pattern? And if they did it via keyboard would it come through as "keyboard"? (I ask this one more from glancing in the polyfill and seeing a listed subset of keys that doesn't include things like 'enter').
Related - if tabbing through items on a page, will that go down as "keyboard"?
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.
Good questions. I have not considered these scenarios yet. Updated the "open questions section".
| | `name` | DOMString | Empty string (inherited from PerformanceEntry) | | ||
| | `startTime` | DOMHighResTimeStamp | Timestamp of the first input event that initiated the scroll | | ||
| | `firstFrameTime` | DOMHighResTimeStamp | Timestamp when the first visual frame reflecting the scroll was presented | | ||
| | `duration` | DOMHighResTimeStamp | Total scroll duration from `startTime` until scrolling stops (includes momentum/inertia) | |
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.
And if startTime is 0 for programmatic invocations, what about duration being based on firstFrameTime instead? If devs want to include the initial lag time as well they can check for a non-zero startTime and then add the firstFrameTime - startTime diff.
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.
Updated the description.
| - **Keyboard/wheel scrolls**: Usually lower, more consistent velocity with discrete steps | ||
| - **Programmatic scrolls**: Smooth scroll behavior produces predictable, constant velocity | ||
| - **Search navigation**: Users jumping to search results often produce short-duration, high-velocity scrolls | ||
|
|
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.
It's worth mentioning scrollbar scrolls, they produce the most checkerboarding, according to Chromium metrics.
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.
It's worth mentioning scrollbar scrolls, they produce the most checkerboarding, according to Chromium metrics.
Added a bullet capturing this.
| readonly attribute DOMHighResTimeStamp startTime; | ||
| readonly attribute DOMHighResTimeStamp firstFrameTime; | ||
| readonly attribute DOMHighResTimeStamp duration; | ||
| readonly attribute unsigned long framesExpected; |
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.
Smoothness metrics, such as framesExpected, framesProduced, and checkerboardTime, provide meaningful measurements of smoothness across various animations and interactions scenarios, including scroll-driven animations and JavaScript/CSS-based animations. While implementing a full Animation Smoothness API is not the immediate goal, introducing these metrics is a significant step toward measuring key aspects of animation performance and user-perceived smoothness.
I’m curious if you’ve considered separating generic smoothness attributes from PerformanceScrollTiming into a distinct interface. This approach allows us to address immediate needs while laying the groundwork for potential future API development.
interface AnimationSmoothnessEntry : PerformanceEntry {
readonly attribute unsigned long framesExpected;
readonly attribute unsigned long framesProduced;
readonly attribute double checkerboardTime;
}
interface PerformanceScrollTiming : AnimationSmoothnessEntry {
...
}
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.
Good idea. If there is a consensus that the path for Animation Smoothness API will include something like this then it certainly reasonable to structure it like this.
There is still an orthogonal open question on what expectedFrame should mean. In my prototype I measure the v-sync rate and use that as the expected so if the frame rate changes the expected changes as well. However, it may be that it makes more sense to decide on a constant smoothness frame rate (e.g. 60 FPS) and use that to calculate the expectedFrames value.
I can update to the proposal
| | `checkerboardTime` | double | Total duration (ms) that unpainted areas were visible during scroll | | ||
| | `distanceX` | long | Horizontal scroll distance in pixels (positive = right, negative = left) | | ||
| | `distanceY` | long | Vertical scroll distance in pixels (positive = down, negative = up) | | ||
| | `scrollSource` | DOMString | Input method: `"touch"`, `"wheel"`, `"keyboard"`, `"other"`, or `"programmatic"` | |
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.
I think the API should be able to report scrollbar scrolls, as they are the most common source of checkerboarding.
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.
This is indeed my preference. Some feedback that was raised is that providing explicit "scrollbar" (or perhaps "trackpad", "autoscroll" etc.) might be a privacy concern since it exposed more information than currently is exposed. To mitigate this upfront I grouped all of them to the "other" since that does not expose any additional information that wasn't existing before. We should have a discussion about this concern and perhaps can think of mitigations which will alleviate the privacy concern.
Expanded description in the open questions "Scrollbar as a Distinct Scroll Source" section capturing this.
…ibute description to indicate it always returns "scroll"
…ormanceScrollTiming interface
…d focus-driven scrolling
…alue, addressing privacy concerns and diagnostic value.
…X/deltaY across documentation and implementation for consistency in the PerformanceScrollTiming API.
…face to specify it always returns "scroll"
Initial proposal for performance Scroll Timing API.
Besides the short explainer, included also design notes document, open question document and a demo with polyfill.