CSS 怎么实现两个 div 一个固定宽另一个填充剩余空间?
当年这可能是一个典型的CSS面试题:“两列布局”。很多年前(大约是10年前吧),有过这样的一个面试题:
两列布局,左侧列宽度是20%,右侧列是80%,两列之间的间距是20px,CSS怎样实现这样的一个布局,而且不会出现滚动条!
对于题主这个问题,早在当年可能会较为蛋疼一点,或许很多开发者会采用 JavaScript 来辅助完成。但对于今天而言,这个布局效果再简单不过了。而且方案很多。
假设构建这样的一个布局,它的 HTML像下面这样:
<body> <aside>侧边栏,固定宽度</aside> <main>主内容,填充剩余空间</main> </body>
这个布局最大的特点是:
两列布局,其中一列固定尺寸(比如说侧边栏),另外一列自适应,能随着容器宽度调整!
接下来,分不同方案来构建这样的一个布局。
calc()方案
在Flexbox和Grid还没出现的时候,如果不借助 JavaScript 的话,calc()
应该是最简单的了吧 :
body { display: flow-root; /*清除浮动*/ } aside { float: left; width: 220px; } main { float: left; width: calc(100% - 220px); }
如果你还希望列与列之间有一定的间距,还可以像下面样写:
body { display: flow-root; /*清除浮动*/ } aside { float: left; width: 220px; } main { float: left; margin-left: 20px; width: calc(100% - 220px - 20px); }
结合 CSS 自定义属性,灵活性会更好:
:root { --fixed-width: 220px; --gap: 20px; } body { display: flow-root; /*清除浮动*/ } aside { float: left; width: var(--fixed-width); } main { float: left; margin-left: var(--gap); width: calc(100% - var(--fixed-width) - var(--gap)); }
如果效果要更完美一点,可以考虑在 body
上添加一个 min-width
的设置。
在这个示例中,用到了两个关键点,第一个 CSS 函数中的 calc()
函数的功能,它可以做四则运算,第二个就是 CSS 值中的 %
,当百分比%
运用于 width
时,它的计算是相对于其父容器的 width
来计算。
Flexbox方案
Flexbox 方案就更简单了:
body { display: flex; gap: var(--gap) } aside { width: var(--fixed-width); } main { flex: 1; }
里使用了 CSS Flexbox 布局,很简单。将body
声明为一个 Flexbox 容器(使用 display
) ,在侧边栏设置固定宽度,主列使用 flex:1
,他会扩展Flexbox容器的剩余空间。如果只是要现这样的一个效果,到此就可以了。
Grid 方案
Grid 方案和 Flexbox 很相似:
body { display: grid; gap: var(--gap); grid-template-columns: var(--fixed-width) 1fr; }
使用Grid 是最简单的!不过要掌握 Grid 就不简单了。这里关键是使用 grid-template-columns
定义了一个两列网格,其中第一列列宽是 --fixed-width
,第二列列宽是 1fr
。这个 fr
是 Grid 中独有的特性。
fr
单位代表网格容器中可用空间的一等份。
从这个描述中不难发现,在CSS网格布局中使用fr
单位确定尺寸的网格轨道被称为 弹性网格轨道 ,因为它们会根据网格容器剩余空间进行对网格轨道进行弹性缩放,这个有点类似于 Flexbox 布局中的 flex
有点类似。
一般情况之下,网格轨道使用fr
单位时,网格容器的可空间会按下面的公式来计算网格轨道尺寸:

对于fr
设置弹性网格轨道理解起来还是有一定的困惑,不过我们可以将其和%
结合起来,会更易于理解。简单地说:
1
个fr
(即1fr
)就是100%
网格容器可用空间;2
个fr
(即2fr
)是各50%
网格容器可用空间,即1fr
是50%
网格容器可用空间。以此类似,要是你有25
个fr
(即25fr
),那么每个fr
(1fr
)就是1/25
或4%
。
使用饼图可以很形象的描述fr
:

注意,一个饼图(圆)就相当于网格容器的可用空间,分割的份数就相当于设置了弹性系数的网格轨道。
上面三个方案效果都是一致的
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
2021-12-30 echarts 如何结合百度地图使用
2021-12-30 echarts 主题颜色更换
2021-12-30 uniapp 拨打电话 - uni.makePhoneCall(tel)
2021-12-30 echarts 随屏幕大小改变大小(resize)
2021-12-30 uniapp 飞入购物车的商品