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

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

我们常常得用一堆其实本来不是这样用的属性来做 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. Redhat、CentOS添加静态路由的标准方法

    我们经常遇到需要在系统默认路由的基础上,额外添加静态路由的需求.为了使得下次系统启动这些静态路由依旧生效,我们可能采取在rc.loal里加入route命令追加静态路由的方法. 现在给大家推荐Redha ...

  2. js 方法封装实例

    (function(){ if(windows.Mr_2_B){windows.Mr_2_B={};} function trim(txt){return txt.replace(/(^\s*|(\s ...

  3. JavaACOFramework的各个类介绍(part3 : Ant4ACS类)

    package aco.ant; import java.util.ArrayList; import sys.Settings; import util.PseudoRandom; import a ...

  4. A python script to check NE syncfail and get log from CIPS

    #! /usr/bin/env python # -*- coding: UTF-8 -*- """The script is to check whether NE i ...

  5. BZOJ 4517: [Sdoi2016]排列计数

    4517: [Sdoi2016]排列计数 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 911  Solved: 566[Submit][Status ...

  6. 月薪3万的程序员告诉你:这样工作才能拿高薪(转 IT之家)

    习惯即刻回报 他不懂得只有春天播种,秋天才会有收获.刚刚付出一点点,甚至还没有付出,就想要得到回报.技术刚刚掌握,能一边百度一边干活了就觉得该拿到多少多少钱了.找工作先想着多少多少钱,入职了没干几个月 ...

  7. JavaScript中的数组遍历forEach()与map()方法以及兼容写法

    原理: 高级浏览器支持forEach方法 语法:forEach和map都支持2个参数:一个是回调函数(item,index,list)和上下文: forEach:用来遍历数组中的每一项:这个方法执行是 ...

  8. bootstrap-table填坑之旅<一>认识bootstrap-table

    应公司需求,改版公司ERP的数据显示样式.由于前期开发的样式是bootstrap,所以选bootstrap-table理所当然(也是因为看了bootstrap-table官网的example功能强大, ...

  9. HTML <a> download 属性,点击链接来下载图片

    Html5里面的 标签的 Download 属性可以设置一个值来规定下载文件的名称.所允许的值没有限制,浏览器将自动检测正确的文件扩展名并添加到文件 (.img, .pdf, .txt, .html, ...

  10. PBOC金融IC卡,卡片与终端交互的13个步骤,简介-第四组(转)

    十:联机处理-可选项终端根据卡片行为分析的结果,执行对应的处理.若卡片响应联机,则终端发起联机操作.联机处理使得发卡行后台可以根据基于后台的风险管理参数检查并授权批准或拒绝交易.除了传统的联机欺诈和信 ...