浅谈css盒模型的宽高

644 阅读3分钟

这是我参与8月更文挑战的第一天,活动详情查看:8月更文挑战

前文

写了好久的CSS,但是对于各种盒模型的尺寸,还是很懵逼的状态,一知半解,所以决心整一波。

正文

盒模型有块级盒子(block flex),行级盒子(inline)。

块格式化上下文(BFC)

每个盒子都会换行,在块盒子布局时发生的区域,常用的产生BFC的方式可以看这里,对于我们日常使用,最常见的就是默认布局和display:flex设定的元素,对于块盒子,默认会有如下行为:

  • 盒子默认会在writing-mode指定的方向上扩展并占据父容器在该方向上的所有可用空间, 默认是horizontal,所以通常的表现就是div在占满宽度,如下:在线链接
<div>
    <div class='title'>writing-mode默认(horizontal)</div>
    <div class="parent">
        <div class="child"></div>
     </div>
     <div class='title'>writing-mode为vertical</div>
     <div class="parent-vertical">
     <div class="child-vertical"></div>
     </div>
  </div>
  
  
.parent {
  background: red;
  height: 100px;
}

.child {
  background: green;
  height: 80px;
  margin-top: 8px;
}

.parent-vertical {
  background: red;
  writing-mode: vertical-rl;
  width: 100px;
  height: 100px;
}

.child-vertical {
  background: green;
  width: 80px;
}

.title {
  margin-top: 16px;
  margin-bottom: 8px;
}

image.png

可以看到,默认情况没有指定width,parent里面的child是占满可用width的。当writing-mode vertical-rl,没有指定height,parent-vertical里面的child-vertical占满可用height。这就是默认的尺寸特性。

不过这里有个问题,按理说 parent-vertical的width应该是占满的,但是不知道为什么要手动设置width??

  • display:flex也是一种块级盒子,我们看看它的表现
 <div>
      <div class="title">flex(column)</div>
      <div class="flex-column">
        <div class="flex-column-child"></div>
      </div>

      <div class="title">flex(row)</div>
      <div class="flex-row">
        <div class="flex-row-child"></div>
      </div>
 </div>

1628092854(1).png flex的表现和上述默认情况类似,都是占满主轴方向空间,不过flex有额外的控制child尺寸的属性,那就是align-items,这个属性是对交叉轴的chid对齐方式的控制,但是它的默认值 stretch 是指定child占满主轴方向空间,所以当我们设置align-items为其他值时,这时候child因为缺少主轴方向尺寸导致无法绘制出来。 除此之外,对于flex的child,还有其他几个属性可以控制,分别是:

  • flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大
  • flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小
  • flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小 具体效果可以看阮一峰的这篇文章

行格式化上下文(LFC)

声明为 display:inline, 每个盒子都不会换行,设置的width和height不生效,一般看到的表述都是这个,但是其实这不全对。例如下面这个情况:

  • display:inline的父元素为Flex弹性盒子,在这种情况下,Flex会使得它的子元素变成 flexible
    <div
        style={{
            height: "100px",
            background: "red",
            width: "100px",
            display: 'flex'
        }}
    >

    <div
        style={{
            background: "green",
            height: "80px",
            display: "inline",
            width: "80px"
        }}
        ref={(ref) => {
          console.log(window.getComputedStyle(ref).getPropertyValue("display"));
        }}
     />
</div>

运行会发现打印的是 block, 这时候虽然声明的是 inline, 但是width和height起作用,如果把父元素的display:flex去掉,则打印的是inline, width和height不起作用。

Demo

参考