这篇文章发布于 2020年10月6日,星期二,13:21,归类于 CSS相关。 阅读 44278 次, 今日 19 次 19 条评论
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=9541
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。
一、推荐使用flex缩写语法
CSS官方文档明确推荐flex属性使用缩写语法,描述如下所示:
Authors are encouraged to control flexibility using the flex shorthand rather than with its longhand properties directly, as the shorthand correctly resets any unspecified components to accommodate common uses.
大致意思是,建议使用单值缩写,而不是完整的3个属性值,因为单值属性所对应的flex计算值根据开发者日常最常用的使用进行了优化。
这句话很多人并不知道什么意思,这个说来话长,想想还是讲一下吧。
flex
属性是flex-grow
,flex-shrink
和flex-basis
这3个CSS属性的缩写,如果不清楚,可以参见我之前这篇口碑热文“CSS flex属性深入理解”。
按照以往的经验,flex
属性只有一个值的时候,另外缺省的值应该使用默认值才对,但是flex
属性并不是这样的。
我们可以对比CSS border
属性。
CSS border
属性是border-width
,border-style
和border-color
这3个CSS属性的缩写,当border
属性设置了1个值或2个值的时候,剩下的属性值一定是默认值,例如:
border:2px
等同于border:2px none currentColor
,也就是此时border-style
是默认值none
,border-color
的计算值是当前的色值;border:#fff
等同于border:medium none #fff
,也就是此时border-width
是默认值medium
;border:solid
等同于border:medium solid currentColor
。
使用下面的代码可以得到flex-basis
默认值是auto
,flex-grow
默认值是0
,flex-shrink
默认值是1
。
console.log(getComputedStyle(document.body).flexGrow); console.log(getComputedStyle(document.body).flexShrink); console.log(getComputedStyle(document.body).flexBasis);
实际运行效果如下:
然后再看下flex
缩写属性的计算值,就会发现不一样的事情:
flex:1
等同于flex:1 1 0%
,flex:1 2
等同于flex:1 2 0%
,即flex-basis
使用的不是默认值auto
,而是使用的0%
;flex:100px
等同于flex:1 1 100px
,即flex-grow
使用的不是默认值0
,而是使用的1
;
这就是上面提到的flex
属性站在实用主义的角度对缩写属性的计算值进行了优化。
然后,还有一个重要原因,flex属性的长语法需要理解深刻,反复使用才能驾驭,门槛比较好,因此,实际开发,如果可以,建议使用flex缩写。
常见的flex缩写有下面这几个,flex:0
、flex:1
、flex:none
、flex:auto
,那各个CSS声明应该在什么场景下使用才正确呢?
//zxx: 如果你看到这段文字,说明你现在访问是体验糟糕的垃圾盗版网站,你可以访问原文获得很好的体验:https://www.zhangxinxu.com/wordpress/?p=9541(作者张鑫旭)
二、使用flex缩写语法场景
下表展示了常见的flex
属性单值语法对应的flex
计算值,涵盖了绝大多数的flex
属性的使用场景。
单值语法 | 等同于 | 备注 |
---|---|---|
flex: initial | flex: 0 1 auto | 初始值,常用 |
flex: 0 | flex: 0 1 0% | 适用场景少 |
flex: none | flex: 0 0 auto | 推荐 |
flex: 1 | flex: 1 1 0% | 推荐 |
flex: auto | flex: 1 1 auto | 适用场景少 |
1. flex:initial基本表现和适用场景
flex:initial
等同于设置flex: 0 1 auto
,可以理解为flex属性的默认值。
该默认值图形示意如下图所示。
其行为表现文字描述为:
flex容器有剩余空间时尺寸不会增长(flex-grow:0),flex容器尺寸不足时尺寸会收缩变小(flex-shrink:1),尺寸自适应于内容(flex-basis:auto)(行为类似fit-content)。
举个例子,我们给flex容器设置深红色的虚线框,如果此时flex子项(设置深天蓝色轮廓)的内容都比较少,就会有如下图所示的效果,剩余空间依然保留。
相关CSS代码和HTML代码如下所示:
.container { display: flex; border: 2px dashed crimson; } .container item { border: 2px solid deepskyblue; }
<div class="container"> <item>范张</item> <item>范鑫</item> <item>范旭</item> <item>范帅</item> <item>范哥</item> </div>
如果子项内容很多,由于flex-shrink:1
,因此,会缩小,表现效果就是文字换行,效果如下图所示。
'initial'
是CSS中的一个全局关键字,表示CSS属性的初始值,通常用来还原已经设置的CSS属性。因此日常开发不会专门设置flex:initial
声明,但是不设置并不是说flex
默认属性值用的不多。
flex:initial适用场景
flex:initial
声明适用于下图所示的布局效果。
上图所示的布局效果常见于按钮、标题、小图标等小部件的排版布局,因为这些小部件的宽度都不会很宽,水平位置的控制多使用justify-content
和margin-left:auto/margin-right:auto
实现。
除了上图所示的布局效果外,flex:initial
声明还适用于一侧内容宽度固定,另外一侧内容宽度任意的两栏自适应布局场景,布局轮廓如图下图所示(点点点表示文本内容)。
此时,无需任何其他Flex布局相关的CSS设置,只需要容器元素设置display:flex
即可。
总结下就是那些希望元素尺寸收缩,同时元素内容万一较多又能自动换行的场景可以不做任何flex
属性设置。
2. flex:0和flex:none的区别和各自适用场景
flex:0
等同于设置flex: 0 1 0%
,flex:none
等同于设置flex: 0 0 auto
。
这两个值的图形示意如下图所示。
其中:
flex:0 1 0%
表示flex-grow
是0,flex-shrink
是1,因此元素尺寸会收缩但不会扩展,在加上flex-basis:0%
表示建议支持是0,因此,设置flex:0
的元素的最终尺寸表现为最小内容宽度;flex:0 0 auto
表示元素尺寸不会收缩也不会扩展,再加上flex-basis:auto
表示固定尺寸由内容决定,由于元素不具有弹性,因此,元素内的内容不会换行,最终尺寸通常表现为最大内容宽度。
举个例子,设置每个flex子项有足够多的内容,HTML代码如下所示:
<h4>flex:0</h4> <div class="container flex-0"> <item>范张范张范张</item> <item>范鑫范鑫范鑫</item> <item>范旭范旭范旭</item> <item>范帅范帅范帅</item> <item>范哥范哥范哥</item> </div> <h4>flex:none</h4> <div class="container flex-none"> <item>范张范张范张</item> <item>范鑫范鑫范鑫</item> <item>范旭范旭范旭</item> <item>范帅范帅范帅</item> <item>范哥范哥范哥</item> </div>
然后对flex子项分别设置flex:0
和flex:none
,CSS代码如下所示:
.container { display: flex; } .flex-0 item { flex: 0; } .flex-none item { flex: none; }
结果如图下图所示:
可以看到应用了flex:0
的元素全部高高耸起,一柱擎天,表现为最小内容宽度;而应用了flex:none
的元素则无视容器的尺寸限制,直接溢出容器,没有换行,表现为最大内容宽度。
适合使用flex:0的场景
由于应用了flex:0
的元素表现为最小内容宽度,因此,适合使用flex:0
的场景并不多,除非元素内容的主体是替换元素,此时文字内容就会庇护在替换元素的宽度下从而不会出现“一柱擎天”的排版效果。
该适用场景的布局示意如下图所示。
其中上图左侧部分的矩形表示一个图像,图像下方会有文字内容不定的描述信息,此时,左侧内容就适合设置flex:0
,这样,无论文字的内容如何设置,左侧内容的宽度都是图像的宽度。
适合使用flex:none的场景
当flex子项的宽度就是内容的宽度,且内容永远不会换行,则适合使用flex:none
,这个场景比flex:0
适用的场景要更常见。
例如列表右侧经常会有一个操作按钮,对于按钮元素而言,里面的文字内容一定是不能换行的,此时,就非常适合设置flex:none
,例如下面这个例子,示意了按钮使用了flex:none
之后的布局变化,HTML和CSS代码如下所示:
<div class="item">
<img src="1.jpg">
<p>右侧按钮没有设置flex:none,表现为最小内容宽度。</p>
<button>按钮</button>
</div>
<div class="item">
<img src="1.jpg">
<p>右侧按钮设置了flex:none,按钮正常显示了。</p>
<button class="none">按钮</button>
</div>
.container {
display: flex;
padding: .5rem;
border: 1px solid lightgray;
background-color: #fff;
}
img {
width: 3rem; height: 3rem;
margin-right: .5rem;
}
button {
align-self: center;
padding: 5px;
margin-left: .5rem;
}
.none {
flex: none;
}
从代码可以看出两段内容的唯一区别就是下面的布局对按钮元素设置了flex:none
,结果就有如下图所示的不同的布局效果。
不仅按钮正常显示了,整个布局会自动适配按钮的尺寸,也就是按钮文字多了,中间的文字内容宽度就会自动减小,整个布局依然是弹性的。
3. flex:1和flex:auto的区别和各自适用场景
flex:1
等同于设置flex: 1 1 0%
,flex:auto
等同于设置flex: 1 1 auto
。
这两个值的图形示意如下图所示。
结合flex属性值的描述,我们可以得出flex:1
和flex:auto
的行为表现:
元素尺寸可以弹性增大,也可以弹性变小,具有十足的弹性,但是
flex:1
在尺寸不足时会优先最小化内容尺寸,flex:auto
在尺寸不足时会优先最大化内容尺寸。
上面的描述可以通过一个例子明白是什么意思,这一次是仅仅设置第1项的文字内容很多,HTML代码如下所示:
<h4>flex:1</h4> <div class="container flex-1"> <item>范张范张范张范张范张范张范张范张范张</item> <item>范鑫</item> <item>范旭</item> <item>范帅</item> <item>范哥</item> </div> <h4>flex:auto</h4> <div class="container flex-auto"> <item>范张范张范张范张范张范张范张范张范张</item> <item>范鑫</item> <item>范旭</item> <item>范帅</item> <item>范哥</item> </div>
可以看出两段HTML结构和内容都是一样的,现在,对上下两端HTML设置不同的CSS样式,代码如下所示:
.flex-1 item { flex: 1; } .flex-auto item { flex: auto; }
结果就会看到如下图所示的布局效果。
上图鲜明地体现了flex:1
和flex:auto
的区别,虽然都是充分分配容器的尺寸,但是flex:1
的尺寸表现更为内敛(优先牺牲自己的尺寸),flex:auto
的尺寸表现则更为霸道(优先扩展自己的尺寸)。
从某种程度上讲,flex:1
的表现神似table-layout:fixed
,flex:auto
的表现神似table-layout:auto
。
适合使用flex:1的场景
当希望元素充分利用剩余空间,同时不会侵占其他元素应有的宽度的时候,适合使用flex:1
,这样的场景在Flex布局中非常的多。
例如所有的等分列表,或者等比例列表都适合使用flex:1
或者其他flex数值,适合的布局效果轮廓如下图所示。
以及适用于无规律布局中动态内容元素,我们不妨继续使用flex:none
那里演示的例子进行说明。
下面这段HTML和CSS代码下的按钮元素是换行显示的(就是前面出现过的按钮不换行的例子的HTML代码)。
<div class="item"> <img src="1.jpg"> <p>右侧按钮没有设置flex:none,表现为最小内容宽度。</p> <button>按钮</button> </div>
.container { display: flex; padding: .5rem; border: 1px solid lightgray; background-color: #fff; } img { width: 3rem; height: 3rem; margin-right: .5rem; } button { align-self: center; padding: 5px; margin-left: .5rem; }
除了设置<button>
元素flex:none
以外,在这个例子中,我们还可以设置<p>
元素flex:1
实现类似的效果。
p { flex: 1; }
结果就有如下图所示,<p>
元素设置了flex:1
之后,按钮元素正常显示了。
适合使用flex:auto的场景
当希望元素充分利用剩余空间,但是各自的尺寸按照各自内容进行分配的时候,适合使用flex:auto
。
flex:auto
多用于内容固定,或者内容可控的布局场景,例如导航数量不固定,每个导航文字数量也不固定的导航效果就适合使用flex:auto
效果来实现,我做了个很简单的示意,代码如下所示:
<nav class="flex"> <span>首页</span> <span>排行榜</span> <span>我的订单</span> <span>个人中心</span> </nav>
nav span { flex: auto; line-height: 3rem; background: #444; color: #fff; text-align:center; } span + span { border-left: 1px solid #eee; }
此时大家就可以看到一个基于内容自动分配宽度的自适应导航效果了,效果如下图所示,文字越多的导航占据的宽度越大,这完全是浏览器自动分配的。
三、最后总结一下
最后总结一下:
flex:initial
表示默认的flex状态,无需专门设置,适合小控件元素的分布布局,或者某一项内容动态变化的布局;flex:0
适用场景较少,适合设置在替换元素的父元素上;flex:none
适用于不换行的内容固定或者较少的小控件元素上,如按钮。flex:1
适合等分布局;flex:auto
适合基于内容动态适配的布局;
以上就是本文内容,写于2020年国庆,部分内容节选自明年会出版的新书《CSS新世界》。
感谢您的阅读,如果您觉得本文内容还不错,欢迎分享。
本文为原创文章,欢迎分享,勿全文转载,如果实在喜欢,可收藏,永不过期,且会及时更新知识点及修正错误,阅读体验也更好。
本文地址:https://www.zhangxinxu.com/wordpress/?p=9541
(本篇完)
- CSS flex属性深入理解 (0.888)
- 写给自己看的display: flex布局教程 (0.799)
- Oh My God,CSS flex-basis原来有这么多细节 (0.760)
- flex-end为什么overflow无法滚动及解决方法 (0.217)
- CSS值类型文档大全 (0.201)
- CSS columns轻松实现两端对齐布局效果 (0.201)
- CSS gap属性进化史 (0.201)
- 粉丝群第1期CSS小测点评与答疑 (0.128)
- 让CSS flex布局最后一行列表左对齐的N种方法 (0.128)
- 一万年了,CSS text-align-last终于可以用了 (0.128)
- CSS高宽不等图片固定比例布局的三重进化 (RANDOM - 0.089)
涨姿势了
还是不明白使用单值缩写的好处在哪里?
明明使用的完整的写法,更加的直观明了。
span + span 可以,我原先一直还用的排除法,学到了
今天在chrome中查看flex:0;会被解析成flex:0 1 0%;
感谢反馈,是图配错了。
求救,圖片看不著了,可否更新下好搭配內文理解,感恩
CDN的问题么?我看下海外CDN是不是出问题了。
可否看下控制台报什么错误,如果可以,麻烦截屏发我 zhangxinxu@zhangxinxu.com ,我给运营商反馈下,谢谢了。
非常感謝你的回覆,控制台卻時有報錯,我已經給你發過去了,再麻煩了,你的網站都是好文章,但是圖片我這都看不到,感謝你的幫忙!!!
你好,邮件并未收到,或者有没有在线的图片URL地址,直接发我。
或者清空浏览器缓存试试,可能是浏览器一直缓存了过期的SSL证书。
我翻了下牆,圖片可以顯示了,不知道是不是跟國內檔住台灣這得ip有關係,沒事這可不影響我學習進步的決心哈哈哈哈,非常感謝你百忙中的回應,期待你後續的文章!!
我想問下我在CSDN論壇上有寫學習的文章,可否分享你的部分內容在我的文章中呢?我會在文章內標示出處的
最初从慕课网的视频了解到你,一晃5,6年了。买了css世界,另外很期待你的新书
原来flexbox的支持性那么好了,看来不需要再用绝对定位了
flex-basis: 0% 的表现却是 width:auto /想哭
学到了!感谢大佬
学到了,感谢大佬分享。
flex很适合新闻列表(左标题+右日期)或讨论列表那种(标题+发布人+更新日期)。标题区的宽度随着容器宽度变化。
再加上text-overflow:elipse绝配。
学到了,flex让布局变得简单