Home >Web Front-end >HTML Tutorial >Flexbox,更优雅的布局_html/css_WEB-ITnose

Flexbox,更优雅的布局_html/css_WEB-ITnose

WBOY
WBOYOriginal
2016-06-21 08:52:23952browse

上个周末,在北航新主楼会议厅里举行了首届 CSS 开发者大会,GitCafe 的前端工程师 Jaych Su 在会上做了演讲,与大家分享了一款更优雅的前端布局——Flexbox。现在,我们就邀请他来为大家讲一下 Flexbox 的相关知识吧~

在设计的眼中,排版的操作是一件很简单的事情,靠左、置中、靠右,我只要点一下,所有元素,就会乖乖的到指定的位置。

但到了前端在排版的实现上,就不是这样了。

我们常常得用一堆其实本来不是这样用的属性来做 hack,比如说用 line-height 来做垂直置中,这样做的确能达到效果,但是在语意上就有点不顺,拿刚刚提到的 line-height 来说,这本来是用来当作段落中的行距,但却因为这个属性能扩展文字的上下空间,结果也被拿来做垂直置中。那有没有一个方法能用来更好地实现 Web 布局呢?

这是 Google 的 Angular。他们几个月前做了一套 UI 来实现在 Angular 上的 Material Design。这套框架用来实现布局的方式,不是以往的 float,而是用了 Flexbox。

Flexbox 是什么呢?就 W3C 官方给到的解释是,这是设计来实现更复杂的版面布局。那我自己对他的定义是,Flexbox 从本质上就是一个 Box-model 的延伸,我们都知道 Box-model 定义了一个元素的盒模型,然而 Flexbox 更进一步的去规范了这些盒模型之间彼此的相对关系。而不需要去用一些很 cheat 的做法,去 hack 一些本来其实不应该用来做版面布局的属性。

身为一个喜欢去玩一些新东西的前端,应该说每个跟互联网有所接触的人,都需要去学新东西。

这是我碰到新东西的时候,一定会问自己的三个问题:

1. 这能做什么?也就是他能解决什么问题?

2. 能用在哪裡?在哪些地方能用这个方法?

3. 为什么能用?他实现所用到的逻辑是什么?

接下来就跟大家分享一下,当初看到 Flexbox 的我问了自己这个三个问题之后,到目前为止我找到的答案。

功能

举一个例子,所有前端都会有的痛点,置中,我们以前是怎么实现的?

最常看到就是用绝对定位,然后把 top 和 left 偏移 五零%,在用 margin 偏移回去。但是这只适用在已经固定大小的元素。

最近几年常看到的做法是这样,在想置中的元素之前,加上一个元素,不想管太旧的 IE 的话,甚至伪元素也可以。在容器用 text-align,然后把底下的两个元素弄成 inline 的形式,在用 vertical-align。他的好处就是,即使底下的元素会随内容改变大小,但不管怎么改变,就是可以始终维持垂直和水平置中。

当然啦,还有很多置中的方法,就不一一介绍了,我们来看一下用 flex 的话怎么置中。

用 Flex 来做置中的话,你可以很从容地做到置中,不用一堆即使本来不是这样用的属性。我只要先指定容器为一个 Flex 容器,然后 justify-content 让他水平方向置中,再 align-items 让他垂直方向置中。我可以很简单很优雅的就做到置中。

那也许你会说,欸?既然一个可以的话,那我再多放几个可不可以?其实可以的。

假设我们现在容器底下有三个元素,喔,这裡就要提到 Flexbox 另外一个屌炸天的功能。

假设一个元素是四零%,另一个是一二%,那在一个 Flex 容器中,只要你有设定 flex-grow 这项属性的话,他的第三个元素就会自适应宽度,填满剩下容器的空白。而在多个元素的状态之下,我们仍然能很轻易的就置中。

刚刚我们提到过,flexbox 是用来规范盒模型之间的相对关系,从这裡你就可以看到。现在我将 justify-content 设成 space-around,元素就会变成已分散对齐的方式去分佈在 flex 容器中。

关于元素的分步,我们再来看几个例子。

这是一个我最近看到的网站。我们可以看到他底下有一个 Slider,这有个问题,而且也常常是前端在版面上的一个痛点,我们想让所有的子元素能够等高。在以前我们很难只用 CSS 去做到这样。

而 flexbox 可以很轻易地只用 CSS 做到这点。只需要在 flex 容器加上 align-items 就好。就能实现容器底下的所有元素,与最高的那个元素等高。

即使我在本来最高的那个元素多加一些内容,其他的元素也一定会维持等高。

兼容

Flex 最初被 W3C 于 09 年制定出来,随后就被大量的讨论。拿指定元素为一个 flex 容器来讲,第一个版本裡是 display:box,第二个版本是 display: flexbox,第三个版本是 display: flex。实在太复杂,还好现在在开源的世界里已经有大大把这三个版本的 flex 做成一些 mixin,使用的时候,你只要 include 进来就可以。

就跟 IE 的使用体验一样,所有的好东西跟 IE 基本都沾不上边,所以如果你需要考虑 IE 用户,那请慎入。所以有人说 IE 的功能只剩下用来下载 Chrome 和 Firefox。

原理

如果你到网上搜 flex,大多都会著墨在 他的对齐、他的控制 DOM 顺序是如何如何好用。但今天我们想聊一聊更深一点的东西,flex item 宽度的计算,大多数情况下,我们只在意显示的比例,这也是宽度的计算比较少被讨论的原因,但如果你想要更精确的控制 item 的显示宽度,其实你是需要去了解,在一个 flex 容器当中,item 的宽度是如何被计算出来的。

当我们把一个容器指定为 flex 容器时,它裡面的 item 其实是有著这样的设定:flex: 0 1 auto

这三个数字其实分别代表:flex-grow、flex-shrink、flex-basis,这三个属性可以说是 flex 之所以智能的原因。

我们先来聊聊 flex-basis 好了,这个属性在 flex 容器为横向的时候,其实就是宽度,当我们把 item 指定成 flex: 0 0 480px 时,其实就是把它的宽度设定成 480px。但是这样并不能表现出 flex 有什么特别的地方啊?为什麽要重複设定宽度?

这时候就要讲到另外两个属性:flex-grow、flex-shrink

这两个属性其实是双胞胎,grow 表示在 item 总宽度比容器小的时候,为了让 item 填满容器,每个 item 增加的宽度。假设有三个 basis 为 100px 的 item。我们从左到右给予 grow 值分别为 3、2、1,那么当 flex 作用之后,最左边的 item 实际增加的宽度是多少?从图中可以算到增加的宽度是 90px,于是最后最左边 item 的宽度是 190px。

我们刚才提到 grow 跟 shrink 其实是双胞胎,其实他们真的很像,shrink 表示在 item 总宽度比容器大的时候,为了让 item 填满容器,每个 item 减少的宽度。但是计算的公式却是不一样的。为什么?因为当你在加的时候无所谓,但是在减的时候,如果只计算赋予的 shrink 值,那么很有可能最后减少的宽度比 basis 大,于是 item 的宽度就变成负值。那我们该怎么修正?把 basis 当成参数计算进去,这样就能保证减少的宽度永远小于 basis。所以我们可以得到修正后的公式,一样以最左边为例子,最后计算出来减少 60px,于是 item 就变成 140px。以上脑子不好使,没关系,实际上最常用的只是 flex: 1。

讲到这里,你刚刚讲的好像这东西很厉害的样子,那你有没有一个最快最简单粗暴的方式去说 Flexbox 真的是个好东西?

嗯⋯⋯有点难,不过我想应该可以。

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn