scroll-behavior属性在真机手机上无平滑滚动效果问题求助
scroll-behavior: smooth在Chrome手机模拟生效,但实际手机设备不生效 我在CSS中给html, body添加了scroll-behavior: smooth属性,在Google Chrome的手机模拟调试工具中可以实现平滑滚动效果;但在实际手机设备中加载网站时,无法呈现滑动过渡效果。
相关代码如下:
JavaScript代码
function scrollToSection(event) { if (supportsSmoothScrolling()) { return; } event.preventDefault(); const scrollToElem = document.getElementById("section"); SmoothVerticalScrolling(scrollToElem, 300, "top"); } function supportsSmoothScrolling() { const body = document.body; const scrollSave = body.style.scrollBehavior; body.style.scrollBehavior = 'smooth'; const hasSmooth = getComputedStyle(body).scrollBehavior === 'smooth'; body.style.scrollBehavior = scrollSave; return hasSmooth; }; function SmoothVerticalScrolling(element, time, position) { var eTop = element.getBoundingClientRect().top; var eAmt = eTop / 100; var curTime = 0; while (curTime <= time) { window.setTimeout(SVS_B, curTime, eAmt, position); curTime += time / 100; } } function SVS_B(eAmt, position) { if (position == "center" || position == "") window.scrollBy(0, eAmt / 2); if (position == "top") window.scrollBy(0, eAmt); }
CSS代码
html, body { scroll-behavior: smooth; overflow-y: scroll; }
HTML代码
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> <div class="container-fluid h-100 nopadding"> <div class="row h-100 nopadding"> <div class="col-lg-8 black nopadding text-center d-flex flex-column justify-content-center"> <a onclick="scrollToSection(event)" href="#more" class="more">Here is the button</a> </div> <div id="more" class="col-lg-4 white nopadding text-center d-flex flex-column align-self-center justify-content-center"> Here is the section </div> </div> </div>
注:我未添加全部页面元素,代码中的箭头代表锚点标签。
可能的原因及解决办法
1. 原生平滑滚动的检测逻辑有误
你写的supportsSmoothScrolling函数检测的是body元素的scrollBehavior,但实际上浏览器的平滑滚动是作用在根容器html(document.documentElement)上的,这会导致检测结果不准确——明明手机浏览器支持原生平滑滚动,却误判为不支持,或者反过来。
修改后的检测函数:
function supportsSmoothScrolling() { const html = document.documentElement; const scrollSave = html.style.scrollBehavior; html.style.scrollBehavior = 'smooth'; const hasSmooth = getComputedStyle(html).scrollBehavior === 'smooth'; html.style.scrollBehavior = scrollSave; return hasSmooth; };
2. 滚动容器设置冲突
你同时给html和body设置了overflow-y: scroll,部分移动浏览器会因此混淆实际的滚动容器,导致scroll-behavior无法生效。
调整CSS:
html { scroll-behavior: smooth; overflow-y: scroll; } body { overflow-y: auto; /* 让body自适应内容,避免双重滚动容器 */ }
3. 代码里的笔误(关键问题!)
你的滚动函数里写的是document.getElementById("section"),但实际要滚动到的元素ID是more,这会导致自定义滚动逻辑找不到目标元素,自然没有任何滚动效果。
修正笔误:
const scrollToElem = document.getElementById("more");
4. 锚点链接的默认行为干扰
移动浏览器中,<a>标签的默认锚点跳转可能会优先执行,哪怕你调用了event.preventDefault()。可以直接禁用默认的锚点行为,或者强化阻止逻辑:
方案一:修改href属性
<a onclick="scrollToSection(event)" href="javascript:void(0)" class="more">Here is the button</a>
方案二:增强阻止逻辑+原生滚动触发
如果检测到支持原生平滑滚动,直接用window.scrollTo触发原生效果,比依赖锚点更可靠:
function scrollToSection(event) { event.preventDefault(); event.stopPropagation(); const targetElem = document.getElementById("more"); if (supportsSmoothScrolling()) { window.scrollTo({ top: targetElem.offsetTop, behavior: 'smooth' }); return; } SmoothVerticalScrolling(targetElem, 300, "top"); }
5. 自定义滚动函数的兼容性问题
你用setTimeout循环实现的自定义滚动,在移动设备上可能因为浏览器的定时器节流、性能问题导致效果卡顿或失效。建议改用更适合浏览器动画的requestAnimationFrame:
优化后的自定义滚动函数:
function SmoothVerticalScrolling(element, duration, position) { const targetTop = element.getBoundingClientRect().top + window.pageYOffset; const startTop = window.pageYOffset; const distance = targetTop - startTop; let startTime = null; function animation(currentTime) { if (startTime === null) startTime = currentTime; const timeElapsed = currentTime - startTime; const progress = Math.min(timeElapsed / duration, 1); // 加入缓动函数,让滚动更自然 const easeProgress = progress < 0.5 ? 2 * progress * progress : 1 - Math.pow(-2 * progress + 2, 2) / 2; window.scrollTo(0, startTop + distance * easeProgress); if (timeElapsed < duration) { requestAnimationFrame(animation); } } requestAnimationFrame(animation); }
内容的提问来源于stack exchange,提问作者Bonsaï

