如何在上方内容展开时保持目标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
相关产品推荐
相关产品推荐

