Web engineering

Accessible motion without taking over the scroll

How this portfolio coordinates section entrances, video seeking and reduced motion while keeping links, keyboard navigation and content available.

Accessible scroll animations begin with a complete static page. Scrolling can then reveal relationships, introduce a project capture or map a video timeline, while ordinary links, keyboard navigation and reduced-motion preferences keep working. This portfolio uses that separation: the browser owns scrolling, and a small coordinator owns when a section is ready to enter.

Quick answer

  • Render useful content before installing animation behavior.
  • Keep scroll position separate from the playback of an entrance.
  • Reveal a section after measured scrolling has settled, rather than after an arbitrary delay.
  • Keep actions usable while decorative transitions run.
  • Cancel movement when the reduced-motion preference changes.
  • Review reverse scrolling, deep links, failed media and enlarged text alongside the opening sequence.

The goal is an explanation that remains useful when the motion is absent. The selected projects still have their names, captures, notes and source links in the static document. The animation changes their introduction, not their existence.

Give scrolling one owner

There are two different questions in a scroll-led page. The first is where the visitor wants to go. The second is what the page should show at that position. Combining both into a wheel handler makes it harder to reason about interruptions: a trackpad gesture, an anchor link and a keyboard command can all compete with the same animation.

Here, ordinary document scrolling answers the first question. Links point to real section identifiers. A visitor can scroll through a long project or expand an engineering note without entering a separate navigation mode. The motion coordinator observes the result and decides when an introduction can play.

Native snapping is limited to suitable sections at larger viewport sizes. The implementation measures whether an eligible scene fits the available height. Tall scenes and enlarged text do not need to be forced into a fixed frame. Proximity snapping is assistance with alignment, not a promise that every small gesture advances exactly one section. The CSS scroll snap reference explains the distinction between proximity and mandatory snapping.

A useful boundary follows from that separation: the motion code must never need to guess what a wheel event means. It can work from the document's actual position, regardless of how that position was reached.

Treat arrival as a state

A section entering the viewport is not the same as a section arriving at its resting position. Starting an entrance during a long smooth anchor transition can use up the reveal before the visitor can inspect it. Starting after a fixed timeout creates a different problem: a short scroll and a long scroll do not finish at the same time.

The portfolio checks position across successive animation frames. After the scroll has remained stable, it looks for unplayed scenes with meaningful visible content. A fitting snap scene can report aligned arrival. A taller section can use ordinary scroll rest. This is a local implementation choice, rather than a browser-wide definition of when every animation should start.

The coordinator gives each scene a once-per-visit state. A visitor returning to an earlier project does not have to wait through its introduction again. Keyboard focus also settles the relevant scene immediately. If a link receives focus, its content must not remain behind an opaque shutter while the timeline catches up.

This approach is especially useful when a section contains a large real capture. The image is evidence. The transition can frame it, but a late reveal must not make the evidence harder to inspect.

Use different movement for different information

The engine capture opens through opposing cover panels. The covers are decorative, ignore pointer input and disappear after their finite movement. The screenshot underneath stays in the document with its alternative text and its source link.

DockLab uses a different introduction. Its workspace settles from a slight perspective angle into a readable plane. That movement introduces the relationship between the product's panels, then stops so the viewer can read the actual capture. It does not keep drifting while someone examines the terminal or remote editor.

The production results use bars with an explicit baseline. Each comparison starts from an index of 100, with the result labeled separately. A reduction in manual data entry reaches 20 on that scale; an improvement of 25 percent reaches 125. The numerical claim remains static and readable throughout. The motion reveals the magnitude without pretending the value is changing in real time.

The implementation uses finite Web Animations for these introductions. Element.animate returns an animation object, which makes cancellation part of the same control flow as creation. A particular duration is an art-direction decision; it should follow the reading task and the distance of the movement.

A video timeline is a position, not a loop

The hero's technical footage is supplied material from the portfolio. A local web-sized derivative gives it the current violet treatment. It is atmospheric footage, not a capture of a project or a performance benchmark.

On a wide screen, its time position follows the hero's bounded scroll range. Forward scrolling advances the requested time. Reverse scrolling rewinds it. The video does not autoplay, and there is no audio track to compete with the visitor's environment.

Seeking needs its own lifecycle. Metadata and usable data must be available before mapping scroll progress to a duration. A request arriving during an existing seek should not build up a queue of old positions. This implementation waits for completion and then consumes the latest scroll position. It also avoids work while the scene is offscreen or the document is hidden.

On narrow screens and with reduced motion, the poster is the deliberate composition. The text, project link and identity are the same. A media failure should produce that complete static surface, not an empty region and a loading indicator.

Handle a preference change while the page is open

Checking a preference once at startup covers only one state. A visitor can change their operating system setting while the page is already open. The existing animations, hidden pending groups and media requests need an answer at that moment too.

The portfolio listens to the media query's change event. Switching to reduced motion cancels running entrances, settles pending scenes, removes the video source and leaves the poster visible. Returning to ordinary motion does not require replaying content that the visitor has already reached. The matchMedia documentation describes the query object and its change notification.

Review failures as well as the opening

A useful review includes a fast jump to the bottom, a reverse scroll, an anchor into the middle, opening a project note and resizing after the page has loaded. Each action asks whether the document still makes sense when a scene's planned introduction is interrupted.

The same review needs a keyboard path. Tab order should follow the reading sequence, focus indicators should remain visible, and a newly focused target should become usable immediately. A sticky header needs space in anchor positioning so that the target heading does not disappear behind navigation.

Text enlargement is a separate check from a narrow viewport. A compact status row that fits a phone can still overflow when its type doubles. Allowing a row to wrap solves that problem more honestly than shrinking the label or clipping the section. The portrait, capture and heading also need to retain their relationship after the text reflows.

Automated measurements help locate overflow and missing labels. They do not decide whether the transition has a useful rhythm, or whether a screenshot remains legible at the chosen scale. Those questions require reviewing the actual surface after the behavior has settled.

Product work and technical responsibility at Legacies

I am co-founder and Technical Lead at Legacies, responsible for backend architecture, integrations and product stability. Horia Stan leads branding and product. The distinction matters here: a visual interaction has a product purpose, while its implementation still needs to preserve access, input behavior and predictable state.

DockLab is our developer workspace in beta. Its appearance in this portfolio uses an actual product capture, giving readers something concrete to inspect alongside the motion. The animation introduces the product; it should also leave room to understand what the workspace does. You can find the product and our custom development work through Legacies, or read the Legacies introduction on this site.

Frequently Asked Questions

Does accessible motion mean removing all animation?

No. The useful distinction is between motion that clarifies the content and motion that controls access to it. A finite project reveal can coexist with a complete static page, provided preference changes, keyboard input and failures are handled.

Should every section use the same reveal?

A shared timing vocabulary can make a page coherent, but identical movement can flatten differences in the content. An image reveal, a data comparison and a career record have different reading tasks and can use different introductions.

Is proximity snapping enough for one section per gesture?

No. Proximity snapping can help align suitable content, but it is not a guarantee of one section per wheel gesture. This portfolio preserves native scrolling rather than implementing a controller that promises that behavior.

Why keep a poster when the video already has a first frame?

The poster is available without waiting for video metadata, decoding or a successful media request. It also provides the intended narrow-screen and reduced-motion composition, so those states do not depend on a decoder being initialized.

About the author

Alexandru Talnaci

Full-stack and systems engineer in Bucharest. Co-founder and technical lead at Legacies, working across web applications, integrations and C++ systems.

Explore the projects behind the notes
Back to all notesSubscribe via RSS