
本文介绍一种纯 CSS 方案,通过将导航栏设为 sticky 定位、主体内容交由 body 原生滚动,实现「鼠标位于页面任意位置时滚轮均可平滑滚动主内容区」的效果,同时保留锚点跳转的 smooth scroll 行为,完全规避 JavaScript 事件劫持导致的卡顿问题。
本文介绍一种纯 CSS 方案,通过将导航栏设为 sticky 定位、主体内容交由 body 原生滚动,实现「鼠标位于页面任意位置时滚轮均可平滑滚动主内容区」的效果,同时保留锚点跳转的 smooth scroll 行为,完全规避 JavaScript 事件劫持导致的卡顿问题。
在构建响应式开发者作品集网站时,常见的双栏布局(左侧导航 + 右侧长内容)容易陷入一个交互陷阱:当右侧内容区设置 overflow-y: auto 后,浏览器默认仅在鼠标悬停其上时响应滚轮——这违背了用户对全页滚动的直觉预期。你可能尝试用 JavaScript 监听全局 wheel 事件并手动控制 .scrollSection.scrollTop,但正如你所遇到的,这种方式会绕过浏览器原生滚动引擎,导致动画失真、scroll-behavior: smooth 失效,且需额外处理方向判断、加速度、惯性等复杂逻辑。
根本解法是回归语义化布局与原生滚动机制:放弃「让子容器滚动」,改为「让整个文档自然滚动」,并通过 CSS 定位让导航栏始终可见。
✅ 推荐方案:Grid + Sticky 导航 + 全局平滑滚动
/* 启用全站锚点平滑滚动 */
html {
scroll-behavior: smooth;
}
/* 使用 grid 实现双栏,避免 flex 高度限制导致的滚动失效 */
body {
margin: 1em 10%;
display: grid;
grid-template-columns: 1fr 2fr; /* 左右比例可调 */
gap: 1em;
min-height: 100vh; /* 确保内容不足时仍占满视口 */
}
/* 导航栏:使用 sticky 定位,脱离文档流但随滚动固定 */
nav {
background-color: antiquewhite;
padding: 1em;
border-radius: 8px;
}
nav > div {
position: sticky;
top: 1em; /* 距离视口顶部的偏移量 */
max-height: calc(100vh - 2em); /* 防止过长时溢出 */
overflow-y: auto; /* 导航项过多时自身可滚动 */
display: flex;
flex-direction: column;
gap: 0.5em;
}
/* 主内容区:作为普通文档流元素,由 body 自然承载滚动 */
main {
background-color: #f5f5f5;
}
/* 各锚点区块:高度自定义,添加间距提升可读性 */
#about,
#experience,
#projects {
height: 500px;
background-color: silver;
padding: 1.5em;
margin: 1em 0;
border-radius: 6px;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}<nav>
<div>
<a href="#about">ABOUT</a>
<a href="#experience">EXPERIENCE</a>
<a href="#projects">PROJECTS</a>
</div>
</nav>
<main>
<div id="about">
<h1>About</h1>
<p>Your bio and introduction here...</p><div class="aritcle_card flexRow">
<div class="artcardd flexRow">
<a class="aritcle_card_img" href="/xiazai/skill11083" title="Java调试"><img
src="https://img.php.cn/upload/skill/001/246/273/6adaf20dbae7c507.jpg" alt="Java调试" ></a>
<div class="aritcle_card_info flexColumn">
<a href="/xiazai/skill11083" title="Java调试">Java调试</a>
<p>通过 JDWP 实现 Java 远程调试:连接远程 JVM、设置断点、单步执行代码、查看变量值、获取调用栈。适用于需要调试远程 Java 应用、排查运行时状态、追踪代码执行流程的场景。
术语注解
JDWP:Java Debug Wire Protocol,Java 调试有线协议(Java 远程调试底层通信协议)
remote JVM:远程 Java 虚拟机
step through code:代码单步调试(步入 / 步过 / 步出调试)
inspect variables:变量查看 / 变量检视
stac</p>
</div>
<a href="/xiazai/skill11083" title="Java调试" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
</div>
</div><p><span>立即学习</span>“<a href="https://pan.quark.cn/s/c1c2c2ed740f" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">Java免费学习笔记(深入)</a>”;</p>
</div>
<div id="experience">
<h1>Experience</h1>
<p>Work history and skills...</p>
</div>
<div id="projects">
<h1>Projects</h1>
<p>Code samples and case studies...</p>
</div>
</main>⚠️ 关键注意事项
-
不要给
body设置height: 100vh或overflow: hidden:这是导致子容器被迫滚动的根本原因。让 body 自然包裹内容,滚动即生效。 -
慎用
position: fixed:它会完全脱离文档流,可能导致导航栏遮挡锚点目标(如#about被盖住)。sticky是更安全的选择——它在滚动中保持定位,且不影响下方元素布局。 -
移动端适配建议:在小屏幕下可改用
flex-column布局,并为nav > div添加position: relative避免 sticky 失效;或使用媒体查询切换为汉堡菜单。 -
无障碍支持:此方案天然支持键盘
Tab导航和屏幕阅读器,而 JS 滚动劫持常破坏焦点管理。
该方案零 JavaScript、零运行时开销、完美继承浏览器滚动优化(包括 macOS 的惯性、触控板平滑度、scroll-behavior),且代码简洁、可维护性强。当你需要“让整个页面听从一次滚动指令”时,优先信任浏览器原生能力,而非覆盖它。

















