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

如何在容器滚动时动态更新两侧渐变阴影的显示状态?

横向滚动容器渐变阴影实时更新方案

问题背景

我有一个包含5个盒子的display: flex横向滚动容器(类名boxes),可通过左右按钮控制滚动。需求是:

  • 容器左右两侧显示白色渐变阴影
  • 滚动到最左侧时,仅显示右侧阴影
  • 滚动到最右侧时,仅显示左侧阴影
  • 其余状态显示两侧阴影,且阴影需随滚动实时更新

但当前阴影固定在初始位置,滚动时不会随容器移动,甚至会出现在容器中间位置,请问该如何实现阴影的实时更新?


原方案问题分析

原代码用容器的::after伪元素做遮罩,但伪元素是绝对定位在容器的可视范围内,不会跟随滚动的内容移动,导致遮罩位置和滚动状态完全脱节。另外JS里硬编码了最大滚动值1206,一旦内容长度或容器尺寸变化,这个值就会失效,兼容性极差。


优化解决方案

核心思路

  1. 把单一遮罩拆成左右两个独立的遮罩元素,固定在容器的左右边缘,确保视觉上始终贴合视口两侧
  2. 通过滚动事件动态判断滚动状态,控制遮罩的显示/隐藏,而非修改渐变参数
  3. 动态计算最大滚动值,彻底摆脱硬编码数值的限制

完整实现代码

HTML(新增遮罩元素)

<div class="boxes">
  <!-- 原有盒子内容 -->
  <div class="box">Box 1</div>
  <div class="box">Box 2</div>
  <div class="box">Box 3</div>
  <div class="box">Box 4</div>
  <div class="box">Box 5</div>
  
  <!-- 新增左右渐变遮罩 -->
  <div class="shadow-overlay shadow-left"></div>
  <div class="shadow-overlay shadow-right"></div>
</div>

CSS(SCSS)

.boxes {
  display: flex;
  overflow-x: scroll;
  -ms-overflow-style: none;
  scrollbar-width: none;
  scroll-behavior: smooth;
  position: relative;
  padding: 0;

  &::-webkit-scrollbar {
    display: none;
  }

  .shadow-overlay {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 60px; /* 遮罩宽度可按需调整 */
    z-index: 1;
    pointer-events: none; /* 不干扰容器内的点击交互 */
    opacity: 0;
    transition: opacity 0.2s ease; /* 平滑过渡效果 */
  }

  .shadow-left {
    left: 0;
    background: linear-gradient(90deg, #fff, transparent);
  }

  .shadow-right {
    right: 0;
    background: linear-gradient(-90deg, #fff, transparent);
  }
}

JavaScript

const boxesView = document.querySelector('.boxes');
const shadowLeft = boxesView.querySelector('.shadow-left');
const shadowRight = boxesView.querySelector('.shadow-right');

// 初始化遮罩状态
updateShadows();

// 滚动时更新遮罩
boxesView.addEventListener('scroll', updateShadows);

// 窗口尺寸变化时重新计算(适配响应式场景)
window.addEventListener('resize', updateShadows);

function updateShadows() {
  // 动态计算最大滚动值:内容总宽度 - 容器可视宽度
  const maxScrollLeft = boxesView.scrollWidth - boxesView.clientWidth;
  
  if (boxesView.scrollLeft <= 0) {
    // 滚动到最左侧:隐藏左遮罩,显示右遮罩
    shadowLeft.style.opacity = '0';
    shadowRight.style.opacity = '1';
  } else if (boxesView.scrollLeft >= maxScrollLeft - 1) {
    // 滚动到最右侧:显示左遮罩,隐藏右遮罩(减1兼容滚动精度误差)
    shadowLeft.style.opacity = '1';
    shadowRight.style.opacity = '0';
  } else {
    // 中间状态:显示两侧遮罩
    shadowLeft.style.opacity = '1';
    shadowRight.style.opacity = '1';
  }
}

方案优势

  • 遮罩固定在容器边缘,不会随内容滚动偏移,视觉效果始终符合预期
  • 通过opacity控制显示状态,逻辑简洁且性能开销低
  • 动态计算最大滚动值,适配任意内容长度和容器尺寸
  • 支持窗口尺寸变化时自动更新,兼容响应式场景

内容的提问来源于stack exchange,提问作者tices

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 07:57:12