# flex布局子元素宽度超出父元素问题
最近在做项目中,使用flex
布局遇到了个老问题:当flex子元素
里的子元素的宽度过大,超出flex父元素
时,设置flex:1
并不能限制flex子元素
的尺寸;具体表现如下:
可以看到,右侧的文本超出部分没有隐藏,而且超出了.wrap
的宽度。之前也遇到过这种情况,没太注意就给忘了,看来有必要总结一下;
# 问题分析
.right
的宽度该如何计算?
正常情况下的元素宽度,如果设置有具体的值,那就是设置的值;如果没有设置,那就是该元素内容区占据的宽度。上面的例子可以看到,.right
并没有设置width
属性,所以.right
是由.right-content
撑开。又由于是flex
盒子子元素,设置了flex: 1
属性,所以:
.right宽度 = .right内容占据宽度(即.right-content宽度) + flex: 1属性分配的宽度
.right
盒子已经设置flex: 1
;为什么宽度还会超出父元素?
这是使用flex
布局很常见的一个误区:给子元素设置了flex
属性,很自然的就认为,它会按比例分配父元素的宽度。因为大多时候恰好是这样,其实并非如此。我们再来好好理解一下flex:1
的含义(flex
是flex-grow
、flex-shrink
和flex-basis
的缩写,这里就不做介绍。详情点这里 (opens new window)
可以看出,flex:1
并不是决定子元素宽度的因素,它只是规定了,如果父元素有多余空间,以怎样的比例去分配剩余空间,并不会对子元素原本就占据的空间做处理。所以,当元素原本的宽度就超过父元素宽度时,子元素内容就会超出。
# 解决方案
- 限制子元素原本宽度,
.right
设置width
属性
修改.right
元素css
如下,
.wrap {
...
.right {
width: 0; //新增
flex: 1;
background: lightblue;
&-content {
...
}
}
}
2
3
4
5
6
7
8
9
10
11
原理:强行设置.right
原本宽度为0,让.right
盒模型宽度完全由flex: 1
这个属性来分配。
chrome浏览器效果完美:
但是在 firefox
浏览器时,即使设置width: 0
,也不会生效,子元素还是超出;可以设置min-width: 0
。
:::
设置min-width: 0
可行的原理:
原因是浏览器默认为flex容器的子元素设置了 "min-width: auto;min-height: auto", 即flex子元素的最小宽度高度不能小于其内容的宽高, 在规范里的表述是: A flex item cannot be smaller than the size of its content along the main axis. 所以通过设置 min-width: 0, 覆盖这个默认设置, flex-shrink属性就能生效了 具体参考这个回答:html - Why don't flex items shrink past content size? - Stack Overflow (opens new window)
:::
.right
设置overflow
属性不为visible
设置width: 0
可行的前提是:.right-content
元素宽度继承父元素.right
。如果当.right-content
元素设置了自己的宽度时,方法1就不能满足了,如下所示:
设置.right-content
元素css
如下,子元素依然会超出
.wrap {
...
.right {
width: 0; //新增
flex: 1;
background: lightblue;
&-content {
width: 300px; //新增
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
background: lightyellow;
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
这时候就回到了基本的css问题,子元素内容超出如何展示,给.right
设置overflow
搞定
正常css
如下,让
.wrap {
...
.right {
// width: 0;
flex: 1;
background: lightblue;
overflow: auto; //新增
&-content {
width: 300px; //新增
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
background: lightyellow;
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 总结
- 设置
min-width:0
可以解决当flex子元素
的子元素大小为auto
的情况; - 设置
overflow
不为visible
可以解决所有情况下的麻烦;
兜兜转转一大圈,回到最初的原点,随手记录一下。