Repository navigation
Drawing between pixels by default, gliding boxes, zoomed pages, and a measured comparison - #14
Merged
Merged
Conversation
amitnarwalofficial
approved these changes
Oct 23, 2026
Drawing between pixels is on by default and scrolling boxes glide by default (see CHANGELOG.md). - Svifa chooses the blocks that scroll with the content and gives each a layer of its own, split around fixed elements and z-indexes that reach past a block. Where a layer would change what is drawn over what, it draws on whole pixels and says why once in the console. `data-svifa-subpixel="off"` and `subpixel: false` turn it off. - Scrolling boxes inside the scroller glide with the same feel and hand the wheel on at their end. `nested: 'native'` leaves them to the browser and a function decides for each box. While the page glides, a box's content moves with it exactly. - Zoomed to a part of a pixel (a browser zoom such as 80% or a screen scale such as 125%), the page and its boxes are drawn from where the browser draws the scroll position, so a glide no longer shimmers. The position Svifa reports is unchanged. - Drawn on whole pixels, a glide keeps an even pace to its end. - A glide drawn between pixels never runs past the end of the page, and in Firefox the wheel over a textarea stays with the textarea. - Tests for something only some engines have are tagged and run only there; none is reported skipped. Signed-off-by: Amit Narwal <amit@arcwright.studio>
arcwrightstudio
force-pushed
the
whole-pixel-ending
branch
from
October 23, 2026 05:56
d9abe3f to
7ea7e6c
Compare
amitnarwalofficial
previously approved these changes
Oct 23, 2026
- The README compares Svifa with the most used smooth scroll libraries, measured on the same page: the end of a glide recorded from a 254 Hz screen in Chrome, Edge, Firefox and WebKit, and what each does with sticky elements, find in page, scroll-driven animations, scrolling boxes, snapping, same-page links, reduced motion, the keyboard, size and dependencies. - Before the browser shows which places it keeps, a glide drawn between pixels at 125% could report a position just past where it was sent; once the browser shows it keeps whole CSS pixels, a glide already past the place it then aims at is held there. - Drawn on whole pixels at such a scale, a glide could take its last pixel early; until the browser shows its grid, it rests only once it is on its last pixel on both grids. - The property tests also run at a device scale of 1.25, and each case they found is a test of its own. Signed-off-by: Amit Narwal <amit@arcwright.studio>
amitnarwalofficial
approved these changes
Oct 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Drawing between pixels is on by default and scrolling boxes glide by default (see CHANGELOG.md), with a measured comparison in the README.
data-svifa-subpixel="off"andsubpixel: falseturn it off.nested: 'native'leaves them to the browser and a function decides for each box. While the page glides, a box's content moves with it exactly.