一点点对 flex 布局有关的看法

1,703 阅读6分钟

从早期版本的 Flexible Box 开始,到现在这个版本的 Flexible Box,在所谓的语法上出现了一些变化,属性名好像都不一样了。记得以前是叫 display: flexbox; 到现在的 display: flex;,还有 box-flex 到现在的 flex,对于之前的并没有过多的了解,当然,对于现在的这个 flex 我了解的也并不多,只知道写法上可能会有一些区别,原理上应该相差不多。

不过久远的属性应该也不用去关心了,就想想现在大家都在玩的这个 flex 吧。相信很多人都会对 flex 布局做一些研究,然后写博客记录,想想这感觉真好,以前很少有这样的,现在大家“写”博客频率比几年前高了很多啊,找资料随便搜一下就有一堆。

然而,我想说,写了博客之后,真的大概了解了,并且大概记住了?

个人觉得并不一定。

情节一

A:“我看你的博客上写了对 flex 布局的总结,挺长的,也挺好的。”
B:“嗯,是的,毕竟现在浏览器对 flex 的支持都挺不错的。”
A:“是啊,现在微信小程序中都推荐直接使用 flex 布局来做。那么你觉得 flex: 1 0 auto; 这个属性是应该放在父级元素呢还是子级元素?”
B 简单思考了一下,道:“父级元素的”

现在想想这个也并没有错,子级元素其实也是可以作为父级元素存在的,所以,是的, 放在父级元素中

但是,我怎么就记得 flex: 1 0 auto; 这样的东西应该是在父级元素有 display: flex; 后才会有效呢。吓得我赶紧翻一下 CSS 手册:

适用于:flex子项

哦,还好还好,没记错什么东西。父级元素要有 display: flex; 后,然后子级元素中的 flex: 1 0 auto; 这样的才会有效果。

情节二

A:“嗯,刚说了一下 flex 是在父级元素还是子级元素中有效的问题,那么这几种的写法有没有区别呢?如果有,那么它们之间的区别是什么呢?”

flex: 1 0 auto;
flex: 0 1 auto;
flex: 1 0 60%;
flex: 1 0 200px;
flex: 0 1 200px;

B:“这个似乎有一些区别,都是用来做弹性布局的,但具体有什么区别我不知道。”

这个要怎么说呢,感觉这个深究下去,似乎是一篇很长的文章,简单来说呢,应该是这样吧。

拆解 flex 属性

首先可以很明确的一点,flex 属性是一个复合属性,其中包含了三个属性,分别是:

  • flex-grow

  • flex-shrink

  • flex-basis

flex 的写法是这样的:

flex:none | <’ flex-grow ‘> <’ flex-shrink >’? || <’ flex-basis ‘>

那么现在只要知道 flex-growflex-shrink 以及 flex-basis 的区别,就应该没有什么问题了。理论上是这样的。

none
none关键字的计算值为: 0 0 auto
<' flex-grow '>
用来指定扩展比率,即剩余空间是正值时此「flex子项」相对于「flex容器」里其他「flex子项」能分配到空间比例。
在「flex」属性中该值如果被省略则默认为「1」
<' flex-shrink '>
用来指定收缩比率,即剩余空间是负值时此「flex子项」相对于「flex容器」里其他「flex子项」能收缩的空间比例。
在收缩的时候收缩比率会以伸缩基准值加权
在「flex」属性中该值如果被省略则默认为「1」
<' flex-basis '>
用来指定伸缩基准值,即在根据伸缩比率计算出剩余空间的分布之前,「flex子项」长度的起始数值。
在「flex」属性中该值如果被省略则默认为「0%」
在「flex」属性中该值如果被指定为「auto」,则伸缩基准值的计算值是自身的 <’ width ‘> 设置,如果自身的宽度没有定义,则长度取决于内容。

以上属性介绍摘录自 doyoe 整理的 CSS 手册(http://css.doyoe.com/properties/flex/flex.htm),具体的也可以通过点击下面的“阅读原文”去看。

只要理解了上面几个值的介绍,那就真的大概上没有什么问题了。

几个简单 demo 效果

先来一个 HTML 结构:

(.flex_wrap.flex_wrap$>.items{$}*4)*4

这个应该大家都能看得懂吧,最终大概是这样的四个 div 包含着的元素。

<div class="flex_wrap flex_wrap1">
  <div class="items">1</div>
  <div class="items">2</div>
  <div class="items">3</div>
  <div class="items">4</div>
</div>

有了结构,然后就应该要有样式了,来一个总的样式。

.flex_wrap {
 display: flex;
 height: 100px;  
 padding: 10px;  
 margin-bottom: 20px;  
 background-color: rgba(255,0,0,.3);  
 border-bottom: 2px solid #666;  
 border-radius: 0 0 5px 5px;
}
.items {
 height: 100%;  
 margin: 0 5px;
}
.items:nth-child(1) {
 background-color: #fff;
}
.items:nth-child(2) {
 background-color: #0f0;
}
.items:nth-child(3) {
 background-color: #ff0;
}
.items:nth-child(4) {
 background-color: #0ff;
}

这里的 display: flex; 没有去考虑不同浏览器的问题,只是为了快速简单展示一个效果,如果需要考虑这些兼容性的写法,那么可以用 autoprefix 来完成新旧属性以及其他浏览器前缀的增加。

情况一

/* flex wrap 1 */
.flex_wrap1 .items:nth-child(1),
.flex_wrap1 .items:nth-child(2),
.flex_wrap1 .items:nth-child(4) {
 flex: 1 0 auto;
}
.flex_wrap1 .items:nth-child(3) {
 flex: 1 0 60%;
}

情况二

/* flex wrap 2 */
.flex_wrap2 .items:nth-child(1),
.flex_wrap2 .items:nth-child(2),
.flex_wrap2 .items:nth-child(4) {
 flex: 0 1 auto;
}
.flex_wrap2 .items:nth-child(3) {
 flex: 0 1 60%;
}

情况三

/* flex wrap 3 */
.flex_wrap3 .items:nth-child(1),
.flex_wrap3 .items:nth-child(2),
.flex_wrap3 .items:nth-child(4) {
 flex: 1 0 10%;
}
.flex_wrap3 .items:nth-child(3) {
 flex: 1 0 200px;
}

情况四

/* flex wrap 4 */
.flex_wrap4 .items:nth-child(1),
.flex_wrap4 .items:nth-child(2),
.flex_wrap4 .items:nth-child(4) {
 flex: 0 1 100px;
}
.flex_wrap4 .items:nth-child(3) {
 flex: 1 0 200px;
}

简单小结

这几种 flex 属性值的组合,可以看到的最终情况是不同的,具体是为什么,在 CSS 手册中有对属性详细的介绍,这里只是简单做一个对比。

不过好像一张张图片分开来对比不够明显,那么我们看一下这四种情况在一起时的一个对比,相信会明显很多。



怎么说呢,其实有时候我个人感觉,如果只是一列的话,就跟使用 float 或者 position 方式来做几列定宽几列自适应的布局方式很相近。效果对比是有了,如果各位还是觉得不够明显的话,那么就只有自行测试对比了哦。




闲扯CSS的那些事儿,没啥事儿就谈谈CSS
不深入,只扯淡
扯点自己想说的,或许也是你想听的,没有高深的东西,但应该不是平庸的……