Logo

Programmable Scroll Engine

scroll-engine

This specification defines an abstract, platform-agnostic model for a one-dimensional scroll engine. It describes scroll domains, observable state, and high-level architecture, including special support for circular scroll domains suitable for storytelling and looping interfaces. The model is intended to be implementable across a variety of host environments, including web browsers, Android, iOS, and other native or embedded runtimes.

This is an unofficial draft. It is not a W3C Standard, and it has not received any formal review. The contents of this document may change at any time.

Conformance

As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.

The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL in this document are to be interpreted as described in RFC2119.

Conforming Scroll Engine Implementations

A Scroll Engine Implementation is any library, module, or component that provides logic for controlling a single scroll axis in accordance with this specification.

A conforming Scroll Engine Implementation MUST:

Conforming Scroll Engine Implementations MAY use any internal representation or underlying platform primitives, as long as the externally observable behavior conforms to this specification.

Conforming Host Environments

A Host Environment is any runtime or platform that embeds a conforming Scroll Engine Implementation and provides a visible scroll surface. Examples include web browsers, Android or iOS applications, game engines, or desktop UI toolkits.

A conforming Host Environment MUST:

  • Provide at least one scroll surface: a host-defined entity whose visible content is moved in response to changes in scroll position (for example, a DOM element, a native scroll view, or a camera transform).
  • Define how scroll positions in the scroll engine map to the scroll surface (for example, mapping canonical positions to pixel-based offsets or item indices).
  • Define how user input and lifecycle events in the host environment are translated into impulses and persistence operations for the scroll engine.
  • Integrate accessibility-related constraints and behaviors as described in Accessibility.

Introduction

Purpose

Many interactive experiences, including narrative and storytelling interfaces, require scroll behaviors that go beyond conventional bounded content scrolling. Examples include circular or looping scrolls, custom smoothness profiles, and scroll states that persist across navigations or app sessions.

This specification defines a Scroll Engine Model: an abstract description of how a one-dimensional scroll axis is represented and controlled. The model is intended to:

  • Support a variety of scroll domains, including bounded, unbounded, and circular domains.
  • Enable rich control over scroll trajectories (e.g., smoothness, easing, custom motion policies).
  • Provide a predictable basis for scroll state persistence across navigations and app sessions.
  • Be implementable across multiple platforms and UI toolkits, such as web, Android, iOS, game engines, and custom runtime environments.

Scope

This document defines the abstract data model and high-level architecture of a scroll engine. It does not define concrete API surface or language bindings for specific platforms. Instead, it is expected that separate binding specifications will define how this model maps to:

  • DOM and CSSOM View APIs in web browsers,
  • native scroll views and list views on platforms such as Android and iOS,
  • and other host-specific scroll surfaces.

This edition intentionally omits detailed algorithms for frame stepping, motion policies, input handling, plugins, and middleware. Those may be specified in future modules.

Out of Scope

The following are out of scope for this edition of the specification:

  • Detailed algorithms for animation loops, schedulers, and motion policies.
  • Concrete APIs (function signatures, classes, or IDL) for specific platforms.
  • The definition of user interface design, layout, or content structure beyond what is needed to specify scroll behavior.

Terminology

Scroll Axis

A scroll axis is a single logical dimension along which scrolling occurs. A scroll axis does not assume a particular physical direction; mapping to horizontal or vertical movement is defined by the host environment.

Scroll Position

A scroll position is a real-valued coordinate on a scroll axis.

The model distinguishes two related notions of position:

  • A canonical position is the scroll position normalized into the canonical range of the active scroll domain (for example, [min, max] for a bounded domain or [min, min + period) for circular domains).
  • A logical position is an internal representation of position that MAY differ from the canonical position by integer multiples of the domain’s period, particularly in circular domains. Logical positions are used to represent potentially unbounded motion over time.

Scroll Domain

A scroll domain describes the allowed range of scroll positions and how positions behave at or beyond the edges of that range. The kinds of scroll domains are defined in Scroll Domains.

Scroll Operation

A scroll operation is a programmatic request to change the scroll position. A scroll operation typically specifies a desired target position and possibly additional motion parameters (such as instantaneous vs. animated movement).

Impulse

An impulse is a discrete change in scroll position originating from user interaction, such as:

  • mouse wheel or trackpad scrolling,
  • touch or pen dragging gestures,
  • keyboard or keypad navigation,
  • gamepad or switch device actions.

Host environments translate such interactions into impulses that can be consumed by the scroll engine.

Origin

The origin of a position update is a tag indicating where the update came from. The following origins are defined:

  • "user": updates directly caused by user actions, such as wheel or touch input, keyboard navigation, or actions from assistive technologies.
  • "program": updates requested explicitly by application code, such as a scroll-to-section call.
  • "momentum": updates that continue motion initially caused by the user, such as inertial scrolling.

Velocity and Direction

Velocity is a measure of the change in canonical position per unit time, as observed by the scroll engine. The exact units of velocity depend on the host environment’s choice of units for positions and time.

Direction is the sign of the most recent non-zero velocity, commonly represented as:

  • -1 for movement in the decreasing direction,
  • 0 for no movement,
  • +1 for movement in the increasing direction.

Frame

A frame is a single evaluation step of the scroll engine in which it:

  • considers any pending impulses and scroll operations,
  • advances motion over time according to a motion policy, and
  • updates observable state.

Data Model

Scroll Domains

A scroll domain is categorized into one of several domain kinds. Each domain kind defines constraints on canonical positions and behavior at or beyond domain edges.

Bounded domain

A bounded domain has two parameters: min and max, with min ≤ max.

  • Canonical positions MUST be clamped to the interval [min, max].
  • Motion that attempts to move beyond min or max MUST result in a canonical position equal to the corresponding bound.
  • No wrapping occurs at either end of the domain.

End-unbounded domain

An end-unbounded domain has a single parameter: min.

  • Canonical positions MUST satisfy position ≥ min.
  • There is no upper bound. Motion that moves beyond any current content extent MAY still be represented by canonical positions greater than any previous value.

All-unbounded domain

An all-unbounded domain has no fixed bounds on canonical positions.

  • Canonical positions MAY take any real value.
  • The domain does not impose clamping or wrapping in either direction.

Circular-unbounded domain

A circular-unbounded domain has two parameters: min and a strictly positive period.

A derived value max is defined as:

max = min + period

The domain has the following semantics:

  • Canonical positions MUST lie in the half open interval [min, max).
  • Any raw position v is mapped to a canonical position c by applying modulo period into [min, max).
  • Implementations MAY maintain a logical position that differs from the canonical position by integer multiples of period in order to represent potentially unbounded motion.
  • When selecting a logical position corresponding to a canonical position, implementations SHOULD choose a value that is as close as possible to the previous logical position, minimizing apparent jumps.
  • Motion that moves beyond max in the increasing direction MUST wrap to min plus any overflow modulo period.
  • Motion that moves below min in the decreasing direction MUST wrap to max minus any underflow modulo period.

The behavior of the original implementation’s circular domain corresponds to this circular-unbounded domain: wrapping is symmetric in both directions.

Circular end-unbounded domain

A circular end-unbounded domain has the same parameters as a circular-unbounded domain: min and a strictly positive period, with max = min + period.

Canonical positions MUST lie in [min, max), but the wrapping behavior is asymmetric:

  • In the increasing direction (for example, a user scrolling “forward” or “down”), motion that moves beyond max MUST wrap to min plus any overflow modulo period. This allows repeated looping as the user continues in the increasing direction.
  • In the decreasing direction (for example, a user scrolling “backward” or “up”), motion that moves below min MUST be clamped at min. No wrap from top back to bottom occurs in this direction.

Implementations MAY maintain a logical position similarly to the circular-unbounded domain, but MUST NOT introduce wraps from top to bottom when motion proceeds in the decreasing direction.

This domain is suitable for narratives where looping is only allowed in one direction (for example, looping when scrolling down through a story, but not when scrolling back up).

Engine Observable State

A conforming Scroll Engine Implementation MUST maintain and expose at least the following observable state:

  • The current canonical position.
  • The active scroll domain and any domain parameters (such as min, max, and period).
  • The current velocity and direction, derived from changes in canonical position over time.
  • A conceptual target position, representing the position towards which the engine is currently moving. In circular domains, implementations MAY track both canonical and logical components of the target.
  • A running flag indicating whether the engine considers the scroll to be “in motion” (for example, during ongoing animation or momentum) or idle.

The concrete API shape used to expose this state is host- and language-specific, but conforming implementations MUST provide some mechanism to observe it.

Scroll State Snapshot

A Scroll State Snapshot captures the scroll engine’s position at a point in time for the purpose of persistence or restoration.

A Scroll State Snapshot MUST contain at least:

  • An ordered collection of per-axis positions, where each axis state includes a position field representing the canonical position on that axis.
  • A timestamp value, whose units are defined by the host environment (for example, milliseconds since epoch or a monotonic clock).

An abstract shape for a Scroll State Snapshot is:

{
  axes: [{ position: <number> }, ...],
  timestamp: <number>
}

Host environments MAY serialize snapshots to JSON, binary formats, or other representations suitable for their storage mechanisms.

Signals and Origins

A Scroll Engine Implementation MAY expose position updates via an observable scroll signal abstraction. A scroll signal has:

  • a current canonical position value, and
  • a set of registered listeners.

When the scroll engine updates the canonical position, it MAY notify listeners with:

  • the new canonical position, and
  • the origin of the update (user, program, or momentum).

Errors thrown by listeners MUST NOT compromise the scroll engine’s internal state or prevent further updates.

Even if a scroll signal abstraction is not used, conforming implementations MUST provide an equivalent mechanism for clients to observe position changes together with their origin.

Accessibility

General Principles

A conforming Scroll Engine Implementation and its Host Environment MUST support accessible scrolling experiences. This includes:

  • Ensuring that the user remains in control of scroll motion, and that user input can override programmatic motion.
  • Respecting platform accessibility settings, including preferences for reduced motion or similar features.
  • Supporting keyboard, keypad, switch, and other assistive input as first-class means of controlling scroll.
  • Avoiding motion that cannot be paused, stopped, or overridden by the user.

Reduced Motion and Motion Sensitivity

Host Environments MUST provide a way to propagate a user’s reduced motion preference (or equivalent) into the scroll engine.

When a reduced motion preference is active:

  • Programmatic scroll operations SHOULD be implemented as immediate position changes without animation, or use significantly simplified and shortened motion.
  • Long-running or continuous auto-scrolling behaviors SHOULD be disabled, minimized, or replaced with non-animated alternatives.

Regardless of motion preferences, the scroll engine MUST allow ongoing motion to be interrupted and overridden by user input.

Keyboard, Keypad, and Switch Input

Host Environments MUST be able to express discrete navigation commands from devices such as keyboards, keypads, gamepads, and switch controls as impulses or scroll operations.

A Scroll Engine Implementation MUST:

  • Accept these impulses in the same way as pointer-based input (such as touch or wheel events).
  • Produce predictable movements in response to such input, according to the host environment’s conventions (for example, line stepping for arrow keys, page stepping for PageUp/PageDown).

Continuous motion initiated programmatically MUST be interruptible by keyboard or assistive input. A user action SHOULD promptly adjust the target or current position to reflect the user’s intent.

Focus Navigation and Tabbing

When a focusable item becomes focused (for example, via Tab/Shift+Tab or other accessibility navigation commands), the Host Environment MAY request a scroll operation to bring the focused item into view.

A Scroll Engine Implementation MUST:

  • Support such focus-driven adjustments as regular scroll operations, using the same domain and motion semantics.
  • Avoid trapping focus by repeatedly re-scrolling in a way that prevents the user from moving focus away.

In circular domains, engines MUST NOT induce repeated loops in response to focus changes unless explicitly requested by the Host Environment.

User Override and Priority of User Input

When user-originated input conflicts with ongoing programmatic motion, user input MUST take precedence.

A Scroll Engine Implementation MUST:

  • Allow user impulses to override or modify the current target position.
  • Stop, pause, or alter ongoing motion accordingly, rather than ignoring user attempts to stop or reverse the motion.

Engines MUST NOT create non-cancelable, non-interruptible scroll loops that continue in spite of user input intended to stop or reverse them.

Platform Accessibility Integration (informative)

While this specification is host-agnostic, conforming Host Environments are expected to integrate the scroll engine with their native accessibility frameworks:

  • Web platforms can use features such as prefers-reduced-motion, ARIA practices, and keyboard focus management to drive scroll behavior.
  • Android platforms can integrate with accessibility services, focus navigation, and key event handling.
  • iOS platforms can integrate with UIAccessibility settings, VoiceOver, and focus navigation mechanisms.

In all cases, the principles defined in this section SHOULD be preserved.

Architecture Overview (informative)

This section is non-normative and describes the conceptual roles and interactions of components in a scroll engine implementation.

Component Roles

A typical system based on this specification includes the following conceptual components:

  • A Scroll Engine, which maintains the scroll axis state as described in Data Model, accepts scroll operations and impulses, and updates positions over time according to a motion policy.
  • A Scroll Surface, a host-defined entity whose visible content changes in response to scroll position (for example, a DOM element, native scroll view, or camera).
  • A Motion Policy, which defines how positions evolve over time from current to target (for example, instantaneous jumps, exponential easing, fixed-duration animations).
  • A Scheduler, which provides a notion of frames or time steps for the scroll engine (for example, display refresh, game loop, or timer-based updates).
  • A set of Input Sources, which translate host-specific input events (pointer, keyboard, accessibility commands, etc.) into impulses.
  • A Persistence Layer, which reads and writes Scroll State Snapshots to storage appropriate for the Host Environment.

Execution Flow (Conceptual)

The high-level execution flow in a system based on this model is:

  1. User input is received by the Host Environment and translated into impulses or scroll operations.
  2. The Scroll Engine updates its internal state and computes a new canonical position according to the active motion policy and scroll domain.
  3. The new canonical position is applied to the Scroll Surface using host-specific mechanisms (for example, DOM scroll offsets or native view properties).
  4. The Scroll Engine notifies observers (such as applications or persistence modules) via its observable mechanisms.
  5. Persistence modules, if present, record snapshots of scroll state at appropriate times.

Programmatic scroll operations follow a similar flow, except that the initial request originates from application code rather than user input.

At all times, user input MUST be able to override programmatic motion, as detailed in Accessibility.

Session Persistence Module (informative)

This section is non-normative and describes a typical pattern for preserving scroll position across navigations or app sessions using Scroll State Snapshots.

Goals

A session persistence module aims to preserve scroll position across:

  • navigations or screen transitions within an application,
  • lifecycle events such as backgrounding and foregrounding,
  • and other host-defined session boundaries.

The module uses Scroll State Snapshots to capture and restore positions in a deterministic manner.

Persistence Semantics

A typical persistence module:

  • Observes scroll state via the engine’s observable mechanisms and periodically or event-driven captures a Scroll State Snapshot.
  • Stores the snapshot in a host-defined storage mechanism, such as web session storage, local storage, Android bundles, or platform-specific state restoration APIs.
  • On startup or appropriate lifecycle events, reads any previously stored snapshot and applies the stored canonical position as the initial position for the scroll engine.

Restore Strategies

Two broad restore strategies are common:

  • Immediate restore: the position is seeded before the user sees the content (for example, before the first frame).
  • Deferred restore: the position is seeded after a host-defined condition such as layout stability or a timeout.

Host Environments should choose a strategy that provides a stable and predictable experience, while also respecting user preferences such as reduced motion (see Reduced Motion and Motion Sensitivity).

Host-Specific Profiles

The following examples are illustrative and not exhaustive.

  • Web profile: storage using session-scoped storage keyed by URL or route identifier; lifecycle linked to events such as pageshow and visibilitychange, and navigation APIs.
  • Android profile: storage using activity or fragment state, view models, or other Android persistence mechanisms; lifecycle linked to methods such as onSaveInstanceState, onPause, and onResume.
  • iOS profile: storage using state restoration APIs or custom persistence; lifecycle linked to controller and scene lifecycle events.

Privacy and Security Considerations

Persistence modules should respect host privacy settings and user expectations around session boundaries. Implementations should handle cases where storage is unavailable or restricted by falling back to non-persistent behavior without compromising correctness.

Integration with Host Platforms (informative)

This section sketches how the abstract model can be integrated into different environments. It does not define normative bindings.

Web Browsers

In web environments, scroll surfaces typically correspond to the window or individual scrollable DOM elements. Canonical positions map naturally to scroll offsets (such as scrollTop and scrollLeft).

Circular domains may be implemented via content duplication, virtualization, or logical repositioning while maintaining consistent canonical positions.

Persistence is often implemented via session-scoped storage and integration with history and lifecycle events.

Android

On Android, scroll surfaces can include ScrollView, RecyclerView, and custom View classes. Canonical positions may correspond to pixel offsets, item indices, or other host-defined units.

End-unbounded and circular domains may be implemented via virtualized lists, repeating adapters, or logical index wrapping while preserving the semantics defined in this specification.

Persistence can be integrated with activity and fragment lifecycles, view models, or application-level storage.

iOS

On iOS, scroll surfaces can include UIScrollView, UICollectionView, UITableView, and related components. Canonical positions typically map to contentOffset or index-based offsets.

Circular and unbounded domains can be implemented using content repetition, logical index arithmetic, or other techniques that preserve canonical positions.

Persistence can be achieved through state restoration APIs, custom storage, or app-specific mechanisms.

Other Host Environments

Other environments, such as game engines or desktop UI toolkits, can integrate the Scroll Engine Model by mapping canonical positions to camera transforms, viewport positions, or equivalent constructs.

The principles of scroll domains, observable state, accessibility, and persistence defined in this specification still apply.