21

flex:0 flex:1 flex:none flex:auto应该在什么场景下使用?

 3 years ago
source link: https://www.zhangxinxu.com/wordpress/2020/10/css-flex-0-1-none/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

byzhangxinxu from https://www.zhangxinxu.com/wordpress/?p=9541

本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。

emuQ32.png!mobile

一、推荐使用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-growflex-shrinkflex-basis 这3个CSS属性的缩写,如果不清楚,可以参见我之前这篇口碑热文“CSS flex属性深入理解”。

按照以往的经验, flex 属性只有一个值的时候,另外缺省的值应该使用默认值才对,但是 flex 属性并不是这样的。

我们可以对比CSS border 属性。

CSS border 属性是 border-widthborder-styleborder-color 这3个CSS属性的缩写,当 border 属性设置了1个值或2个值的时候,剩下的属性值一定是默认值,例如:

  • border:2px 等同于 border:2px none currentColor ,也就是此时 border-style 是默认值 noneborder-color 的计算值是当前的色值;
  • border:#fff 等同于 border:medium none #fff ,也就是此时 border-width 是默认值 medium
  • border:solid 等同于 border:medium solid currentColor

使用下面的代码可以得到 flex-basis 默认值是 autoflex-grow 默认值是 0flex-shrink 默认值是 1

console.log(getComputedStyle(document.body).flexGrow);
console.log(getComputedStyle(document.body).flexShrink);
console.log(getComputedStyle(document.body).flexBasis);

实际运行效果如下:

eaY3mir.png!mobile

然后再看下 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:0flex:1flex:noneflex:auto ,那各个CSS声明应该在什么场景下使用才正确呢?

//zxx: 如果你看到这段文字,说明你现在访问是体验糟糕的垃圾盗版网站,你可以访问原文获得很好的体验:https://www.zhangxinxu.com/wordpress/?p=9541(作者张鑫旭)

二、使用flex缩写语法场景

下表展示了常见的 flex 属性单值语法对应的 flex 计算值,涵盖了绝大多数的 flex 属性的使用场景。

flex单值语法对应的计算值 单值语法 等同于 备注 flex: initial flex: 0 1 auto 初始值,常用 flex: 0 flex: 0 0 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属性的默认值。

该默认值图形示意如下图所示。

bQvuaeU.png!mobile

其行为表现文字描述为:

flex容器有剩余空间时尺寸不会增长(flex-grow:0),flex容器尺寸不足时尺寸会收缩变小(flex-shrink:1),尺寸自适应于内容(flex-basis:auto)(行为类似fit-content)。

举个例子,我们给flex容器设置深红色的虚线框,如果此时flex子项(设置深天蓝色轮廓)的内容都比较少,就会有如下图所示的效果,剩余空间依然保留。

RVJR3iB.png!mobile

相关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 ,因此,会缩小,表现效果就是文字换行,效果如下图所示。

Qv6ZbaR.png!mobile

'initial' 是CSS中的一个全局关键字,表示CSS属性的初始值,通常用来还原已经设置的CSS属性。因此日常开发不会专门设置 flex:initial 声明,但是不设置并不是说 flex 默认属性值用的不多。

flex:initial适用场景

flex:initial 声明适用于下图所示的布局效果。

VnMZNbf.png!mobile

上图所示的布局效果常见于按钮、标题、小图标等小部件的排版布局,因为这些小部件的宽度都不会很宽,水平位置的控制多使用 justify-contentmargin-left:auto/margin-right:auto 实现。

除了上图所示的布局效果外, flex:initial 声明还适用于一侧内容宽度固定,另外一侧内容宽度任意的两栏自适应布局场景,布局轮廓如图下图所示(点点点表示文本内容)。

Zzuu6vz.png!mobile

此时,无需任何其他Flex布局相关的CSS设置,只需要容器元素设置 display:flex 即可。

总结下就是那些希望元素尺寸收缩,同时元素内容万一较多又能自动换行的场景可以不做任何 flex 属性设置。

2. flex:0和flex:none的区别和各自适用场景

flex:0 等同于设置 flex: 0 0 0%flex:none 等同于设置 flex: 0 0 auto

这两个值的图形示意如下图所示。

BJV7jaa.png!mobile

从上可以看出 flex:0flex:none 对应的 flex-growflex-shrink 属性值均是 0 ,因此两者都会有如下的行为描述:

元素尺寸不会弹性增大、也不会弹性变小,也就是元素不再具有弹性。

flex-basis:0%flex-basis:auto 有什么区别呢?

  • flex-basis:0% 表示固定尺寸是0,由于元素不具有弹性,因此,设置 flex:0 的元素的最终尺寸表现为最小内容宽度;
  • flex-basis:auto 表示固定尺寸由内容决定,由于元素不具有弹性,因此,设置 flex:none 的元素最终尺寸表现为最大内容宽度;

举个例子,设置每个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:0flex:none ,CSS代码如下所示:

.container {
    display: flex;
}
.flex-0 item {
    flex: 0;
}
.flex-none item {
    flex: none;
}

结果如图下图所示:

YBzYbyz.png!mobile

可以看到应用了 flex:0 的元素全部高高耸起,一柱擎天,表现为最小内容宽度;而应用了 flex:none 的元素则无视容器的尺寸限制,直接溢出容器,没有换行,表现为最大内容宽度。

适合使用flex:0的场景

由于应用了 flex:0 的元素表现为最小内容宽度,因此,适合使用 flex:0 的场景并不多,除非元素内容的主体是替换元素,此时文字内容就会庇护在替换元素的宽度下从而不会出现“一柱擎天”的排版效果。

该适用场景的布局示意如下图所示。

ZzyEV32.png!mobile

其中上图左侧部分的矩形表示一个图像,图像下方会有文字内容不定的描述信息,此时,左侧内容就适合设置 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 ,结果就有如下图所示的不同的布局效果。

32qIR3v.png!mobile

不仅按钮正常显示了,整个布局会自动适配按钮的尺寸,也就是按钮文字多了,中间的文字内容宽度就会自动减小,整个布局依然是弹性的。

3. flex:1和flex:auto的区别和各自适用场景

flex:1 等同于设置 flex: 1 1 0%flex:auto 等同于设置 flex: 1 1 auto

这两个值的图形示意如下图所示。

BfMF7rv.png!mobile

结合flex属性值的描述,我们可以得出 flex:1flex: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;
}

结果就会看到如下图所示的布局效果。

InmuqaA.png!mobile

上图鲜明地体现了 flex:1flex:auto 的区别,虽然都是充分分配容器的尺寸,但是 flex:1 的尺寸表现更为内敛(优先牺牲自己的尺寸), flex:auto 的尺寸表现则更为霸道(优先扩展自己的尺寸)。

从某种程度上讲, flex:1 的表现神似 table-layout:fixedflex:auto 的表现神似 table-layout:auto

适合使用flex:1的场景

当希望元素充分利用剩余空间,同时不会侵占其他元素应有的宽度的时候,适合使用 flex:1 ,这样的场景在Flex布局中非常的多。

例如所有的等分列表,或者等比例列表都适合使用 flex:1 或者其他flex数值,适合的布局效果轮廓如下图所示。

QBna2i3.png!mobile

以及适用于无规律布局中动态内容元素,我们不妨继续使用 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 之后,按钮元素正常显示了。

zuuyaqm.png!mobile

适合使用flex:auto的场景

当希望元素充分利用剩余空间,但是各自的尺寸按照各自内容进行分配的时候,适合使用 flex:auto

flex:auto 多用于内容固定,或者内容可控的布局场景,例如导航数量不固定,每个导航文字数量也不固定的导航效果就适合使用 flex:auto 效果来实现,我做了个很简单的示意,代码如下所示:

<nav class="flex">
  <span>首页</span>
  <span>排行榜</span>
  <span>我的订单</span>
  <span>个人中心</span>
</nav>
nav span {
    <strong>flex: auto;</strong>
    line-height: 3rem;
    background: #444;
    color: #fff;
    text-align:center;
}
span + span {
    border-left: 1px solid #eee;
}

此时大家就可以看到一个基于内容自动分配宽度的自适应导航效果了,效果如下图所示,文字越多的导航占据的宽度越大,这完全是浏览器自动分配的。

myQreaf.png!mobile

三、最后总结一下

最后总结一下:

flex:initial
flex:0
flex:none
flex:1
flex:auto

以上就是本文内容,写于2020年国庆,部分内容节选自明年会出版的新书《CSS新世界》。

感谢您的阅读,如果您觉得本文内容还不错,欢迎分享。

UNreUf.png!mobile

本文为原创文章,欢迎分享,勿全文转载,如果实在喜欢,可收藏,永不过期,且会及时更新知识点及修正错误,阅读体验也更好。

本文地址: https://www.zhangxinxu.com/wordpress/?p=9541

(本篇完)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK