For a whole page, use animation-timeline: scroll(root) on a fixed bar. This demo uses a named timeline (--reading) on a scroll container so it works inside a box.
The JS block only runs where CSS scroll timelines aren't supported, so modern browsers do all the work off the main thread.
Background: Scroll-driven animations with zero JavaScript.