布局长这样:左边 48px 头像,右边文字区 flex: 1。放一段普通中文没事,一旦进来一条没有空格的 URL 或者长英文单词,整个容器横着撑出去,页面开始横向滚动。
.media { display: flex; gap: 12px; }
.media .avatar { flex: 0 0 48px; }
.media .body { flex: 1; } /* 想让它吃掉剩余空间,并且能缩 */
直觉是”flex-shrink 默认为 1,应该能缩”,但怎么都不缩。
规范里的一行字
CSS Flexbox 里,flex item 的 min-width 初始值是 auto。这个 auto 在主轴上会解析成 min-content——内容缩到最小可能宽度的那一档。一条没有断点的长串,它的 min-content 就是整串本身。
而 flex-shrink 再怎么缩,也不能小于 min-width。两者叠加的结果:子项被内容焊死在原地。
规范里还有个例外:当 overflow 不是 visible(即 hidden / auto / scroll / clip)时,automatic minimum size 会退化成 0。这解释了那个流传很广但很少被讲清的经验——”加个 overflow: hidden 就好了”,它治好的正是这一条。
三种写法,挑一种
/* 1. 显式关掉 auto,最直接,副作用最小 */
.media .body { flex: 1; min-width: 0; }
/* 2. 借那个规范的例外条款 */
.media .body { flex: 1; overflow: hidden; }
/* 注意:这会把溢出的内容裁掉,不是所有场景都能接受 */
/* 3. 让长串本身可以断行,从"内容最小宽度"这一侧解决 */
.media .body { flex: 1; overflow-wrap: anywhere; }
我一般用第一种。min-width: 0 的语义就是”允许缩到零”,写出来之后阅读的人也知道这里为什么这么写——比一个来历不明的 overflow: hidden 清楚。
同一个坑的两个变种
省略号不显示。 text-overflow: ellipsis 要生效需要三个条件同时成立:overflow: hidden、white-space: nowrap、以及——在 flex 子项里——min-width: 0。很多”省略号没效果”的问题,前两个都对,就差最后一个。
.cell {
flex: 1;
min-width: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
Grid 里完全一样。 grid item 的 min-width / min-height 也是 auto。所以 grid-template-columns: 1fr 遇到长内容也会溢出,要写 minmax(0, 1fr)——它跟 min-width: 0 是同一个问题的两种写法,只是作用在轨道上。
/* 会被内容撑破 */
grid-template-columns: 1fr 1fr 1fr;
/* 不会 */
grid-template-columns: repeat(3, minmax(0, 1fr));
顺带一句
flex: 1 是 flex-grow:1; flex-shrink:1; flex-basis:0% 的缩写。如果想”按内容宽度、不参与分配”,就写 flex: 0 0 auto;”固定 48px、不放大不缩小”就是 flex: 0 0 48px。把三个值都写出来,比用缩写更容易一眼看懂意图——尤其是三个月后回来看的自己。