You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在页面滚动至底部80%时禁止向下滚动且兼容iPhone设备?

兼容iOS的滚动限制实现方案

原有代码iOS失效原因

原有代码存在两个核心问题导致iOS设备不生效且功能不符合要求:

  1. iOS Safari 11.3之后默认将touchmove、scroll事件设为passive模式,该模式下e.preventDefault()会被系统直接忽略,必须显式声明passive: false才能正常触发阻止行为
  2. 代码直接阻止了所有触摸事件,没有区分滚动方向,会导致向上滚动也被禁用

核心实现逻辑

首先计算页面滚动进度,当页面滚动高度 + 视口高度 >= 文档总高度 * 0.8时判定到达阈值,此时仅阻止向下滚动行为,允许用户向上滚动。

原生JS(React)完整实现

useEffect(() => {
  // 滚动阈值:滚动至文档总高度的80%时触发限制
  const SCROLL_THRESHOLD = 0.8
  // 记录上一次滚动的Y轴坐标,用于判断滚动方向
  let lastYPosition = window.scrollY

  // PC端滚动事件处理
  const handleScroll = (e) => {
    const currentScrollTop = window.scrollY
    const viewportHeight = window.innerHeight
    const docFullHeight = document.documentElement.scrollHeight
    const isReachThreshold = (currentScrollTop + viewportHeight) >= docFullHeight * SCROLL_THRESHOLD
    // 方向判断:当前滚动高度大于上一次即为向下滚动
    const isScrollDown = currentScrollTop > lastYPosition

    if (isReachThreshold && isScrollDown) {
      e.preventDefault()
      return
    }
    lastYPosition = currentScrollTop
  }

  // 移动端touch事件处理,兼容iOS
  const handleTouchMove = (e) => {
    const currentTouchY = e.touches[0].clientY
    const currentScrollTop = window.scrollY
    const viewportHeight = window.innerHeight
    const docFullHeight = document.documentElement.scrollHeight
    const isReachThreshold = (currentScrollTop + viewportHeight) >= docFullHeight * SCROLL_THRESHOLD
    // 触摸场景方向判断:手指y坐标小于上一次即为向上滑,对应页面向下滚动
    const isScrollDown = currentTouchY < lastYPosition

    if (isReachThreshold && isScrollDown) {
      e.preventDefault()
    }
    lastYPosition = currentTouchY
  }

  // 绑定事件,显式声明passive: false兼容iOS
  window.addEventListener('scroll', handleScroll, { passive: false })
  window.addEventListener('touchmove', handleTouchMove, { passive: false })

  // 组件卸载时移除事件监听,避免内存泄漏
  return () => {
    window.removeEventListener('scroll', handleScroll)
    window.removeEventListener('touchmove', handleTouchMove)
  }
}, [])

注意:建议给滚动事件添加节流处理,避免频繁触发导致性能损耗。

纯CSS备选方案

如果是固定容器滚动场景,不需要动态计算阈值,可以直接用CSS实现,无兼容性问题:

/* 给滚动容器添加以下样式 */
.scroll-box {
  /* 限制容器最大可滚动高度为视口的80% */
  max-height: calc(100vh * 0.8);
  overflow-y: auto;
  /* 兼容iOS的弹性滚动效果 */
  -webkit-overflow-scrolling: touch;
}

常用工具包推荐

  • 节流工具:lodash.throttle,用于降低滚动事件触发频率,优化性能
  • 钩子工具:react-use库的useScroll钩子,可以直接获取滚动位置、滚动方向等参数,无需手动计算

内容的提问来源于stack exchange,提问作者アリ・ナディム

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 05:09:03