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

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

我们常常得用一堆其实本来不是这样用的属性来做 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 真的是个好东西?

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

参考:https://ruby-china.org/topics/23767

Flexbox,更优雅的布局的更多相关文章

  1. Flexbox弹性布局,更优雅的布局

    Flexbox,更优雅的布局 Flex 布局教程:语法篇 Flex 布局教程:实例篇 2009年,W3C提出了一种新的方案----Flex布局,可以简便.完整.响应式地实现各种页面布局.目前,它已经得 ...

  2. CSS 黑魔法小技巧,让你少写不必要的JS,代码更优雅

    首页   登录注册         CSS 黑魔法小技巧,让你少写不必要的JS,代码更优雅 阅读 8113 收藏 927 2017-09-26 原文链接:github.com 腾讯云容器服务CSS,立 ...

  3. PostCSS一种更优雅、更简单的书写CSS方式

    Sass团队创建了Compass大大提升CSSer的工作效率,你无需考虑各种浏览器前缀兼,只需要按官方文档的书写方式去写,会得到加上浏览器前缀的代码,如下: .row { @include displ ...

  4. 使用 Promises 编写更优雅的 JavaScript 代码

    你可能已经无意中听说过 Promises,很多人都在讨论它,使用它,但你不知道为什么它们如此特别.难道你不能使用回调么?有什么了特别的?在本文中,我们一起来看看 Promises 是什么以及如何使用它 ...

  5. async 更优雅异步体验

    上一篇<让 Generator 自启动>介绍了通过起动器让 Generator 跑起来,而本篇采用 async 实现更优雅的异步编程. 从例子开始 借用上一篇例子中的例子说起. funct ...

  6. [改善Java代码]集合运算时使用更优雅的方式

    在初中代数中,我们经常会求两个集合的并集.交集.差集等,在Java中也存在着此 类运算,那如何实现呢? 一提到此类集合操作,大部分的实现者都会说:对两个集合进行遍历,即可求出结果.是的,遍历可以实现并 ...

  7. Lambda表达式, 可以让我们的代码更优雅.

    在C#中, 适当地使用Lambda表达式, 可以让我们的代码更优雅. 通过lambda表达式, 我们可以很方便地创建一个delegate: 下面两个语句是等价的 Code highlighting p ...

  8. 使用Castle扩展Ibatis.Net,面向接口编程-更优雅的代码

    使用Ibatis.Net做项目半年了,甚是喜欢,感觉确实是个简单.轻巧的O/R Mapping框架,特别是将Sql配置在Xml文件中,相当于直接将Dao层抽离了出来. 本文假定读者对Ibatis.Ne ...

  9. 少年,是时候换种更优雅的方式部署你的php代码了

    让我们来回忆下上次你是怎么发布你的代码的: 1. 先把线上的代码用ftp备份下来 2. 上传修改了的文件 3. 测试一下功能是否正常 4. 网站500了,赶紧用备份替换回去 5. 替换错了/替换漏了 ...

随机推荐

  1. mybais整合的框架没有sql-debug输出

    将ibatis log4j运行级别调到DEBUG可以在控制台打印出ibatis运行的sql语句,方便调试: ### 设置Logger输出级别和输出目的地 ###log4j.rootLogger=deb ...

  2. linux 脚本小试系列

    实现100以内的奇数和和偶数和的脚本 1 #!/bin/bash 2 # #声明一个偶数变量和一个奇数变量 3 declare -i evensum=0 4 declare -i oddsum=0 # ...

  3. UVALive 3971 组装电脑

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...

  4. [Bug]枚举数组,并找到某些元素删除

    lldb报错:Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <_ ...

  5. 扩展卡尔曼滤波(MRPT)

    EKF relies on a linearisation of the evolution and observation functions which are good approximatio ...

  6. 定长循环队列C语言实现

    #ifndef _CONST_H_#define _CONST_H_ #include <stdio.h>#include <stdlib.h> typedef enum { ...

  7. 服务器上index.jsp变空

    早上,前五分钟3台分别浏览了3台服务器,都是正常的,一会后台说其中一台打开页面是空白的,发现这台服务器上的index.jsp文件变成了空白.用其他服务器上的index.jsp文件覆盖,蹦出了另一个错误 ...

  8. 《构建之法》8&16

    [8.1] 对产品的生命周期管理好像一直以来都没有引起我足够的重视,在这一段对产品学习的过程中也少有看到相关内容.是因为针对不同产品而言,产品周期的管理太具有个性特征,没有太统一的规则可循吗?我觉得不 ...

  9. 移动端上传图片iphone图片旋转以及服务端处理方法

    判断是否需要旋转 /**             *iphone判断图片方向,是否需要旋转图片             */            if(strpos($_SERVER['HTTP_U ...

  10. adeng朝花夕拾

    ============================C/C++基础拾遗===================================== 1.指针: 函数指针做函数参数 回调函数 语法现象 ...