有如下一段代码,页面上会如何呈现呢?
.flex-box {
width: 200px;
height: 100px;
display: flex;
}
.box1 {
width: 100px;
background-color: #ccc;
}
.box2 {
flex: 1;
background-color: skyblue;
}
<div class="flex-box">
<div class="box1"></div>
<div class="box2">halgjlajlgjlajglajghahahhahahhahahaha</div>
</div>
这是常用的左侧定宽,右侧自适应的用法,浏览器是如何计算宽度的呢?
很多人可能会有疑问:为什么.box1
设置了宽度,但还是会被挤扁呢?
flex如何伸缩
例如有以下例子:
.flex-box {
width: 400px;
height: 100px;
display: flex;
}
.box1 {
width: 200px;
background-color: red;
}
.box2 {
width: 200px;
background-color: green;
}
.box3 {
width: 400px;
background-color: blue;
}
<div class="flex-box">
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
</div>
父容器中的子元素都有一个初始宽度,初始宽度如何决定下面说明
如果按照初始宽度放入普通父容器中,那么他们会溢出400个像素。
当父元素display: flex;默认情况下子盒子flex-shrink:1,box1、box2、box3都具有可收缩的特性。
flex-shrink 定义的仅仅只是元素宽度变小的一个权重分量。每个元素具体收缩多少,还有另一个重要因素,即它本身的宽度。 展示尺寸这么算:
总权重为1x200 + 1x200 + 1x400 = 800;
三个元素分别收缩:
- 400 x 1(flex-shrink) x 200(width) / 800 = 100
- 400 x 1(flex-shrink) x 200(width) / 800 = 100
- 400 x 1(flex-shrink) x 400(width) / 800 = 200
box1的展示尺寸为:box1默认宽度 - 100 = 100;
box2的展示尺寸为:box2默认宽度 - 100 = 100;
box3的展示尺寸为:box3默认宽度 - 200 = 200;
还是很好理解的吧。同理,当元素不够撑满父元素时,需要伸展的宽度也是按照这种方式计算的。只是比例基数变成了剩余空间的宽度。这时候需要设置子元素的flex-grow为1,因为默认情况下子盒子flex-grow为0。 不同的是,伸展时的每个元素的权重即为元素的 flex-grow 的值。
如果你希望元素不能伸缩或者不能伸展,那么需要设置相应的属性为0。
如: flex-shrink: 0,flex-grow: 0.
flex-basis,width,content决定初始宽度
flex-basis 用于计算上一小节中元素的“初始宽度”。
- flex-basis为auto时, 初始宽度为设置的宽度值或者元素内容大小(盒子模型中的占用宽度)。
- flex-basis为像素值时,初始宽度为flex-basis的值。
- flex-basis为百分比时,初始宽度为占父容器的比例。
- flex-basis为0或0%时,初始宽度为0。
常见的flex设置:
样式 | felx-grow | flex-shink | flex-basis |
---|---|---|---|
flex默认值 | 0 | 1 | auto |
flex: 1 | 1 | 1 | 0% |
flex:auto | 1 | 1 | auto |
flex: none | 0 | 0 | auto |
flex-basis 属性在任何空间分配发生之前初始化flex子元素的尺寸。
初始宽度优先级:flex-basis > width > content,最终尺寸会受到min-width和max-width的制约
现在来解答文章开头的第一个问题,浏览器是如何计算的。
box1的初始尺寸是100px,box2的初始尺寸是0,那么有100的剩余尺寸,box1占比0,box2占比1,所以剩余尺寸都分配给box2
==这些表现在子盒子内容宽度不会超出子盒子宽度的时候一切都看起来你恭我顺,风平浪静,但当某个子盒子内容宽度超出子盒子宽度时候,就要开始争地盘了。==
以上两节所讲的是获取剩余空间和分配剩余空间,但实际中一些元素并不会乖乖得服从分配,那么就需要找出不符合分配的成员,重新计算分配空间
flex子元素如何争地盘
在实践中,收缩行为会倾向于给你合理的结果。你通常不希望自己的内容完全消失,或者文本框比自己的最小内容要小,同样的,伸展行为也希望尽可能得将内容展示出来。
除非有明确的width相关设置,否则尺寸都不会主动超过容器宽度的,但是,存在一些特殊情况,例如,连续的英文数字,好长好长;或者内联元素被设置了white-space:nowrap。如果内容超出,根据展示规则,该元素就不会乖乖服从分配的空间了,他就会侵占剩余空间,那必定必定牵连着其他子元素的收缩,但无论伸展还是收缩,都会受到max-width和min-width的约束。但如果父盒子实在承受不了子盒子的内容,那么只能真的溢出了。
所谓不符合分配的成员指的是分配后的空间 < content,当成员不符合分配时,那么该成员的最终值就是 content,因为这个成员的超出,其他成员就需要将超出的空间重新分配
看以下例子:
.flex-box {
width: 300px;
height: 100px;
display: flex;
}
.flex-box > div {
flex: 1 1 auto;
}
.box1 {
width: 200px;
}
<div class="flex-box">
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
</div>
这里box1初始值是200,box2和box3初始值是0,那么剩余空间是100,会给box1,box2,box3分别分配33,那么box1,box2,box3分别是233,33,33
.flex-box {
width: 300px;
height: 100px;
display: flex;
}
.flex-box > div {
flex: 1 1 0%;
}
.box1 {
width: 200px;
}
<div class="flex-box">
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
</div>
这里box1,box2,box3初始值都是0,那么剩余空间是300,会给box1,box2,box3分别分配100,那么box1,box2,box3分别是100,100,100
这个时候把box1的宽度去掉,给box1加个200px的内容呢<div style="width: 200px;"></div>
,以上两个例子又如何呈现呢?
.flex-box {
width: 300px;
height: 100px;
display: flex;
}
.flex-box > div {
flex: 1 1 auto;
}
<div class="flex-box">
<div class="box1">
<div style="width: 200px;"></div>
</div>
<div class="box2"></div>
<div class="box3"></div>
</div>
这里box1初始值是200,box2和box3初始值是0,那么剩余空间是100,会给box1,box2,box3分别分配33,那么box1,box2,box3分别是233,33,33
.flex-box {
width: 300px;
height: 100px;
display: flex;
}
.flex-box > div {
flex: 1 1 0%;
}
<div class="flex-box">
<div class="box1">
<div style="width: 200px;"></div>
</div>
<div class="box2"></div>
<div class="box3"></div>
</div>
这里box1,box2和box3初始值是0,那么剩余空间是300,会给box1,box2,box3分别分配100,但box1的内容被撑到了200,box1要伸展,相应的box2和box2就要重新分配空间(-100px),都在允许的范围内去伸展和压缩,box1要伸展100px,相应的box2和box3分别压缩50px,最终呈现的是box1,box2,box3分别是200,50,50
这个时候回头来看开头的例子
box1的初始值是100,box2初始值是0,box1 flex:0,box2 flex: 1,那么剩余空间都给了box2,box1是可缩盒子,box2是可伸可缩盒子,当box2内容超出原本的空间后就会伸展,box1会相应得收缩。
那么如何避免这种情况呢?
- 做法1:给box1设置最小宽度min-width
- 做法2:给box1设置flex-shink:0
- 做法3:从内容上处理,给box2设置word-break:break-all
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。