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设置弹性网格轨道理解起来还是有一定的困惑,不过我们可以将其和%结合起来,会更易于理解。简单地说:

1fr(即1fr)就是100%网格容器可用空间;2fr(即2fr)是各50%网格容器可用空间,即1fr50%网格容器可用空间。以此类似,要是你有25fr(即25fr),那么每个fr1fr)就是1/254%

使用饼图可以很形象的描述fr

注意,一个饼图(圆)就相当于网格容器的可用空间,分割的份数就相当于设置了弹性系数的网格轨道

上面三个方案效果都是一致的

 

posted @ 2024-12-30 11:13  蓦然JL  阅读(141)  评论(0)    收藏  举报
访问主页
关注我
关注微博
私信我
返回顶部