DO TRUNG DUNG

Interfaces / Note 05 / 2026 / 1 min read

Fixing a Reduced-Motion Hydration Bug

While testing this portfolio with prefers-reduced-motion, I found a hydration bug that left animated sections in the DOM but visually hidden.

The page was there, but the content was invisible

During release testing I opened the portfolio with prefers-reduced-motion set to reduce. Several pages still had their text in the DOM, but animated sections were left visually hidden.

The initial state and hydrated state disagreed

Some motion components started with opacity set to zero before the reduced-motion preference was known. After hydration, reduced motion disabled the animation target, but nothing explicitly returned those components to their visible state.

TSX
initial={reduceMotion ? false : { opacity: 0, y }}
animate={reduceMotion ? { opacity: 1, y: 0 } : undefined}

Reduced motion still needs a final state

The fix was not just to remove animation. Reduced-motion users still need an explicit visible end state, with zero-duration transitions where necessary.

I added it to the release check

After the fix, I added a regression test and ran every public sitemap route under reduced motion to confirm the content remained visible.