news 2026/4/23 16:10:45

不滚动?局部滚动才高级:前端滚动区域实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
不滚动?局部滚动才高级:前端滚动区域实战指南


不滚动?局部滚动才高级:前端滚动区域实战指南

  • 页面不滚动?局部滚动才高级:前端滚动区域实战指南
    • 当整个页面“冻住”,只有部分内容在悄悄滑动
    • 滚动条的前世今生:从原生 overflow 到现代 CSS 新特性
    • 深入理解局部滚动的核心机制:容器、内容与 overflow 的三角关系
      • 1. 容器必须“限高”
      • 2. 内容必须“溢出”
      • 3. overflow 的“四小花旦”
    • CSS 实现局部滚动的多种姿势:overflow、scrollbar 样式、容器高度控制全解析
      • 姿势 1:固定高度 + overflow:auto(后台列表最爱)
      • 姿势 2:flex 剩余空间滚动(聊天窗口标配)
      • 姿势 3:横向滚动瀑布流(卡片不折行)
      • 姿势 4:隐藏滚动条但保留功能(产品经理最爱)
    • JavaScript 动态控制滚动区域:监听、定位与平滑滚动技巧
      • 1. 平滑滚动到指定元素(无需插件)
      • 2. 无限滚动(IntersectionObserver 版)
      • 3. 聊天自动底部吸附(新消息来了贴底)
      • 4. 自定义滚动条拖拽(简单粗暴版)
    • 移动端的特殊挑战:iOS 弹性滚动、安卓兼容性与触摸事件处理
      • 1. iOS 的“橡皮筋”玄学
      • 2. 安卓的“闪烁”与“回流”
      • 3. 阻止“整页回弹”的终极黑魔法
    • 性能陷阱与优化策略:滚动卡顿、重绘回流、虚拟滚动初探
      • 1. 卡成 PPT 的元凶
      • 2. 优化三板斧
      • 3. 虚拟滚动(Virtual Scroll)入门
    • 调试滚动异常的侦探手册:为什么我的局部滚动不生效?
      • 排查清单(打印出来贴显示器)
    • 实用开发技巧大放送:隐藏滚动条但保留功能、自定义滚动条样式、滚动联动交互
      • 技巧 1:滚动条“隐身”但鼠标滚轮健在
      • 技巧 2:双栏联动(左侧目录高亮,右侧内容滚)
      • 技巧 3:滚动条“渐隐”动画(逼格 +1)
    • 让滚动更聪明:结合 Intersection Observer 实现懒加载与动画触发
      • 1. 图片懒加载(前文已给),再送“背景图”懒加载:
      • 2. 滚动触发“淡入”动画(AOS 的极简替代)
      • 3. 数字滚动累加(简历里写“提升用户体验 90%”就靠它)
    • 尾声:把“滚动”做成一种体验,而不是一种功能

页面不滚动?局部滚动才高级:前端滚动区域实战指南

当整个页面“冻住”,只有部分内容在悄悄滑动

你有没有过这样的体验:打开一个后台系统,左侧菜单稳如磐石,右侧表格却像脱缰的野马,上下翻飞;或者刷着手机,顶部导航纹丝不动,商品卡片在指尖丝滑穿梭。那一刻,你突然意识到——“原来页面可以不整体滚动!”
别笑,我第一次见到这种玩法时,差点把键盘上的咖啡喷出来。整页滚动就像大排档的炒面,管饱但粗糙;局部滚动则是深夜食堂的厚蛋烧,精致、克制,还带点仪式感。今天,我们就把这块“厚蛋烧”的做法彻底拆给你看:从 CSS 的“祖传 overflow”,到 JavaScript 的“滚动劫持”,再到移动端的“弹性玄学”,甚至性能优化的“虚拟滚动”黑魔法,一个都不放过。读完这篇,你也能让页面该动的地方动,该静的地方静,老板看了都说“高级”。

滚动条的前世今生:从原生 overflow 到现代 CSS 新特性

故事要从 1998 年说起。那一年,CSS 2 规范里悄悄塞进了两个单词:overflow: auto。没人想到,这对小兄弟日后会成为网页布局的“流量担当”。
在 IE6 称王称霸的年代,我们想给div塞滚动条,只能老老实实写:

.scroll-box{width:300px;height:200px;overflow:auto;/* 超出就滚,不超出就静 */}

简单、直接,但丑得令人发指——灰灰的滚动条像没擦干净的油烟机,宽度还不可调。
后来,WebKit 内核异军突起,苹果率先在 2009 年带来-webkit-scrollbar系列私有属性,前端er 第一次尝到“自定义滚动条”的甜头:

/* 给滚动条整容 */.chat-list::-webkit-scrollbar{width:6px;}.chat-list::-webkit-scrollbar-thumb{background:linear-gradient(180deg,#ff8a00,#e52e71);border-radius:3px;}.chat-list::-webkit-scrollbar-track{background:rgba(0,0,0,0.05);}

再后来,CSS 工作组的大佬们觉得老让开发者写私有前缀太掉价,于是 CSS Scrollbars Module 横空出世,scrollbar-widthscrollbar-color走进标准:

/* Firefox 已支持 */.firefox-box{scrollbar-width:thin;/* auto | thin | none */scrollbar-color:#ff8a00 #f0f0f0;/* 滑块颜色 轨道颜色 */}

一句话总结:滚动条从“能用”到“好看”,花了整整 20 年。而我们,站在巨人的肩膀上,只需要写几行代码,就能把“油烟机”换成“北欧极简风”。

深入理解局部滚动的核心机制:容器、内容与 overflow 的三角关系

想玩局部滚动,先得搞懂“三角恋”:

  1. 容器(Container):舞台,决定“谁”可以滚。
  2. 内容(Content):演员,决定“有没有”必要滚。
  3. overflow:导演,喊 Action 的那一位。

1. 容器必须“限高”

没限高=没边界,内容再长也滚不动。
错误示范:

<divclass="parent"><divclass="child">…超长内容…</div></div><style>.parent{overflow:auto;}/* 没给高度,滚个寂寞 */</style>

正确姿势:

.parent{height:100%;/* 或者固定 300px */overflow:auto;/* 或者 scroll / hidden + JS 自定义 */}

2. 内容必须“溢出”

如果子元素身高只有 150px,而容器 300px,那滚动条会傲娇地拒绝出场。
调试小技巧:给容器加outline: 1px solid red,一眼看清边界。

3. overflow 的“四小花旦”

属性值行为描述
visible默认,溢出不剪,也不滚
hidden溢出剪掉,不滚
scroll永远显示滚动条,溢出与否都占空间
auto智能,溢出才出现滚动条,不溢出则隐身

记住口诀:“auto 最常用,scroll 做备胎,hidden 做剪裁,visible 看天意。”

CSS 实现局部滚动的多种姿势:overflow、scrollbar 样式、容器高度控制全解析

姿势 1:固定高度 + overflow:auto(后台列表最爱)

<divclass="table-wrapper"><table>…几十行 tr…</table></div>
.table-wrapper{max-height:60vh;/* 视口高度的 60%,自适应 */overflow:auto;border:1px solid #e8e8e8;}

姿势 2:flex 剩余空间滚动(聊天窗口标配)

<sectionclass="chat"><header>Header</header><mainclass="chat-list">…消息…</main><footer>Input</footer></section>
.chat{height:100vh;display:flex;flex-direction:column;}.chat-list{flex:1;/* 占据剩余高度 */overflow:auto;}

姿势 3:横向滚动瀑布流(卡片不折行)

.horizontal-scroll{white-space:nowrap;/* 强制不换行 */overflow-x:auto;scroll-snap-type:x mandatory;/* 子元素对齐 */}.horizontal-scroll .card{display:inline-block;width:260px;scroll-snap-align:start;}

姿势 4:隐藏滚动条但保留功能(产品经理最爱)

.hide-scrollbar{overflow:auto;/* 对 WebKit 生效 */&::-webkit-scrollbar{display:none;}/* 对 IE/Edge 生效 */-ms-overflow-style:none;/* 对 Firefox 生效 */scrollbar-width:none;}

一行注释写清楚:“隐藏不是砍掉,滚轮、触摸、JS 照样能用,只是颜值党不想看到那条黑杠杠。”

JavaScript 动态控制滚动区域:监听、定位与平滑滚动技巧

CSS 负责“静态造型”,JS 才是“动态灵魂”。下面直接丢给你一套“滚动组合拳”,复制就能打。

1. 平滑滚动到指定元素(无需插件)

// 传统写法,一行解千愁document.querySelector('.target').scrollIntoView({behavior:'smooth'});// 进阶:控制父容器滚动,避免整页跳functionscrollToRow(list,index){constitem=list.children[index];if(!item)return;consttop=item.offsetTop;list.scrollTo({top,behavior:'smooth'});}

2. 无限滚动(IntersectionObserver 版)

constlist=document.querySelector('.feed');constfooter=document.querySelector('.footer-sentinel');constio=newIntersectionObserver(entries=>{if(entries[0].isIntersecting){loadMore().then(newHtml=>{list.insertAdjacentHTML('beforeend',newHtml);});}},{root:list,rootMargin:'100px'});io.observe(footer);

3. 聊天自动底部吸附(新消息来了贴底)

functionkeepBottom(box){// 判断是否已贴底:距离底部 < 10pxconstisBottom=box.scrollHeight-box.scrollTop-box.clientHeight<10;if(isBottom){// 等 DOM 更新完再滚requestAnimationFrame(()=>{box.scrollTop=box.scrollHeight;});}}// 监听新消息mutObs=newMutationObserver(()=>keepBottom(box));mutObs.observe(box,{childList:true});

4. 自定义滚动条拖拽(简单粗暴版)

constthumb=scrollbar.querySelector('.thumb');lety=0,startTop=0;thumb.addEventListener('mousedown',e=>{y=e.pageY;startTop=thumb.offsetTop;document.addEventListener('mousemove',move);document.addEventListener('mouseup',up);});functionmove(e){constdelta=e.pageY-y;thumb.style.top=`${startTop+delta}px`;// 同步内容滚动constmax=container.scrollHeight-container.clientHeight;container.scrollTop=(thumb.offsetTop/(scrollbar.clientHeight-thumb.clientHeight))*max;}functionup(){document.removeEventListener('mousemove',move);document.removeEventListener('mouseup',up);}

移动端的特殊挑战:iOS 弹性滚动、安卓兼容性与触摸事件处理

1. iOS 的“橡皮筋”玄学

iOS Safari 给body加了祖传“橡皮筋”,但你要是敢把overflow:hiddenbody上一怼,整个页面瞬间变石雕。解决方案:
把滚动交给“内部容器”,并开启“弹性开关”:

.scroll-ios{overflow-y:scroll;-webkit-overflow-scrolling:touch;/* 灵魂属性 */}

注意:

  • 容器必须独立“堆叠上下文”,否则橡皮筋依旧。
  • 如果用了position:fixed遮罩,记得加@supports (-webkit-touch-callout: none)做降级,不然软键盘弹出时分分钟教你做人。

2. 安卓的“闪烁”与“回流”

部分国产安卓的 WebView 在滚动时会“闪白”,原因是背景没固定:

.scroll-android{overflow:auto;background-attachment:local;/* 关键 */}

3. 阻止“整页回弹”的终极黑魔法

// 限定滚动区域,body 禁止滚document.body.addEventListener('touchmove',e=>{if(!e.target.closest('.scroll-local')){e.preventDefault();// 让 body 稳如狗}},{passive:false});

性能陷阱与优化策略:滚动卡顿、重绘回流、虚拟滚动初探

1. 卡成 PPT 的元凶

  • 重绘:滚动条滑一次,全页面红一遍(DevTools Rendering 面板里 Paint flashing 狂闪)。
  • 回流:改了元素宽高,浏览器重新计算位置。
  • 图片解码:几千张头像同时加载,主线程直接罢工。

2. 优化三板斧

  1. 合成层升级:will-change: transform把元素抬进 GPU 独立图层,减少重绘。
  2. 防抖 + 节流:滚动监听 16ms 一次就够了,别贪心。
  3. 懒加载:下面这段“最简懒加载”拿去用,不谢。
constio=newIntersectionObserver(entries=>{entries.forEach(en=>{if(en.isIntersecting){constimg=en.target;img.src=img.dataset.src;io.unobserve(img);}});});document.querySelectorAll('img[data-src]').forEach(img=>io.observe(img));

3. 虚拟滚动(Virtual Scroll)入门

如果列表超过 1000 行,DOM 再薄也扛不住。思路:只渲染可视区域 + 上下缓冲带。
伪代码 50 行,跑通原理:

constitemHeight=48;constbuffer=5;consttotal=10000;list.addEventListener('scroll',()=>{constscrollTop=list.scrollTop;conststart=Math.floor(scrollTop/itemHeight);constend=start+Math.ceil(list.clientHeight/itemHeight);constslice=data.slice(Math.max(0,start-buffer),end+buffer);render(slice);// 只渲染 slice 这一段// 用 paddingTop/paddingBottom 撑开滚动高度list.firstElementChild.style.paddingTop=`${start*itemHeight}px`;list.lastElementChild.style.paddingBottom=`${(total-end)*itemHeight}px`;});

真要用?别重复造轮子,react-window、vue-virtual-scroller、ag-grid 都帮你封装好了,但原理必须懂,面试会考。

调试滚动异常的侦探手册:为什么我的局部滚动不生效?

排查清单(打印出来贴显示器)

  1. 容器有没有“限高”?
    getComputedStyle(box).height是不是auto
  2. 内容有没有“溢出”?
    → 加outline看一眼边界。
  3. 父级有没有transform
    transform会创建 containing block,position:fixed子元素可能“叛逃”。
  4. iOS 上滚不动?
    -webkit-overflow-scrolling: touch写了没?
  5. 安卓闪白?
    → 给滚动容器加background-color,别透明。
  6. 写了scroll-behavior: smooth却瞬移?
    → 被scrollTo({behavior:'instant'})覆盖了,检查冲突脚本。
  7. 自定义滚动条失踪?
    → 只在 WebKit 生效,Firefox 用scrollbar-color,IE 直接放弃。

实用开发技巧大放送:隐藏滚动条但保留功能、自定义滚动条样式、滚动联动交互

技巧 1:滚动条“隐身”但鼠标滚轮健在

上面已给代码,再补一句:产品经理如果非要“苹果风格”,把宽度设为 0 也能过审:

::-webkit-scrollbar{width:0!important;}

技巧 2:双栏联动(左侧目录高亮,右侧内容滚)

constheadings=content.querySelectorAll('h2');constlinks=toc.querySelectorAll('a');content.addEventListener('scroll',throttle(()=>{letcurrent='';headings.forEach(h=>{if(h.offsetTop-80<=content.scrollTop)current=h.id;});links.forEach(a=>a.classList.toggle('active',a.hash===`#${current}`));},100));

技巧 3:滚动条“渐隐”动画(逼格 +1)

.scrollbar-fade{overflow:auto;transition:scrollbar-color 0.3s;}.scrollbar-fade:not(:hover){scrollbar-color:transparent transparent;/* Firefox */}.scrollbar-fade:not(:hover)::-webkit-scrollbar-thumb{background:transparent;/* WebKit */}

让滚动更聪明:结合 Intersection Observer 实现懒加载与动画触发

1. 图片懒加载(前文已给),再送“背景图”懒加载:

<divclass="bg-lazy"data-bg="hero.jpg"></div>
constioBg=newIntersectionObserver(entries=>{entries.forEach(en=>{if(en.isIntersecting){constdiv=en.target;div.style.backgroundImage=`url(${div.dataset.bg})`;ioBg.unobserve(div);}});});document.querySelectorAll('.bg-lazy').forEach(el=>ioBg.observe(el));

2. 滚动触发“淡入”动画(AOS 的极简替代)

.fade-up{opacity:0;transform:translateY(30px);transition:0.6s;}.fade-up.visible{opacity:1;transform:translateY(0);}
constioFade=newIntersectionObserver(entries=>{entries.forEach(en=>{if(en.isIntersecting)en.target.classList.add('visible');});},{threshold:0.1});document.querySelectorAll('.fade-up').forEach(el=>ioFade.observe(el));

3. 数字滚动累加(简历里写“提升用户体验 90%”就靠它)

functioncountUp(el,target){letn=0;consttimer=setInterval(()=>{n+=Math.ceil(target/50);if(n>=target){n=target;clearInterval(timer);}el.textContent=n.toLocaleString();},16);}constioCount=newIntersectionObserver(entries=>{entries.forEach(en=>{if(en.isIntersecting){consttarget=+en.target.dataset.to;countUp(en.target,target);ioCount.unobserve(en.target);}});});document.querySelectorAll('.count-up').forEach(el=>ioCount.observe(el));

尾声:把“滚动”做成一种体验,而不是一种功能

局部滚动就像一把雕刻刀,用好了,页面层次分明、交互丝滑;用不好,卡顿、兼容、性能三座大山一起砸下来。本文从 CSS 的“祖传 overflow”讲到虚拟滚动的“黑科技”,再奉上一堆“复制可用”的代码片段,目的就是让你在面对“页面不滚动”的需求时,不再心里咯噔一下,而是嘴角上扬:“这个我熟。”
下次产品经理说“能不能让这里单独滚”,你就可以把这篇文章甩给他——不对,还是别甩,自己偷偷收藏就好。毕竟,高手向来低调,只有滚动条在悄悄发光。

欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。

推荐:DTcode7的博客首页。
一个做过前端开发的产品经理,经历过睿智产品的折磨导致脱发之后,励志要翻身农奴把歌唱,一边打入敌人内部一边持续提升自己,为我们广大开发同胞谋福祉,坚决抵制睿智产品折磨我们码农兄弟!


专栏系列(点击解锁)学习路线(点击解锁)知识定位
《微信小程序相关博客》持续更新中~结合微信官方原生框架、uniapp等小程序框架,记录请求、封装、tabbar、UI组件的学习记录和使用技巧等
《AIGC相关博客》持续更新中~AIGC、AI生产力工具的介绍,例如stable diffusion这种的AI绘画工具安装、使用、技巧等总结
《HTML网站开发相关》《前端基础入门三大核心之html相关博客》前端基础入门三大核心之html板块的内容,入坑前端或者辅助学习的必看知识
《前端基础入门三大核心之JS相关博客》前端JS是JavaScript语言在网页开发中的应用,负责实现交互效果和动态内容。它与HTML和CSS并称前端三剑客,共同构建用户界面。
通过操作DOM元素、响应事件、发起网络请求等,JS使页面能够响应用户行为,实现数据动态展示和页面流畅跳转,是现代Web开发的核心
《前端基础入门三大核心之CSS相关博客》介绍前端开发中遇到的CSS疑问和各种奇妙的CSS语法,同时收集精美的CSS效果代码,用来丰富你的web网页
《canvas绘图相关博客》Canvas是HTML5中用于绘制图形的元素,通过JavaScript及其提供的绘图API,开发者可以在网页上绘制出各种复杂的图形、动画和图像效果。Canvas提供了高度的灵活性和控制力,使得前端绘图技术更加丰富和多样化
《Vue实战相关博客》持续更新中~详细总结了常用UI库elementUI的使用技巧以及Vue的学习之旅
《python相关博客》持续更新中~Python,简洁易学的编程语言,强大到足以应对各种应用场景,是编程新手的理想选择,也是专业人士的得力工具
《sql数据库相关博客》持续更新中~SQL数据库:高效管理数据的利器,学会SQL,轻松驾驭结构化数据,解锁数据分析与挖掘的无限可能
《算法系列相关博客》持续更新中~算法与数据结构学习总结,通过JS来编写处理复杂有趣的算法问题,提升你的技术思维
《IT信息技术相关博客》持续更新中~作为信息化人员所需要掌握的底层技术,涉及软件开发、网络建设、系统维护等领域的知识
《信息化人员基础技能知识相关博客》无论你是开发、产品、实施、经理,只要是从事信息化相关行业的人员,都应该掌握这些信息化的基础知识,可以不精通但是一定要了解,避免日常工作中贻笑大方
《信息化技能面试宝典相关博客》涉及信息化相关工作基础知识和面试技巧,提升自我能力与面试通过率,扩展知识面
《前端开发习惯与小技巧相关博客》持续更新中~罗列常用的开发工具使用技巧,如 Vscode快捷键操作、Git、CMD、游览器控制台等
《photoshop相关博客》持续更新中~基础的PS学习记录,含括PPI与DPI、物理像素dp、逻辑像素dip、矢量图和位图以及帧动画等的学习总结
日常开发&办公&生产【实用工具】分享相关博客》持续更新中~分享介绍各种开发中、工作中、个人生产以及学习上的工具,丰富阅历,给大家提供处理事情的更多角度,学习了解更多的便利工具,如Fiddler抓包、办公快捷键、虚拟机VMware等工具

吾辈才疏学浅,摹写之作,恐有瑕疵。望诸君海涵赐教。望轻喷,嘤嘤嘤

非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。愿斯文对汝有所裨益,纵其简陋未及渊博,亦足以略尽绵薄之力。倘若尚存阙漏,敬请不吝斧正,俾便精进!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 11:51:58

【Linux驱动篇】LED驱动开发实验

文章目录 【Linux驱动篇】LED驱动开发实验1 简介1.1 地址映射1.1.1 ioremap函数1.1.2 iounmap函数 1.2 IO内存访问函数1.2.1 读操作函数1.2.2 写操作函数 2 硬件原理分析3 实验程序编写3.1 新建工程3.1 LED灯驱动程序编写3.2 编写测试APP3.3 编写Makefile 4 编译测试4.1 编译4.…

作者头像 李华
网站建设 2026/4/17 19:44:06

美食信息推荐系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】

摘要 随着互联网技术的快速发展和人们生活水平的不断提高&#xff0c;美食文化逐渐成为现代生活中不可或缺的一部分。美食信息推荐系统通过整合用户偏好、地理位置和菜品评价等多维度数据&#xff0c;为用户提供个性化的美食推荐服务。传统的餐饮信息管理方式存在信息更新滞后…

作者头像 李华
网站建设 2026/4/18 7:33:58

Windows内存诊断工具

Windows 内置内存诊断工具是排查内存故障时最直接、最方便的首选工具。 工具简介 Windows 内存诊断工具 是一个内置于 Windows 操作系统中的硬件检测程序。它的唯一目的就是通过向计算机的物理内存写入和读取各种数据模式&#xff0c;来检测内存条是否存在错误。 核心特点 内置…

作者头像 李华