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

如何在上方内容展开时保持目标Div固定在窗口顶部?

我来帮你搞定这个弹跳问题!核心原因是你之前的滚动逻辑和CSS高度过渡不同步——当点击关闭按钮时,上方的div从高度0恢复到原始尺寸,会把之前打开的div往下挤,而你的滚动动画是直接跳转到div初始状态的位置,就出现了先下移再滚动回顶部的弹跳效果。下面给你两种完美解决的方案:

方案一:用requestAnimationFrame实时同步滚动位置

这个方法会在CSS过渡的1秒内,持续更新页面的滚动位置,确保之前打开的div始终贴在视口顶部,完全匹配过渡动画的节奏,不会有任何弹跳。

完整代码

HTML

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div></div>
<div></div>
<div></div>
<div></div>
<button>close</button>

CSS

html, body {height:100%; padding:0; margin:0;}
div {height:25%; transition:height 1s;}
div.open {height:400px;}
div.close {height:0;}
div:nth-of-type(1) {background:red;}
div:nth-of-type(2) {background:blue;}
div:nth-of-type(3) {background:green;}
div:nth-of-type(4) {background:yellow;}
button { margin-bottom:100%;}

JavaScript

var activeDiv;
$('div').click(function() {
    $(this).addClass('open');
    $('div').not(this).addClass('close');
    activeDiv = this; // 记录当前被打开的div
});

$('button').click(function(){
    const $active = $(activeDiv);
    // 先检查目标div是否已经在视口顶部,是的话直接恢复即可
    if ($active.offset().top - $(window).scrollTop() === 0) {
        $('div').removeClass('open close');
        return;
    }

    // 开始触发所有div的高度恢复过渡
    $('div').removeClass('open close');
    
    // 用requestAnimationFrame在过渡期间实时调整滚动位置
    const startTime = performance.now();
    function syncScroll(currentTime) {
        const elapsedTime = currentTime - startTime;
        if (elapsedTime < 1000) { // 和CSS过渡的1秒时长保持一致
            // 让滚动位置始终等于目标div的顶部位置
            $(window).scrollTop($active.offset().top);
            requestAnimationFrame(syncScroll);
        } else {
            // 过渡结束后再确认一次位置,确保完全对齐
            $(window).scrollTop($active.offset().top);
        }
    }
    requestAnimationFrame(syncScroll);
});
方案二:临时固定目标div的位置

这个方法更简单,在过渡期间把之前打开的div设置为固定定位,让它死死钉在视口顶部,等所有div的高度过渡完成后,再取消固定定位并调整滚动位置到它的最终位置。

修改后的核心代码

新增CSS

div.fixed-top {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 1;
}

修改后的JavaScript

var activeDiv;
$('div').click(function() {
    $(this).addClass('open');
    $('div').not(this).addClass('close');
    activeDiv = this;
});

$('button').click(function(){
    const $active = $(activeDiv);
    // 计算过渡完成后,目标div的最终位置(从400px恢复到25%高度的偏移量)
    const finalScrollPos = $active.offset().top + ($active.height() - 400);
    
    // 给目标div添加固定定位,让它留在顶部
    $active.addClass('fixed-top');
    
    // 触发所有div的高度恢复过渡
    $('div').removeClass('open close');
    
    // 监听过渡结束事件,完成后清理并调整滚动位置
    $active.one('transitionend', function() {
        $active.removeClass('fixed-top');
        $('html, body').scrollTop(finalScrollPos);
    });
});

为什么原来的方法会失效?

你之前获取的divPos是点击div时的初始位置,但当点击关闭按钮后,上方的div会从高度0恢复到25%,这个过程会把目标div向下挤压,导致页面先出现div下移,然后你的滚动动画才开始生效,最终就出现了明显的弹跳。上面的两种方法都是让滚动/定位逻辑和CSS过渡完全同步,从根源上解决了这个问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:57:44