理解CSS3 max/min-content及fit-content等width值

这篇文章发布于 2016年05月20日,星期五,02:06,归类于 CSS相关。 阅读 139934 次, 今日 50 次 48 条评论

 

一、为何要蹦出这些新玩意?

在CSS3的世界里,width属性又多了几个关键字成员,fill-available, max-content, min-content, 以及fit-content

想必很多小伙伴都没见过。不知大家有没有跟我一样的感觉,去厕所蹲了个大号,再回到办公室就会遇到之前没见过的前端新特性。

像我这种只学HTML和CSS都有些应接不暇,我想,那些CSS3, HTML5, ES6/ES7, React, Angular, bootstrap, postcss, node都会的小伙伴,应该每天都只睡3-4个小时吧,好厉害!

凡是存在就有其道理。那为何规范里要给稀松常见的width属性加几个关键字呢?

大家说我是先讲各个属性值表示的含义,还是先讲讲为什么要弄这些新属性值呢?

一番深思熟虑,我决定……先讲讲兼容性……

宽度尺寸兼容性

基本上,移动端已经可以愉快地使用了。

据我测试,目前还离不开私有前缀,例如:

.min-content {
    width: -webkit-min-content;
    width: -moz-min-content;
    width: min-content;    
}

好了,要开始往深的地方讲了。

虽然,作为名词fill-available, max-content, min-content, 以及fit-content都是新鲜面孔,但是,实际上,在CSS2.1的时候,就有类似的尺寸概念……

二、CSS2.1的尺寸体系

在CSS2.1的世界中,常见的尺寸分为这几类:
1. 充分利用可用空间
例如,一些div元素默认宽度100%父元素,这种充分利用可用空间的行为就称为“fill-available”。

2. 收缩与包裹
典型代表就是浮动,绝对定位以及inline-block,英文称为“shrink-to-fit”,直译为“收缩到合适”,这种直译往往都是不准确的,这种行为表现确实很难描述,有些只可意会不能言传的感觉,而我自己一直以“包裹性”作为理解。在CSS3中有个专有的关键名称,fit-content.

3. 收缩到最小
这个基本上就出现在table-layoutauto的表格中,想必有经验的小伙伴一定见过下面这样一柱擎天的盛况的吧!

表格一柱擎天截图示意

大家空间都不够的时候,文字能断的就断,中文是随便断的,英文单词不能断。于是乎,第一列被无情地每个字都断掉,形成一柱擎天。这种行为称之为“preferred minimum width”或者“minimum content width”。

也就是本文的重点角色之一min-content,换了一个更加规范好听的名字了。实际上,大家也看到了,min-content这种尺寸特性,display:table-cell实际上就有,但是,由于没有明确的名词或概念,大家都不知道,都是稀里糊涂有此表现,究其根本就不清楚了。

4. 超出容器限制
上面1~3情况,除非有明确的width相关设置,否则尺寸都不会主动超过容器宽度的,但是,存在一些特殊情况,例如,连续的英文数字,好长好长;或者内联元素被设置了white-space:nowrap,则表现为一江春水向东流。

例如下面:

.box {
    display: inline-block;
    width: 100px; height: 20px; 
    padding: 10px;
    background-color: #f0f3f9;
    white-space: nowrap;
}

尺寸主动超过容器宽度,恰如一江春水向东流。

max-content的表现与之有些类似,具有收缩特性,同时最大内容宽度。

// ——— 有必要来根低调的分隔线 ———-

好了,至此,大家会发现,fill-available, max-content, min-content, 以及fit-content确实在CSS2.1的时候,就有类似概念。

下面问题来了,既然CSS2.1这些特性都有了,那还要额外弄一些新值过来干嘛呢?岂不是白白增加学习成本啊?

我认为有3个好处:

  1. 方便某些布局的实现;
  2. 最重要的作用: 在原有的display水平不变的情况下拥有元素其他display值才有的特性!
  3. 让整个CSS世界的size体系更加直观和完善;

我们下面不妨一边了解下各个width值的作用和表现,一边验证我上面所说的好处!

三、理解width:fill-available

width:fill-available比较好理解,比方说,我们在页面中扔一个没有其他样式的<div>元素,则,此时,该<div>元素的width表现就是fill-available自动填满剩余的空间。也就是我们平常所说的盒模型的margin,border,padding的尺寸填充。

出现fill-available关键字值的价值在于,我们可以让元素的100%自动填充特性不仅仅在block水平元素上,其他元素,例如,我们一直认为的包裹收缩的inline-block元素上:

div { display:inline-block; width:fill-available; }

此时,元素兼具了块状元素的自动填充特性以及内联元素的定位对齐等特性。于是,(例如)我们就可以直接使用line-height让一个块状表现的元素垂直居中。

您可以狠狠地点击这里:CSS3 width:fill-available下的垂直居中demo

块状元素尺寸表现内联元素垂直居中行为

完整关键CSS代码如下:

.box {
    height: 200px; 
    /* 行高控制垂直居中 */
    line-height: 200px;
}
.fill-available {
    /* 元素内联,响应行高和vertical-align控制 */
    display: inline-block;
    vertical-align: middle;
    
    /* 宽度如块状元素般表现 */
    width: -webkit-fill-available;
    width: -moz-fill-available;
    width: -moz-available;    /* FireFox目前这个生效 */
    width: fill-available;
}

正如上面注释所提到的,FireFox浏览器下,目前(2016-05-20)不是标准的-moz-fill-available,而是-moz-available,估计过个几个版本可能会调整过来。

四、理解width:max-content

max-content的行为表现可以这么理解,假设我们的容器有足够的宽度,足够的空间,此时,所占据的宽度是就是max-content所表示的尺寸。

不懂没关系,我们看一个对比示例,保证立马就知道!

您可以狠狠地点击这里:CSS3 width:max-content对比测试demo

这是一个display:inline-blockwidth:max-content的对比demo,如果妹子下面的文字描述短,大家是看不出区别的。但是,如果文字内容像demo所展示的这么长,嘻嘻嘻嘻~~

周星驰 笑

会发现,width:max-content表现得好像设置了white-space:nowrap一样,文字一马平川下去,元素的宽度也变成了这些文字一行显示的宽度!为什么会这么表现呢?定义就是这样的,对吧,我们对照下,首先,假设我们的容器有足够的空间,你想呀,容器足够空间,那下面的描述文字肯定一行显示了,此时,上面的图片和下面的文字那个内容宽度大,自然是文字啦,所谓max-content就是值采用宽度大的那个内容的宽度。

max-content的表现对比示意

五、理解width:min-content

min-content宽度表示的并不是内部那个宽度小就是那个宽度,而是,采用内部元素最小宽度值最大的那个元素的宽度作为最终容器的宽度。

首先,我们要明白这里的“最小宽度值”是什么意思。替换元素,例如图片的最小宽度值就是图片呈现的宽度,对于文本元素,如果全部是中文,则最小宽度值就是一个中文的宽度值;如果包含英文,因为默认英文单词不换行,所以,最小宽度可能就是里面最长的英文单词的宽度。So,大家明白的说。

还没完全弄懂没关系,我们看一个对比例子,您可以狠狠地点击这里:CSS3 width:min-content对比demo

同样的是和display:inline-block做比较,display:inline-block虽然也具有收缩特性,但宽度随最大长度长的那一个(同时不超过可用宽度)。而width:min-content的最终宽度是图片和文字最小宽度值里面大的那一个。

在本例子中,图片的宽度最小值是256像素,不能再缩了;而文字的最小宽度值是字符display:inline-所占据的宽度,因为inline-block后面的block可以换行,中文不用谈,天生被换行的命,显然display:inline-所占据的宽度要远远小于256像素,因此,最终我们元素的宽度就是256像素,肉眼看到的就是自适应图片宽度的一个效果。在CSS2.1的世界里,这种效果实际上是不好实现的,要借助单元格特性。

没有图片文字的最小宽度值

下图为对比效果截图:

min-content下的对比效果截图

六、理解width:fit-content

width:fit-content也是应该比较好理解的,“shrink-to-fit”表现,换句话说,和CSS2.1中的float, absolute, inline-block的尺寸收缩表现是一样的。

OK,然后,有小伙伴会疑问,既然跟很多CSS声明有一样的表现,那为什么还要再弄个新东西呢?

就拿水平居中效果举例,首先浮动肯定不行,因为只有左浮动和右浮动;绝对定位压根不占据空间,普通流中根本无法应用,而inline-block需要父级使用text-align:center,而本身可能还需要text-align:left略烦。

width:fit-content可以没有这些烦恼,因为,width:fit-content可以实现元素收缩效果的同时,保持原本的block水平状态,于是,就可以直接使用margin:auto实现元素向内自适应同时的居中效果了。

您可以狠狠地点击这里:CSS3 width:fit-content使用与margin auto下水平居中demo

结果,简简单单就居中了,也不要担心其他元素会跟在后面一行显示了:

收缩表现下margin:auto居中效果

七、结束语

CSS中的元素尺寸分为两类,一类叫做“内部尺寸”,英文写作”Intrinsic Sizing”,尺寸由内部元素决定;还有一类叫做“外部尺寸”,英文写作”Extrinsic Sizing”,宽度由外部元素决定。

考考大家:
fill-available, max-content, min-content, fit-content这4个关键字,哪个是“内部尺寸”,哪个是“外部尺寸”呢?

看本文之前难度90,看完本文之后,难度10. 如果你觉得还是很难,建议再看一遍,然后不断递归。

好了,其他废话就不多说了,感谢阅读,欢迎交流!

(本篇完)

分享到:


发表评论(目前48 条评论)

  1. 喜欢学芝士的某某说道:

    max-content的表现与之有些类似,具有收缩特性,同时最大内容宽度。
    如何在css2中让父元素包裹住 内容超出自己的子元素(no-wrap)呢?

  2. ruya说道:

    IE中怎么和 fitContent 类似的效果呢, 我想实现 文字过长时, 容器宽度被max-width 控制着, 不长时,由文本内容决定

  3. Andy说道:

    ie都不支持,有啥意义

  4. 飘过~~~~说道:

    技术变化太快,深感转行才是正路。

  5. solo说道:

    哎,三句话讲完,讲了这么多废话。直接讲核心,省博主时间,也省阅读者的时间呀。

  6. ynchuan说道:

    fill-available 外部尺寸
    max-content 内部尺寸
    min-content 内部尺寸
    fit-content 外部尺寸+内部尺寸

  7. 八里说道:

    第四部分的事例里面加个overflow 就好了, 我以为那行字会超出父元素的宽度

  8. ubbcou说道:

    fill-availabele:设置的这个元素表现相当于没有设置样式的div,宽度自动充满父级
    max-content:设置了这个属性的元素,会自动伸展或者收缩宽度,使自身宽度和最大宽度的子元素宽度一致
    min-content:设置了这个属性的元素,会自动伸展或者收缩宽度,使自身宽度和最小宽度的子元素宽度一致

    是这个理吧 :)

  9. kevin说道:

    小小反饋:
    的範例中
    垂直置中並不是因為.box設定的line-hight,而是因為.fill-available有vertical-aiign: middle唷

    • 光源说道:

      vertical-align:middle的作用机制就是对齐基线,这里之所以要设置line-height(最关键的)就是要让首行匿名元素(空白节点)处于父容器基线左右的位置,然后内联元素设置了vertical-align:middle才会对齐这个节点,否则是无效的!!!!

  10. tolerious说道:

    .box {
    height: 200px;
    /* 行高控制垂直居中 */
    line-height: 200px;
    }
    .fill-available {
    /* 元素内联,响应行高和vertical-align控制 */
    display: inline-block;
    vertical-align: middle;

    /* 宽度如块状元素般表现 */
    width: -webkit-fill-available;
    width: -moz-fill-available;
    width: -moz-available; /* FireFox目前这个生效 */
    width: fill-available;
    }

    第一个例子中好像加不加width为fill-avaiable的属性进去, 表现形式都是一样的。

    • 胖子说道:

      你试试把文字都删了,现在之所以一样是因为文字把父元素撑开了。

    • 光源说道:

      display: inline-block元素默认是fit-content,你如果不加上fill-available的话,红色背景应该是不会填充的

  11. 王尖儿说道:

    个人觉得只有fit-available是外部尺寸;其余三个,都是根据内部内容来决定自己的宽度!!

  12. 阳阳说道:

    赞一个,我觉得答案是fill-available和fit-content 是外部尺寸,max-content和min-content 是内部尺寸;fit-content自己测试当下面的文字超出父元素最大宽度时,文字会换行显示。

    • 光源说道:

      你所指的父元素最大宽度是什么意思?自己设置的值么?这个似乎不是评判内外部尺寸的依据。。。

  13. Grubby说道:

    六、理解width:fit-content
    这一章的demo里面box的div那段代码少了个text-align:center

    https://github.com/GrubbyHunter

  14. kiwi说道:

    感谢大神,没事就会来看您的博客,循序渐进地看,因为有的内容比较深目前还不适合看~ 今天这篇又涨姿势了,我会继续努力!感谢!

  15. 贰撸子说道:

    犀利的 一匹

  16. wendy说道:

    一直做移动端的页面,张老师多谢移动端分享啊

  17. 倾译说道:

    看你写的东西,真的学到了很多,真心感谢

  18. Eliza说道:

    fill-available是Extrinsic Sizing,max-content,min-content 和fit-content 是Intrinsic Sizing;
    今天看了《css揭秘》,第36条讲的width:min-content; margin: auto来居中~

  19. 小少说道:

    感谢大神!最后留的问题,我觉得答案是fill-available是外部尺寸,max-content,min-content 和fit-content 是内部尺寸,不知道对不对

  20. CSSer说道:

    请教
    a.btn:active

    a:active.btn

    都可以执行,有什么差异?

  21. 刘东奇说道:

    等这些属性逐步普及之后,前端的开发难度应该会降低不少吧

  22. 墨丶水瓶说道:

    哈哈 ,万年不变的张含韵 I 服了 You

  23. 萌萌的小山山说道:

    跟着大神学习了。有个么几个问题:width:fill-available和width:100%有什么区别?max-content有什么实际用途?min-content和fit-content我觉得还是挺有用的

  24. levomm说道:

    fill-available和fit-content是外部尺寸、min-width和max-width是内部尺寸。对吧?

  25. 小夭说道:

    fill-available, max-content外部尺寸,min-content, fit-content内部尺寸。
    好文章,赞赞赞

  26. distu说道:

    “去厕所蹲了个大号,再回到办公室就会遇到之前没见过的前端新特性”
    —>233333,笑尿了

  27. 可爱的麦尼玛说道:

    膜拜大神,又涨姿势了

  28. 夏至说道:

    哈哈。张老板 第一句带有严重的鄙视啊。。。 哈哈哈。不过俺们喜欢。那些 react,node … 都会的小伙伴。确实好厉害。。。。

  29. weining说道:

    da shen zong neng gei wo men fen xiang hen duo you yong de dong xi
    gan xie

  30. 小黑牛说道:

    张鑫旭大神
    你怎么这么牛逼呢
    我基本没事的话 都会看你的博客
    赞!!

  31. 一汀烟雨说道:

    好东西啊,等于是每个元素都增加了好几项技能。

  32. meepo说道:

    棒就一个字,我只说三次。棒棒

  33. kyle说道:

    博主分享的知识都很不错。

    哈哈,还是张含韵的铁粉。