双列滚动时文本列到底后固定、图片列可继续滚动的实现问题
这个效果可以实现,有纯CSS和JS两种方案,分别适配不同场景:
方案1:纯CSS实现(适合内容高度固定场景)
你之前sticky定位不生效的核心原因是:sticky元素的滚动活动范围由它的直接父元素高度决定,你之前直接给文本/aside加sticky的话,父元素是body,高度等于左侧更高的图片列高度,所以会等到全部内容滚动完才会移动。
正确的做法是给文本的父容器(aside)设置和左侧图片列相同的高度,再给文本元素加sticky定位,修改后的CSS代码如下:
body{ display: flex; margin: 0; } nav{ position: fixed; top: 0; left: 0; right: 0; background: #ffc3d9; height: 50px; z-index: 10; } section, aside{ margin-top: 50px; width: 50vw; } /* 新增:aside高度和左侧图片列一致,本示例左侧3个块共600px,所以设为600px */ aside { position: relative; height: 600px; } /* 新增:文本设置sticky,top值为导航高度+自定义顶部边距 */ aside p { position: sticky; top: 60px; margin: 10px; } .block{ display: block; width: 100%; height: 200px; }
HTML代码不需要做任何修改,即可实现预期效果:滚动页面时文本跟随滚动,当文本底部完全露出后,因为父容器aside已经到了高度下限,sticky元素就会停止滚动,继续下滑即可查看剩余的图片内容。
方案2:JS实现(适配内容高度动态变化场景)
如果左侧图片列高度不固定,或者文本长度是动态渲染的,可以用JS监听滚动事件动态调整文本位置:
首先新增一个CSS类:
/* 新增固定定位的类 */ .text-fixed { position: fixed; top: 60px; width: calc(50vw - 20px); /* 减去p的左右margin */ }
JS代码如下:
const aside = document.querySelector('aside') const text = aside.querySelector('p') const navHeight = 50 const textMargin = 10 // 计算文本滚动停止的阈值 function calculateThreshold() { const textHeight = text.offsetHeight return text.offsetTop + textHeight - (window.innerHeight - navHeight) + textMargin } let stopThreshold = calculateThreshold() // 窗口尺寸变化时重新计算阈值 window.addEventListener('resize', () => { stopThreshold = calculateThreshold() }) window.addEventListener('scroll', () => { const scrollTop = window.scrollY if (scrollTop >= stopThreshold) { // 滚动超过阈值,文本随页面滚动逐步上移 text.classList.remove('text-fixed') text.style.transform = `translateY(${scrollTop - stopThreshold}px)` } else if (scrollTop > 0) { // 滚动未到阈值,文本固定在视口顶部 text.classList.add('text-fixed') text.style.transform = 'none' } else { // 回到页面顶部,恢复默认位置 text.classList.remove('text-fixed') text.style.transform = 'none' } })
该方案可以自动适配左右列的动态高度,不需要提前固定高度值。
内容的提问来源于stack exchange,提问作者Nathan
相关产品推荐
相关产品推荐

