css探索之流体布局

632 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

背景

这段时间碎片时间比较多,重新温习一遍《css世界》,恰好发现了一些之前忽略的知识点,所以在这里进行学习探索一下。由于内容稍显基础,所以对大佬们们来说没啥干货。

流体布局

什么是流体布局?

所谓的“流体布局”,通俗点讲就是跟流体一样,在水平方向可以自动填充的布局方式。

盒模型

按照css盒尺寸涉及到的区域是由margin、border、padding和content这几个属性组成,进一步进行推测,css世界中理论上应该有四种盒模型,分别为:

  • margin-box
  • border-box
  • padding-box
  • content-box

但是,很遗憾,目前的浏览器只实现了 border-boxcontent-box 这两种盒模型(曾经Firefox实现过padding-box,只不过后来又放弃了)。

宽度分离原则

背景介绍


在日常开发过程中,经常会碰到一种场景:块区域需要指定尺寸,但是本身又具有描边和内边距,导致需要进行宽度的动态计算。

    .box {
        margin: 20px;
        padding: 20px;
        border: 2px solid #f33;
        width: 200px;
        height: 200px;
        background: #333;
    }

    <div class="box"></div>

这时具体效果如下图:

image.png

这时块区域的宽度其实是 244(width + padding * 2 + border * 2),而实际上,我们想要的是一个200宽度的块区域。这时,为了满足我们的需求,我们就需要动态计算宽度值,然后赋值给width属性。但是,如果border或者padding发生改变的时候,我们就需要再次进行计算。

那有没有什么好的方式可以解决这个问题呢?

宽度分离原则使用


我们试一下宽度分离原则:宽度分离就是width属性不与影响宽度的border和padding属性共存。实现方式就是充分利用流体布局,在外层嵌套一层标签,父元素就行宽度设置,子元素采用width:auto

具体实现代码如下:

.father {
  width: 200px;
  height: 200px;
}

.child {
  margin: 20px;
  padding: 20px;
  border: 2px solid #f33;
  height: 156px;
  background: #333;
}

<div class="father">
    <div class="child"></div>
</div>

我们来看一下效果如何(图中右侧块):

image.png

结果分析


测试结果证明,宽度分离原则确实能解决盒尺寸的计算问题。

这个时候,肯定有人会提出疑问了:宽度分离原则多增加了一层标签,增加了HTML成本。

没有错,确实会有这样的问题,而且过深的嵌套也确实会导致额外的页面渲染和维护成本。但是增加的只是一层只有width属性的标签,相比较于收益来说,这点耗损是可以接收的。

当然,有没有更完美的解决方案呢?当然有,那就是box-sizing。

box-sizing

名词解释


box-sizing就是盒尺寸,更准确的说是盒尺寸的作用细节。

box-sizing使用


话不多说,前面我们已经提到了盒模型,这里我们就直接上代码来看一下效果:

    .parent {
      margin: 20px;
      width: 220px;
      height: 220px;
      border: solid 10px #ffc129;
    }

    .content-box {
      box-sizing: content-box;
      width: 100%;
      border: solid #5B6DCD 10px;
      padding: 5px;
    }

    .border-box {
      box-sizing: border-box;
      width: 100%;
      border: solid #5B6DCD 10px;
      padding: 5px;
    }

    <div class="parent">
        parent
        <div class="content-box">child</div>
    </div>

    <div class="parent">
        parent
        <div class="border-box">child</div>
    </div>

具体效果如下图:

image.png

通过图中的对比,我们可以很明显的看出来,content-box和border-box的区别就在于宽度的计算方式不同。实际上,造成这种结果的原因是不同的box-sizing改变了content作用的位置。

box-sizing局限性


使用了box-sizing,可以解决大多数场景的问题。但是,这个方式不是万能,再碰到涉及到margin的时候就略显捉襟见肘了。这个时候,我们就需要考虑新的布局方式了,例如flex布局、gird布局等。