`StickyStack` 中的关键双针布局冲突以及 `HorizontalPan` 中的减少运动内容锁定
作者: codeCraft-Ritik创建于 2026年9月12日更新于 2026年9月12日
1. CSS position: sticky vs. GSAP pin: true Collision (StickyStack)
在 StickyStack 中,JSX 元素具有 className="stack-card sticky top-0 ...",而 useEffect 配置如下:
ScrollTrigger.create({
trigger: card,
start: "top top",
endTrigger: cardEls[cardEls.length - 1],
end: "top top",
pin: true,
pinSpacing: false,
});
- 问题: ScrollTrigger 通过应用
position: fixed实现锁定。将 CSSposition: sticky(sticky top-0)与 ScrollTrigger 的pin: true相混合会导致浏览器的原生合成器和 GSAP 的滚动引擎在每次滚动时竞争元素的定位。 - 官方 GSAP 指导: GreenSock 明确指出: "不要将 CSS position: sticky 套用到正在由 ScrollTrigger 锁定的元素上。"
- 症状: 严重的滚动抖动、视觉抖动和逆向滚动时的坐标计算错误。
2. 减少运动永久性内容不可访问性 (HorizontalPan)
在 HorizontalPan 中:
export function HorizontalPan({ children }: { children: React.ReactNode }) {
const wrap = useRef<HTMLDivElement>(null);
const track = useRef<HTMLDivElement>(null);
const reduce = useReducedMotion();
useEffect(() => {
if (reduce || !wrap.current || !track.current) return;
// GSAP ScrollTrigger 设置...
}, [reduce]);
return (
<section ref={wrap} className="relative overflow-hidden">
<div ref={track} className="flex h-[100dvh] items-center">
{children}
</div>
</section>
);
}
- 问题: 当用户在操作系统级别启用
prefers-reduced-motion: reduce时,useReducedMotion()会返回true并跳过 GSAP 初始化。然而,<section>会无条件保持overflow-hidden。 - 症状(WCAG 2.1 失败): 没有滚动条或 CSS 替代方案。所有超出初始屏幕宽度的卡片/面板永远被切断,无法访问。
3. 过时的闭包和破坏的调整 (HorizontalPan)
const distance = track.current!.scrollWidth - window.innerWidth;仅在初始安装时被求值一次。x: -distance和end: () => +=${distance}绑定该静态整数。- 在窗口大小调整或字体/资源加载时,
invalidateOnRefresh: true…
内容来源: Leonxlnx/taste-skill