这是我参与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;
}
可以看到,默认情况没有指定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>
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不起作用。