译文:Flexbox 彻底指南 (A Complete Guide to Flexbox)


 

背景

Flexbox 布局 (Flexible Box) 模块 (目前是 W3C 的一个最后征集工做草案(Last Call Working Draft))旨在提供一种更有效的方式,在容器的项之间处理布局、对齐和空间分配,即便它们的大小未知而且/或是动态变化的(所以叫作“flex”)。 css

Flex 布局背后的主要思想是让容器可以改变其项的宽度/高度(和顺序),以最好地填充可用空间(主要是为了适应各类显示设备和屏幕大小)。一个 flex 容器扩大其项来填充可用的空闲空间,或者缩小它们以防止溢出。html

最重要的是,flexbox 布局与常规布局(基于垂直的块(block)、基于水平的内联(inline))截然相反,flexbox 布局是方向无关的。虽然常规布局工做很适合页面,但它们缺少灵活性(没有双关语)来支持大型或复杂的应用程序(特别是当涉及到方向变化、大小调整、拉伸、收缩等)时。
css3

注意:Flexbox 布局最适合应用程序的组件和小型布局,而网格布局则适合更大规模的布局。git

 

基础和术语

因为 flexbox 是一个完整的模块,而不是一个单独的属性,它涉及到不少东西,包括它的所有属性。其中一些是要在容器上设置的(父元素,称为“flex容器”),而其余的则是设置在子元素上(称为“flex项/元素”)。
若是常规布局是基于块(block)和内联(inline)流方向,那么 flex 布局则基于“flex流方向(flex-flow direction)”。 请看一看规范中的下图,其解释了 flex 布局背后的主要思想。

 基本上,弹性项(flex items)将沿着主轴(main axis)(从 main-start 到 main-end)或侧轴(cross axis)(从 cross-start 到 cross-end)布局。github

  • main axis - flex容器的主轴是主要的轴,flex项被沿其放置。小心,它不必定是水平的;这取决于 flex-direction 属性的值(见下)。
  • main-start | main-end - flex 项放在容器内,从 main-start 到 main-end。
  • main size - 一个弹性项的宽度或高度,任何一个在主维度上,就是这个项的主尺寸。flex 项的 main size 属性是“宽度”或“高度”属性之一,任何一个均可以是 main size。
  • cross axis - 垂直于主轴的轴称为横轴。它的方向取决于主轴方向。
  • cross-start | cross-end - Flex行充满了flex项,并将其放置到容器中,行开始于Flex容器的 cross-start 端,并向 cross-end 端方向前进。
  • cross size - 一个 flex 项的宽度或高度,任何一个在侧维度上,就是该项的 cross size。cross size属性是在侧维度上的“宽度”或“高度”中其一。

Properties for the Parentweb

(flex container)浏览器

Properties for the Childrenapp

(flex items)ide

 

# display

定义一个 flex 容器;inline 或 block 取决于给定的值。它为全部直接的子元素提供一个 flex 上下文。
    .container {
        display: flex; /* or inline-flex */
    }
注意,CSS 列对 flex 容器没有影响。
 

# flex-direction

肯定主轴, 用来定义 flex 容器中的 flex 项的放置方向。Flexbox 是(除了可选的 wrap)一个单向布局概念。能够将 flex 项看做主要是在水平的行或垂直的列中布局的。
    .container {
        flex-direction: row | row-reverse | column | column-reverse;
    }
 
  • row (default): 从左到右(若是元素的 dir 属性为 ltr);从右到左(若是元素的 dir 属性为 rtl)
  • row-reverse: 从右到左(若是元素的 dir 属性为 ltr);从左到右(若是元素的 dir 属性为 rtl)
  • column: 自上而下
  • column-reverse: 自下而上

# flex-wrap

默认状况下,flex 项都将尝试放置在一行上。你能够根据须要使用该属性来更改默认行为以支持换行。
    .container{
        flex-wrap: nowrap | wrap | wrap-reverse;
    }
 
  • nowrap (default): 全部 flex 项位于一行中
  • wrap: flex 项将从上到下多行排列
  • wrap-reverse: flex 项将从下到上多行排列
 

# flex-flow (适用于:父 flex 容器元素)

这是一个简化的 flex-direction 和 flex-wrap 属性,它们一块儿定义了 flex 容器的主和侧轴。默认是 row nowrap。
    flex-flow: <‘flex-direction’> || <‘flex-wrap’>
 

# justify-content

该属性定义了浏览器如何分配顺着父容器主轴的弹性元素之间及其周围的空间。它帮助分配剩余的空闲空间当不管在一行中的全部 flex 项是固定大小的仍是弹性的可是达到它们的最大尺寸的时候。 当它们溢出行时, 该属性也能这些项的对齐方式发挥一些控制做用。
    .container {
        justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
    }
 
  • flex-start (default): 从行首开始排列。每行第一个弹性元素与行首对齐,同时全部后续的弹性元素与前一个对齐
  • flex-end: 从行尾开始排列。每行最后一个弹性元素与行尾对齐,其余元素将与后一个对齐
  • center: 伸缩元素向每行中点排列。每行第一个元素到行首的距离将与每行最后一个元素到行尾的距离相同
  • space-between: 在每行上均匀分配元素;第一个元素位于行首,最后一个元素位于行尾
  • space-around: 元素在行内均匀分布,在元素周围的间距相等。注意,视觉上的间距不相等,由于全部元素在其两边都有相等的空白。第一个元素距离容器边缘有一个单位的空白,而元素之间有两个单位的空白由于下一个元素也有其本身的空白边距。
  • space-evenly: 元素到容器边缘及元素之间间距相等地均匀分布方式。
 

# align-items

该属性定义弹性元素沿当前行的侧轴方向上如何布局的默认行为。能够将其理解为 justify-content 应用于侧轴的版本(垂直于主轴)。
    .container {
        align-items: flex-start | flex-end | center | baseline | stretch;
    }
 
  • flex-start: 元素侧轴起点的边缘与行的侧轴起点对齐
  • flex-end: 元素侧轴终点的边缘与行的侧轴终点对齐
  • center: 元素在侧轴方向上居中对齐
  • baseline: 全部元素向基线对齐。侧轴起点到元素基线距离最大的元素将会于侧轴起点对齐以肯定基线
  • stretch (default): 弹性元素被在侧轴方向被拉伸到与容器相同的高度或宽度。(同时遵照 min-width/max-width 属性的设置

# align-content

该属性设置当在侧轴方向上有额外空间的时候弹性容器中行的对齐方式,相似于在主轴上 justify-content 属性对个体元素的对齐方式。
注意:该属性在弹性容器中仅有一行弹性元素的状况下没有效果。
    .container {
        align-content: flex-start | flex-end | center | space-between | space-around | stretch;
    }
 
  • flex-start: 全部行从侧轴起点开始填充。第一行的侧轴起点边和容器的侧轴起点边对齐。接下来的每一行紧跟前一行
  • flex-end: 全部行从侧轴末尾开始填充。最后一行的侧轴终点和容器的侧轴终点对齐。同时全部后续行与前一个对齐
  • center: 全部行朝向容器的中心填充。每行互相紧挨,相对于容器居中对齐。容器的侧轴起点边和第一行的距离相等于容器的侧轴终点边和最后一行的距离
  • space-between: 全部行在容器中平均分布。相邻两行间距相等。容器的侧轴起点边和终点边分别与第一行和最后一行的边对齐
  • space-around: 全部行在容器中平均分布,相邻两行间距相等。容器的侧轴起点边和终点边分别与第一行和最后一行的距离是相邻两行间距的一半
  • stretch (default): 拉伸全部行来填满剩余空间。剩余空间平均的分配给每一行
 

# order

默认状况下,flex 元素按源顺序排列。同时,order 属性能够控制它们在弹性容器中出现的顺序。
    .item {
        order: <integer>;
    }
 

# flex-grow

该属性定义弹性盒子项(flex item)的拉伸因子,它定义了一个 flex 项在必要时能够拉伸的能力。它接受一个无单位数值,做为一个比例。它规定了 flex 项在 flex 容器内可占据的可用空间的大小。
若是全部项的 flex-grow 属性都设置为 1,那么容器中的剩余空间将平均分配给全部的子元素。若是其中一个子元素的值为 2,那么其对剩余空间的占用将比其余项多一倍(或者至少尝试一下)。
    .item {
        flex-grow: <number>; /* default 0 */
    }
负值是无效的。
 

# flex-shrink

这定义了一个 flex 项在必要时收缩的能力。flex 元素仅在默认宽度之和大于容器的时候才会发生收缩,其收缩的大小是依据 flex-shrink 的值。
    .item {
        flex-shrink: <number>; /* default 1 */
    }
负值是无效的。
 

# flex-basis

这定义了在剩余空间被分配以前,元素的默认大小。它能够是一个长度(例如 20%,5rem 等)或一个关键字。auto 关键字的意思是“看个人 width 或 height 属性”(这是由关键字 main-size 临时完成的,直到废弃为止)。content 关键字的意思是“基于项中内容的大小调整尺寸” ———— 这个关键字尚未获得很好的支持,因此很难测试,也很难知道它的同胞属性 max-content、min-content 和 fit-content 是什么。
    .item {
        flex-basis: <length> | auto; /* default auto */
    }
若是设置为0,则不将内容周围的额外空间考虑在内。若是设置为 auto,额外的空间将基于它的 flex-grow 属性值分配。 查看此图
 

# flex

这是一个简写属性,能够同时设置 flex-grow, flex-shrink 与 flex-basis。第二和第三个参数(flex-shrink 和 flex-basis)是可选的。默认为 0 1 auto。
    .item {
        flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
    }
建议使用这个简写属性,而不是设置单个属性。
 

# align-self

这容许对单个 flex 元素覆盖默认对齐(或者由 align-item 指定的对齐)。
属性值请参考对 align-items 属性的解释。
    .item {
        align-self: auto | flex-start | flex-end | center | baseline | stretch;
    }
 
注意,float,clear 和 vertical-align 对弹性元素没有影响。

 

Examples

让咱们从一个很是简单的例子开始,解决一个几乎平常的问题:完美地居中。若是你使用 flexbox,那就不能再简单了。
.parent {
    display: flex;
    height: 300px; /* Or whatever */
}
.child {
    width: 100px;  /* Or whatever */
    height: 100px; /* Or whatever */
    margin: auto;  /* Magic! */
}
这就依赖于在 flex 容器中设置 “auto” 的 margin 吸取额外的空间。所以,设置一个垂直的 margin 为 auto,将使这个 flex 项完美地在两个轴上居中。
 
如今咱们来使用更多的属性。 考虑一个拥有6个元素的 list,全部元素都有一个固定的尺寸,在美学问题上,但它们能够是自动大小的。咱们但愿它们在水平轴上均匀地分布,这样当咱们调整浏览器的大小时,一切都很好(没有 media query!)。
.flex-container {
    /* We first create a flex layout context */
    display: flex;
 
    /* Then we define the flow direction and if we allow the items to wrap
     * Remember this is the same as:
     * flex-direction: row;
     * flex-wrap: wrap;
     */
    flex-flow: row wrap;
 
    /* Then we define how is distributed the remaining space */
    justify-content: space-around;
}
完成。其余的都只是一些样式的问题。 下面是本例在 CodePen 上的一个 pen。必定要去CodePen,试着调整你的窗口大小,看看会发生什么。
 
 
让咱们试试别的。假设咱们在咱们的网站上有一个右对齐的导航,但咱们但愿它在中等大小的屏幕上居中对齐,而在小的设备上是单列的。很是简单。
/* Large */
.navigation {
    display: flex;
    flex-flow: row wrap;
    /* This aligns items to the end line on main-axis */
    justify-content: flex-end;
}
/* Medium screens */ @media all and (max-width: 800px) { .navigation { /* When on medium sized screens, we center it by evenly distributing empty space around items */ justify-content: space-around; } }
/* Small screens */ @media all and (max-width: 500px) { .navigation { /* On small screens, we are no longer using row direction but column */ flex-direction: column; } }
 
 
让咱们利用弹性元素的灵活性来尝试一些更有趣的事情。一个移动优先(mobile-first)的带有全宽(full-width)页头和页脚的三列布局怎么样,而且独立于源顺序。
.wrapper {
    display: flex;
    flex-flow: row wrap;
}
/* We tell all items to be 100% width */ .header, .main, .nav, .aside, .footer { flex: 1 100%; }
/* We rely on source order for mobile-first approach * in this case: * 1. header * 2. nav * 3. main * 4. aside * 5. footer */

/* Medium screens */ @media all and (min-width: 600px) { /* We tell both sidebars to share a row */ .aside { flex: 1 auto; } }
/* Large screens */ @media all and (min-width: 800px) { /* We invert order of first sidebar and main * And tell the main element to take twice as much width as the other two sidebars */ .main { flex: 2 0px; } .aside-1 { order: 1; } .main { order: 2; } .aside-2 { order: 3; } .footer { order: 4; } }

https://codepen.io/team/css-tricks/pen/jqzNZqsvg

 

Flexbox 前缀

Flexbox 须要一些供应商(vendor)的前缀来支持尽量多的浏览器。它不只包含带有供应商前缀的前置修饰属性,还包括实际上彻底不一样的属性和值名。这是由于 Flexbox 规范已经随着时间的推移而改变,建立了一个 “旧的”、“过渡的”和“新的”版本。
也许处理这一问题的最好方法是编写新的(和最终的)语法,并经过  Autoprefixer 运行您的CSS,它可以很好地处理回退问题。
或者,这里有一个 Sass 的 @mixin 来帮助处理一些前缀,这也让你知道须要作些什么:
@mixin flexbox() {
    display: -webkit-box;
    display: -moz-box;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: flex;
}
@mixin flex($values) {
    -webkit-box-flex: $values;
    -moz-box-flex: $values;
    -webkit-flex: $values;
    -ms-flex: $values;
    flex: $values;
}
@mixin order($val) {
    -webkit-box-ordinal-group: $val;
    -moz-box-ordinal-group: $val;
    -ms-flex-order: $val;
    -webkit-order: $val;
    order: $val;
}
.wrapper {
    @include flexbox();
}
.item {
    @include flex(1 200px);
    @include order(2);
}

 

相关文章

其余资源

Bugs

Flexbox 固然不是没有它的 bug/缺陷/issue。我目前所看到的最好的关于它们的收集是 Philip Walton 和 Greg Whitworth 的  Flexbugs。这是一个用来追踪全部 bug/缺陷/issue 的开放源代码的地方,因此我认为最好只是将它连接在此。
 

浏览器支持

根据 flexbox 的“版本”拆分:
  • (new) 表示规范中最新的语法(例如 display: flex;)
  • (tweener) 这是2011年以来的一种怪异的非官方语法(例如 display: flexbox;)
  • (old) 表示从2009开始的旧的语法(例如 display: box;)
Chrome
Safari
Firefox
Opera
IE
Android
iOS
20- (old)
3.1+ (old)
2-21 (old)
12.1+ (new)
10 (tweener)
2.1+ (old)
3.2+ (old)
21+ (new)
6.1+ (new)
22+ (new)
11+ (new)
4.4+ (new)
7.1+ (new)
 
有关如何混合语法以得到最佳浏览器支持的更多信息,请参考  this article (CSS-Tricks) 或者  this article (DevOpera)。黑莓浏览器 10+ 支持新语法。
相关文章
相关标签/搜索