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

如何实现点击子Div后平滑滚动居中并展开占满父容器?

问题描述

我有1个父div和4个子div,4个子div默认均分父容器空间;点击任意子div时,该子div要展开占满父容器,同时父容器变为可水平滚动状态。现在的问题是点击后子div无法平滑滚动到屏幕中心并吸附居中,之前用scrollIntoView方法没生效。

解决方案

问题核心是先执行滚动再修改布局,导致滚动计算基于旧的元素尺寸,同时scrollIntoView的执行时机没跟上DOM布局更新。以下是修复方案:

关键修复点

  1. 调整执行顺序:先给目标子元素添加active类更新布局,再等待DOM重绘完成后执行滚动操作
  2. 修正flex属性:避免flex-grow导致的布局异常,确保激活的子元素固定占满父容器宽度
  3. 全局滚动吸附:给所有子元素添加滚动吸附规则,提升交互一致性

修改后的完整代码

JavaScript

const items = document.querySelectorAll(".wrapper");

items.forEach((item) => {
  item.addEventListener("click", () => {
    // 单选逻辑:移除其他子元素的active类
    items.forEach(i => i.classList.remove("active"));
    // 给当前点击的子元素添加active类,触发布局更新
    item.classList.add("active");
    
    // 等待DOM重绘完成后执行滚动,确保基于新布局计算位置
    requestAnimationFrame(() => {
      item.scrollIntoView({
        behavior: "smooth",
        block: "center",
        inline: "center"
      });
    });
  });
});

CSS

.container-selection {
  display: flex;
  flex-direction: row;
  justify-content: space-evenly;
  align-items: center;
  min-height: calc(100% - var(--l-footer-height) - 5.5rem);
  padding-top: 1rem;
  padding-bottom: 1rem;
  gap: 1rem;
  padding-inline: 1rem;
  overflow-x: scroll;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
}

.container-selection .selection {
  display: flex;
  flex: 1 1 0;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  align-self: stretch;
  border-radius: 1.5rem;
  font-weight: bold;
  gap: 1rem;
  min-width: calc(25vw - 2rem);
  user-select: none;
  -moz-user-select: none;
  -webkit-user-select: none;
  transition: flex 0.3s ease;
}

.container-selection::-webkit-scrollbar {
  display: none;
}

.wrapper {
  display: flex;
  align-self: stretch;
  flex: 1 1 0; /* 默认均分父容器空间 */
  scroll-snap-align: center; /* 默认支持滚动吸附 */
  transition: all 300ms ease;
}

.wrapper.active {
  flex: 0 0 100%; /* 固定占满父容器宽度,避免flex-grow异常 */
  scroll-snap-align: center; /* 激活后依然保持滚动吸附 */
}

HTML

<div class="container-selection">
  <div class="wrapper">
    <div class="selection glass" id="admin">
      <img src="<?= ADMIN_ICON ?>" alt="admin icon">
      <span>ADMIN</span>
    </div>
  </div>
  <div class="wrapper">
    <div class="selection glass" id="official">
      <img src="<?= OFFICIAL_ICON ?>" alt="official icon">
      <span>OFFICIAL</span>
    </div>
  </div>
  <div class="wrapper">
    <div class="selection glass" id="faculty">
      <img src="<?= FACULTY_ICON ?>" alt="faculty icon">
      <span>FACULTY</span>
    </div>
  </div>
  <div class="wrapper">
    <div class="selection glass" id="nonteaching">
      <img src="<?= NONTEACHING_ICON ?>" alt="nonteaching icon">
      <span>NON-TEACHING</span>
    </div>
  </div>
</div>

原理说明

  • requestAnimationFrame:等待浏览器完成下一帧重绘后执行滚动,此时.wrapper.active的新尺寸已经生效,scrollIntoView能计算出正确的滚动位置
  • flex: 0 0 100%:固定激活子元素的宽度为父容器100%,避免flex-grow导致父容器宽度被额外撑开,保证滚动逻辑正常
  • 全局scroll-snap-align: center:无论子元素是否激活,都能在滚动时自动吸附到容器中心,提升交互流畅度

内容的提问来源于stack exchange,提问作者John Lee Ingua

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 07:45:12