scroll-behavior: smooth 必须写在 html 元素上才生效,body 上无效;仅对原生锚点跳转和 scrollintoview() 有效,不支持 ie,safari 15.4+ 及主流现代浏览器可用。

scroll-behavior: smooth 必须写在 html 元素上
直接加在 body 上无效,这是最容易踩的坑。浏览器只认 html 根元素的 scroll-behavior 声明,body 或其他容器设了也白设。
生效范围仅限原生锚点跳转(如 <a href="#section1"></a>)和 element.scrollIntoView();window.scrollTo() 默认不走这个行为,除非显式传 { behavior: 'smooth' }。
- IE 完全不支持,Edge 79+、Chrome 61+、Firefox 68+、Safari 15.4+ 可用
- 若页面用了
transform或perspective,可能意外禁用平滑滚动 - 不要和
overflow: hidden同时作用于html,会冲突
window.scrollTo() 加 { behavior: 'smooth' } 的兼容性陷阱
这个 API 在 Safari 15.4+ 才开始支持,老版本 Safari 会静默忽略 behavior 参数,直接硬跳。安卓 WebView 表现也不稳定,部分机型会卡顿或跳过动画。
建议加上降级逻辑:
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
document.getElementById('back-to-top').addEventListener('click', () => {
if ('scrollBehavior' in document.documentElement.style) {
window.scrollTo({ top: 0, behavior: 'smooth' });
} else {
window.scrollTo(0, 0); // fallback to instant
}
});
- 别在滚动中反复触发,比如监听
scroll事件里调用它,容易引发渲染抖动 - 避免和
requestAnimationFrame混用,除非你明确控制帧节奏 - 若需精确控制滚动终点(比如避开固定 header),得手动计算
top偏移量
滚动触发动画:用 IntersectionObserver 替代 scroll 事件监听
监听 scroll 事件做“滚动到某位置加样式”看似简单,但主线程压力大、易卡顿,尤其在低端设备上。现代方案是用 IntersectionObserver,它在渲染线程外运行,不阻塞页面。
例如让某个 <div class="fade-in"> 进入视口时淡入:
<pre class="brush:php;toolbar:false;">const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('active');
observer.unobserve(entry.target); // 用完即停,避免重复触发
}
});
}, { threshold: 0.1 });
document.querySelectorAll('.fade-in').forEach(el => observer.observe(el));</pre>
<ul>
<li>
<code>threshold: 0.1 表示元素 10% 进入视口就触发,不是非要完全可见
intersection-observer npm 包)scrollReveal.js 更轻量,无需额外库,原生 API 即可覆盖大部分场景自定义滚动动画必须绕开 marquee 标签
<marquee></marquee> 是废弃标签,所有现代浏览器都已弃用,且无法控制缓动、暂停、响应式宽度等基本需求。它生成的滚动有明显空白间隙、速度不可调、无法与 CSS 动画协同。
真正可用的方案是 CSS @keyframes + transform: translateX(),配合精确宽度计算:
@keyframes scroll-left {
0% { transform: translateX(100%); }
100% { transform: translateX(-100%); }
}
.scrolling-text {
animation: scroll-left 20s linear infinite;
white-space: nowrap;
}
- 关键点:动画位移距离必须等于内容实际宽度(不是父容器宽度),否则会露白
- 用
transform而非left,保证 GPU 加速,避免重排 - 若内容动态加载,需在 DOM 更新后重新测量并重设动画 duration
scroll 监听、频繁 class 切换、或未节流的尺寸计算,就会立刻拖慢主线程。真正稳定的方案,永远是优先用原生机制(scroll-behavior、IntersectionObserver),再补 JS 控制细节。










