How Hallmark Handles Reduced-Motion Accessibility for Motion-Sensitive Users
Hallmark detects the prefers-reduced-motion media query on page load and conditionally disables all animated transitions, view transitions, and scroll-linked effects when users have requested reduced motion.
Hallmark is an open-source accessibility toolkit by Nutlope that helps developers build motion-aware interfaces. As implemented in the Hallmark repository, reduced-motion support is built into the core architecture rather than added as an afterthought. The framework automatically respects user preferences at both the system level and within individual demo implementations.
Detecting Reduced-Motion Preferences in Hallmark
The foundation of Hallmark's accessibility approach lives in site/js/main.js. On initialization, the script creates a persistent Boolean flag that captures the user's motion preference:
// Detect the reduced-motion preference once at startup.
const reduced = matchMedia("(prefers-reduced-motion: reduce)").matches;
This single detection at line 5 propagates throughout the entire application. By evaluating the matchMedia query immediately, Hallmark avoids repeated DOM queries and ensures consistent behavior across all subsequent motion checks.
Guarding View-Transition Animations
Modern Chromium browsers support the View Transitions API for smooth state changes. Hallmark leverages this for theme switches but only when motion is not restricted.
In site/js/main.js at lines 761-762, the applyTheme() function checks the reduced flag before invoking document.startViewTransition():
function applyTheme(theme) {
if (!THEMES[theme]) return;
const apply = () => {
root.dataset.theme = theme;
swapArchetypes(theme);
setPressed(theme);
};
// Only use View Transition if the user has NOT requested reduced motion.
if (!reduced && document.startViewTransition) {
document.startViewTransition(apply);
} else {
apply();
}
}
When reduced is true, the theme change executes instantly through the apply() callback. Users experience immediate visual feedback without the sliding, fading, or morphing effects that could trigger vestibular disorders.
Example-Level Reduced-Motion Implementation
Hallmark's demo examples demonstrate the same pattern independently. Each example script performs its own matchMedia query, ensuring self-contained accessibility even when copied or modified.
Tally Demo (site/examples/tally/app.js)
const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
The tally animation respects this flag at its source, skipping number-counting transitions when motion reduction is preferred.
Hyperlane Demo (site/examples/hyperlane/script.js)
Line 14 guards the hero entrance animation:
if (!reduced) {
// Animate hero elements into view
}
Without this check, the parallax scrolling and entrance effects would play regardless of user settings.
Cobalt Demo (site/examples/cobalt-01/script.js)
This example takes the most comprehensive approach at line 6, bypassing its entire animation system when reduceMotion is detected:
const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
if (!reduceMotion) {
// Run animated sequence…
} else {
// Fallback: static layout or instantly-shown content.
}
The pattern repeats across press-01, garden-01, custom-02, and other examples in the site/examples/ directory.
Key Implementation Files
Understanding where Hallmark implements reduced-motion accessibility helps you audit your own adaptations:
| File | Purpose |
|---|---|
site/js/main.js |
Core detection and theme transition guarding |
site/examples/tally/app.js |
Interactive tally with motion-conditional counting |
site/examples/hyperlane/script.js |
Hero animation with reduced-motion fallback |
site/examples/cobalt-01/script.js |
Complete animation bypass implementation |
site/examples/*/script.js |
Additional examples following the same pattern |
Adapting Hallmark's Pattern in Your Projects
To implement Hallmark-style reduced-motion handling in your own code:
- Detect once at initialization – Store
matchMedia("(prefers-reduced-motion: reduce)").matchesin a constant or state variable. - Guard every animation entry point – Check the flag before calling
document.startViewTransition(),requestAnimationFrame()loops, or CSS animation triggers. - Provide instantaneous fallbacks – Ensure your
elsebranches render final states immediately, not merely delayed states. - Test with actual user preferences – Enable "Reduce motion" in macOS System Settings > Accessibility or Windows Settings > Ease of Access.
This approach satisfies WCAG 2.1 Success Criterion 2.3.3 (Animation from Interactions) without requiring users to hunt for site-specific motion toggles.
Summary
- Hallmark detects reduced-motion preferences immediately via
matchMedia("(prefers-reduced-motion: reduce)")insite/js/main.js - Theme transitions use View Transitions API only when motion is permitted, falling back to instant application otherwise
- Every demo example implements independent motion guarding, making the pattern copy-paste friendly
- No configuration required – accessibility activates automatically based on user system preferences
- Consistent file structure makes Hallmark's accessibility approach auditable and teachable
Frequently Asked Questions
Does Hallmark require JavaScript for reduced-motion support?
Yes, Hallmark's reduced-motion detection depends on JavaScript's window.matchMedia() API. The framework assumes a progressive enhancement approach where base content remains accessible without scripts, but motion suppression specifically requires the detection script to run.
Can I override Hallmark's reduced-motion detection?
The reduced constant in site/js/main.js is hardcoded to the media query result. To override for testing or specific use cases, you would need to modify the source or wrap animation calls with your own conditional logic. The examples demonstrate how to add custom guards without touching core files.
Does Hallmark reduce motion for CSS animations as well?
Hallmark's JavaScript detection primarily guards programmatic animations and View Transitions. For CSS-only animations, you should pair Hallmark's script with standard media queries: @media (prefers-reduced-motion: reduce) { /* static styles */ } in your stylesheets.
Which browsers support Hallmark's reduced-motion features?
The core matchMedia detection works in all modern browsers. The document.startViewTransition() API used for theme changes requires Chromium 111+. In unsupported browsers, Hallmark's else branch ensures themes still apply instantly, maintaining accessibility across browser generations.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →