为什么侧边栏布局推荐使用flex
后台管理系统的页面结构通常很固定:左边一条导航侧边栏,右边一大块内容区域。传统做法是用浮动加宽度百分比,或者绝对定位硬凑,代码写起来繁琐不说,后期调整起来也容易出问题。比如侧边栏高度想跟随内容区自动撑满,浮动方案就得靠伪元素清除加负margin这类技巧,可读性很差。

flex布局出现之后,这类问题基本迎刃而解。flex天生就是为单维方向的排列设计的,把外层容器设为display: flex之后,子元素会自动排成一行,配合flex-shrink、flex-grow等属性,固定宽度与自适应宽度的组合只需要两三行代码。更重要的是,子项的高度默认会拉伸到与容器一致,这正是侧边栏布局最需要的效果,不需要任何额外的hack。
除此之外,flex方案的语义也很清晰。看到display: flex加上width: 240px和flex: 1,任何开发者都能立刻理解这个结构是一个固定侧边栏加弹性内容区。维护成本明显低于浮动方案,这也是目前几乎所有UI框架的布局组件都基于flex实现的原因。
基础实现:固定侧边栏加自适应内容区
先看最简单的场景:左侧侧边栏固定240像素宽,右侧内容区占满剩余空间。结构上只需要一个外层容器包住两个子元素。
<div class="layout"> <aside class="sidebar">侧边栏</aside> <main class="content">内容区域</main> </div>
样式部分是关键。外层容器设置flex,侧边栏给固定宽度并且禁止收缩,内容区用flex: 1自动占据剩余空间。
.layout {
display: flex;
min-height: 100vh; /* 让布局至少撑满一屏 */
}
.sidebar {
width: 240px;
flex-shrink: 0; /* 防止侧边栏被内容挤压 */
background: #2c3e50;
color: #fff;
}
.content {
flex: 1; /* 等价于 flex-grow:1 flex-shrink:1 flex-basis:0% */
background: #f5f6f8;
padding: 20px;
}这里有一个新手常踩的坑:如果不给侧边栏设置flex-shrink: 0,当右侧内容特别宽(比如包含一个超宽的表格或代码块)时,侧边栏会被压缩变形。因为flex子项默认flex-shrink为1,空间不足时会按比例缩小。明确声明不收缩,才能保证侧边栏宽度始终稳定。
反过来,如果需求是侧边栏占据固定比例,比如四分之一宽度,可以把侧边栏写成flex: 0 0 25%,内容区写flex: 1,同样干净利落。
侧边栏独立滚动与整体布局的完善
实际项目中,侧边栏菜单项往往很多,超过一屏高度后需要侧边栏内部自己滚动,而内容区独立滚动,顶部的header还要保持固定。这时需要给整个布局设定一个确定的高度,然后让两个区域分别处理溢出。
html, body {
height: 100%;
margin: 0;
}
.layout {
display: flex;
height: 100vh; /* 视口高度固定 */
overflow: hidden;
}
.sidebar {
width: 240px;
flex-shrink: 0;
overflow-y: auto; /* 菜单过多时侧边栏内部滚动 */
}
.content {
flex: 1;
overflow-y: auto; /* 内容区独立滚动 */
}如果还需要在顶部加一条通栏的header,常见做法是外层用纵向flex,header固定高度,下方的主体区域flex: 1,主体区域内部再做左右结构的横向flex,形成flex的嵌套使用。
.app {
display: flex;
flex-direction: column;
height: 100vh;
}
.header {
height: 60px;
flex-shrink: 0;
}
.layout {
flex: 1;
display: flex;
overflow: hidden;
}这种嵌套结构在各大管理后台模板中随处可见,逻辑清晰且各区域滚动互不影响。需要注意的是height: 100vh在移动端浏览器上可能因为地址栏的收起展开产生跳动,移动端可以考虑用100dvh或者JS动态计算视口高度来规避。
可折叠侧边栏与响应式处理
很多后台系统支持折叠侧边栏。基于flex实现折叠非常简单,只需要切换侧边栏的宽度即可,flex: 1的内容区会自动补齐腾出的空间,配合transition还能得到平滑的动画效果。
.sidebar {
width: 240px;
flex-shrink: 0;
transition: width 0.25s ease;
overflow: hidden;
}
.sidebar.collapsed {
width: 64px; /* 折叠后只显示图标 */
}移动端适配方面,小屏幕下左右结构通常不再合适,可以让布局在断点处切换为纵向排列。flex做这件事同样轻松,把flex-direction改为column,再调整各区域的高度即可。
@media (max-width: 768px) {
.layout {
flex-direction: column;
}
.sidebar {
width: 100%;
height: auto;
}
.content {
flex: 1;
}
}与其他方案对比一下:浮动方案需要手动清除浮动,侧边栏等高问题难以优雅解决;绝对定位方案会让内容区无法自然撑开文档流,滚动处理很别扭;Grid布局虽然也能用grid-template-columns: 240px 1fr一句话实现同样的效果,且在纯二维布局上更强,但flex的浏览器兼容性历史更好,学习成本更低,对于这种一维的左右分栏,flex依然是最顺手的选择。当然,如果页面后续要发展成更复杂的多行多列栅格,可以平滑迁移到Grid,两者并不冲突。
总结一下,flex实现左右结构侧边栏的核心要点有三个:外层容器display: flex;侧边栏固定宽度加flex-shrink: 0防挤压;内容区flex: 1自适应撑满。在此基础上按需添加overflow实现独立滚动,配合媒体查询完成响应式切换,就能覆盖绝大多数后台系统的布局需求。