资讯专栏INFORMATION COLUMN

Flexbox完全指南(译)

pekonchan / 1439人阅读

摘要:本文译自这里,针对本文介绍的属性列个提纲伸缩容器属性伸缩项目属性以后再布局时可以考虑用啦背景布局模块目前上一次工作草案的叫法旨在提供一种更高效的方式来布局排列及分配容器中项目的空间,即便容器大小是未知或动态变化的因此称为。

本文译自 A Complete Guide to Flexbox
这里,针对本文介绍的属性列个提纲:
伸缩容器属性

display

flex-direction

flex-wrap

flex-flow

justify-content

align-items

align-content

伸缩项目属性

order

flex-grow

flex-shrink

flex-basis

flex

align-self

以后再布局时可以考虑用flexbox啦~~

背景

Flexbox 布局(Flexible Box)模块(目前W3C上一次工作草案的叫法)旨在提供一种更高效的方式来布局、排列及分配容器中项目的空间,即便容器大小是未知或动态变化的(因此称为“flex”)。

Flex布局的主要思想是使容器具备改变其子项目的宽度或高度的能力,以此充分填充可用空间(主要是为了适应各种显示设备和屏幕尺寸)。使用flex布局的容器能扩展其子项目来填满可用空间,也能缩小他们以防止溢出容器。

Flex布局与常规布局相比,最主要的是它是方向无关的(常规布局通常是块级元素从上到下布局,行内元素从左到右布局)。尽管常规布局对于页面布局十分好用,但却缺少对大型或复杂应用的灵活性支持(尤其是当涉及到取向改变,尺寸调整,拉伸,收缩等场景时)。

注意:Flexbox布局主要适用于应用的组件以及小规模的布局,对于那些较大规模的布局网格布局更适用。

基本概念&术语

Flexbox是一整个模块,并非单一的一个属性,它涉及的东西比较多,包括一系列属性。其中一些属性是用在容器(父元素,即伸缩容器)上的,其他一些属性则是用在子元素(伸缩项目)上的。

如果说常规布局是基于块与行内元素的流向的,那么flex布局则是基于“flex流向”的。请看来自w3c规范中的这张图,解释了flex布局的主要思想:

通常,伸缩项目的布局要么按照主轴(main axis)方向,从主轴起点(main-start)到主轴终点(main-end),要么按照交叉轴(cross axis)方向,从交叉轴起点(cross-start)到交叉轴终点(cross-end)。

主轴(main axis) - 伸缩容器的主轴,是伸缩项目布局遵循的主要方向。注意:这个方向不一定是水平方向;它取决于“flex-direction”属性的值(见下文);

主轴起点(main-start) | 主轴终点(main-end ) - 伸缩项目置于容器中,从主轴起点(main-start)到主轴终点(main-end);

主体大小(main size) - 伸缩项目的宽度或高度就是主体大小,不管主维度是哪个。伸缩项目的主体大小要么是‘width’属性,要么是‘height’属性,不管主维度是哪一个。

交叉轴(cross axis) - 与主轴垂直的轴称为交叉轴(cross axis), 它的方向取决于主轴(main axis)的方向;

交叉轴起点(cross-start) | 交叉轴终点(cross-end) - 伸缩行填充着伸缩项目,并放置于伸缩容器中,从伸缩容器交叉轴起点开始,沿着交叉轴终点方向;

交叉方向大小(cross size) – 伸缩项目的宽度或高度就是交叉方向的大小,不管交叉维度是哪一个。交叉方向大小属性要么是交叉轴维度的宽度要么是交叉轴维度的高度。

父元素(伸缩容器)属性

display

display属性用来定义伸缩容器,容器是行内元素或者块元素取决于给定的值,这个属性开启了容器内所有直接子元素的flex上下文。
CSS:

.container {
    display: flex; /*or inline-flex*/
}

注意:CSS columns对于伸缩容器没有作用。

flex-direction

这个属性建立了主轴方向,定义了伸缩项目在伸缩容器内排列的方向。Flexbox是一个单一方向布局的概念。可以认为伸缩项目或者沿水平方向或者沿垂直方向布局。
CSS:

.container {
    flex-direction: row | row-reverse | column | column-reverse;
}

row(默认值): 在‘ltr’排版中从左到右,‘rtl’排版中从右到左;

row-reverse: "ltr"中从右到左,‘ltr’中从左到右;

column: 与row属性一样,但是是从顶部到底部;

column-reverse: 与row-reverse一样,但是是从底部到顶部。

flex-wrap

默认情况下,伸缩项目会尽量排成一行。当然,可以根据需要让伸缩项目换行来改变它。此时,方向也很重要,它决定了下一行堆叠的方向。
CSS:

.container {
    flex-wrap: nowrap | wrap | wrap-reverse;
}

nowrap(默认):单行模式/"ltr"中从左到右,"rtl"中从右到左;

wrap: 多行模式/"ltr"中从左到右,"rtl"中从右到左

wrap-reverse: 多行模式/"ltr"中从右到左,"rtl"中从左到右;

flex-flow(适用于:伸缩容器,也就是父元素)

这是"flex-direction"和 "flex-wrap"属性的快捷形式,它同时定义了伸缩容器的主轴和交叉轴。默认值是row nowrap。
CSS:

flex-flow: <"flex-direction"> || <"flex-wrap">
justify-content

justify-content定义了沿着主轴的排列方式。当一行中的所有伸缩项目都不能再伸缩时,或者能伸缩但已经达到了自身最大尺寸时,这个属性负责分配剩余的自由空间。同时它也能在溢出时对排列元素进行一定的控制。
CSS:

.container {
    justify-content: flex-start | flex-end | center | space-between | space-around
}

flex-start(默认值):伸缩项目朝着起点方向紧凑排列;

flex-end: 伸缩项目朝着终点方向紧凑排列;

space-between: 伸缩项目在一行中平均分配,第一个项目在起点处,最后一个项目在终点处;

space-around: 伸缩项目两侧的空间保持相等,在一行中平均分配。值得注意的是在视觉上,一个项目两边的空间是不相等的,因为所有项目都是在自身的两边分配了相等的空间。第一个项目在容器边缘分配得到一份空间,但是第二个项目的左边会分得两份空间,因为它自身的也有一份分配的空间。

align-items

align-items定义了伸缩项目沿着交叉轴当前方向的布局方式。可以把它看成交叉轴方向的justify-content版本。
CSS:

.container {
    align-items: flex-start | flex-end | center | baseline | stretch;
}

flex-start: 伸缩项目的起点放置在交叉轴线的起点上;

flex-end: 伸缩项目的终点放置在交叉轴线的终点上;

center: 伸缩项目置于交叉轴线的中心;

baseline: 伸缩项目按照他们的基线排列;

stetch(默认): 拉伸以填满容器(仍然遵循min-width/max-width)

align-content

align-content定义了伸缩容器当在交叉轴上有多余空间时的排列线,和主轴方向上justify-content排列伸缩项目类似。
注意:这个属性在只有一行伸缩项目时无效。
CSS:

.container {
    algin-content: flex-start | flex-end | center | space-between | space-around | stretch;
}

flex-start: 紧邻容器起始排列;

flex-end: 紧邻容器终点排列;

center: 排列在容器中间;

space-between: 平均分配,第一行在容器起始处而最后一行在容器末尾处;

space-around: 平均分配,每行两边距离相等;

stretch(默认值): 拉伸项目来占据剩余空间;

子元素属性(伸缩项目)

order

默认情况下,伸缩项目按照文档流出现的先后顺序排列。但order属性可以控制在伸缩容器内的显示顺序。
CSS:

.item {
    order: ;
}
flex-grow

flex-grow定义了伸缩项目必要时扩展的能力。它接受一个无单位的值作为比例。它指定了伸缩容器内伸缩项目能伸展的可用空间的大小。

如果所有伸缩项目的flex-grow属性设置为1,容器中剩余空间会被均等分配给所有子元素。如果一个子元素的flex-grow设置为2,那么它占据的剩余空间中会是其他子元素占据空间的两倍。
CSS:

.item {
    flex-grow: ; /*default 0*/
}

负数无效。

flex-shrink

flex-shrink定义了伸缩项目根据需要收缩的能力。

.item {
    flex-shrink: ; /*default 1*/
}

负数无效。

flex-basis

定义了元素在剩余空间被分配之前的默认大小。它的值可以是长度(例如20%, 5rem等),也可以是关键词。"auto"表明元素的大小取决于元素的宽度或高度属性(临时由main-size属性决定)。"content"表明元素大小取决于伸缩项目内容的大小-目前尚不支持,因此max-content,min-content,fit-content这些兄弟属性较难测试和分析。
CSS:

.item {
    flex-basis:  | 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

允许默认对齐方式(或者由align-items定义的对齐方式)能被单个伸缩项目覆盖。
CSS:

.item {
    align-self: auto | flex-start | flex-end | center | baseline | stretch;
}

注意:float,clear,vertical-align属性对伸缩项目没有作用。

Examples

我们先从一个非常简单的例子开始,解决一个最常见的问题:居中。使用flexbox你会发现简直不能更容易了。
CSS:

.parent {
    display: flex;
    height: 300px; /*Or whatever*/
}
.child {
    width: 100px; /*Or whatever*/
    height: 100px; /*Or whatever*/
    margin: auto; /*Magic! */
}

这依赖于一个特性:伸缩容器里的元素的margin值如果设置了"auto",能自动均衡容器中剩余的空间。所以在垂直方向也设置了auto后,能使得伸缩项目在两个轴线方向上都完美居中。

现在,让我们来使用更多属性。考虑有一个有6个条目的列表,每一个都是固定大小的,但他们可以被调整大小的。我们希望它们能平均地分布在水平轴上,这样当我们调整浏览器时,依然能良好地显示(不使用媒体查询)。

.flex-container {
    /*首先创建一个伸缩容器*/
    display: flex;
    /*然后定义伸缩流方向,并且伸缩项目能换行
    * 记住这个设置等同于下面这两个设置:
    * flex-direction: row;
    * flex-wrap: wrap;
    */
    flex-flow: row wrap;
    /*然后定义剩余空间如何分配*/
    justify-content: space-around;
}

好了。剩下的仅仅是样式的问题了。
下面是一个阐述这个属性的具体例子。试试去CodePen上查看,再调整浏览器窗口看看会发生什么。
HTML:

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

SCSS:

@import "compass/css3";

.flex-container {
  padding: 0;
  margin: 0;
  list-style: none;
  
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  
  -webkit-flex-flow: row wrap;
  justify-content: space-around;
}

.flex-item {
  background: tomato;
  padding: 5px;
  width: 200px;
  height: 150px;
  margin-top: 10px;
  
  line-height: 150px;
  color: white;
  font-weight: bold;
  font-size: 3em;
  text-align: center;
}

这是在PC正常显示屏幕下的效果(浏览器宽度约为1190px)的效果:

缩小浏览器,6个盒子的排列会随浏览器宽度的大小进行调整,这是浏览器宽度小于约700px时的效果:

随着浏览器继续缩小,最终6个盒子会变为逐个纵向排列的布局形式。

再试试别的属性。设想网站顶部有一个靠右对齐的导航,我们希望它在中等大小的屏幕和单一栏目的小屏幕上都居中显示。非常容易:
CSS:

/* 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;
  }
}

具体示例代码:
HTML:

SCSS:

@import "compass/css3";

.navigation {
  list-style: none;
  margin: 0; 
  
  background: deepskyblue;
  
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  
  -webkit-flex-flow: row wrap;
  justify-content: flex-end;
}

.navigation a {
  text-decoration: none;
  display: block;
  padding: 1em;
  color: white;
}

.navigation a:hover {
  background: darken(deepskyblue, 2%);
}

@media all and (max-width: 800px) {
  .navigation {
    justify-content: space-around;
  }
}

@media all and (max-width: 600px) {
  .navigation {
    -webkit-flex-flow: column wrap;
    flex-flow: column wrap;
    padding: 0;
  }
  
  .navigation a { 
    text-align: center; 
    padding: 10px;
    border-top: 1px solid rgba(255,255,255,0.3); 
    border-bottom: 1px solid rgba(0,0,0,0.1); 
  }

  
  .navigation li:last-of-type a {
    border-bottom: none;
  }
}

上述示例结果图:

缩小浏览器,宽度小于等于600px时:

现在让我们再尝试一下伸缩项目上的属性!比如一个手机上的三栏布局,其中头部和尾部占据全屏。并且不管它们在文档流的顺序。
CSS:

.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; }
}

具体示例代码:
HTML:

Header

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.

Footer

SCSS:

@import "compass/css3";

.wrapper {
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;  
  
  -webkit-flex-flow: row wrap;
  flex-flow: row wrap;
  
  font-weight: bold;
  text-align: center;
}

.wrapper > * {
  padding: 10px;
  flex: 1 100%;
}

.header {
  background: tomato;
}

.footer {
  background: lightgreen;
}

.main {
  text-align: left;
  background: deepskyblue;
}

.aside-1 {
  background: gold;
}

.aside-2 {
  background: hotpink;
}

@media all and (min-width: 600px) {
  .aside { flex: 1 auto; }
}

@media all and (min-width: 800px) {
  .main    { flex: 3 0px; }
  .aside-1 { order: 1; } 
  .main    { order: 2; }
  .aside-2 { order: 3; }
  .footer  { order: 4; }
}

body {
  padding: 2em; 
}

上述示例结果图:

缩小浏览器,宽度小于等于600px时:

Flexbox 前缀

Flexbox需要书写较多的前缀以支持大多数浏览器下的显示。这里指的不仅仅包括(在属性前)加入浏览器的前缀,实际上还包含加入其它一些不一样的属性和属性值。这是因为Flexbox规范一直在向前发展,先后创建了"old", "tweener"和"new"几个版本。

也许更好的处理办法是使用新语法,并通过Autoprefixer来运行你的CSS。

这里给出一个Sass @mixin的示例可以帮助解决一些前缀问题,或许可以给你提供一些思路:
SCSS:

@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);
}
相关属性

A Complete Guide to Grid

Almanac entries on Grid properties, like grid-row / grid-column

其它资源

Flexbox in the CSS specifications

Flexbox at MDN

Flexbox at Opera

Diving into Flexbox by Bocoup

Mixing syntaxes for best browser support on CSS-Tricks

Flexbox by Raphael Goetter (FR)link

Flexplorer by Bennett Feely

Bugs

Flexbox 并非没有bug. 我看过的最好的收集这方面bug的是Philip Walton and Greg Whitworth的Flexbugs。 这是一个开源的跟踪问题的地方。

浏览器支持

这个要区分一下flexbox的版本:

(new)表明规范上最新的语法(例如:display:flex;);

(tweener)表明是2011年旧版的非官方语法(例如:display: flexbox;);

(old)表明是2009年旧版语法(例如:display:box)。

Blackberry浏览器10+支持新版语法。
更多关于如何混合使用语法来最好地让flexbox得到浏览器的支持,请参考这篇文章或这篇

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/115345.html

相关文章

  • CSS及布局

    摘要:经过半年的打磨,正式发布,主要是新增了一些常用组件,并使用命名,为接下来的微信小程序开发做好准备。这两种方式实现的瀑布流式布局均支持首屏和网页窗口大小改变时的列数自适应。主要是对于标准里的布局方式草案中的布局方式进行一些总结。 一劳永逸的搞定 flex 布局 寻根溯源话布局 一切都始于这样一个问题:怎样通过 CSS 简单而优雅的实现水平、垂直同时居中。记得刚开始学习 CSS 的时候,看...

    jaysun 评论0 收藏0
  • [] Grid 布局完全指南

    摘要:如果你定义的内容包含重复部分,你可以使用标记去组织它。另外,也有一个比较复杂但是方便的语法指定三个属性,示例如下与以下代码是等价的因为无法隐式重置属性,与。 简介 CSS 栅格布局 (亦称 Grid),是一个基于栅格的二维布局系统,旨在彻底改变基于网格用户界面的设计。CSS 一直以来并没有把布局做的足够好。刚开始,我们使用 tables,后来是 floats,positioning 和...

    Baoyuan 评论0 收藏0
  • 小技巧 - 收藏集 - 掘金

    摘要:然而学习布局,你只要学习几个手机端页面自适应解决方案布局进阶版附源码示例前端掘金一年前笔者写了一篇手机端页面自适应解决方案布局,意外受到很多朋友的关注和喜欢。 十分钟学会 Fiddler - 后端 - 掘金一.Fiddler介绍 Fiddler是一个http抓包改包工具,fiddle英文中有欺骗、伪造之意,与wireshark相比它更轻量级,上手简单,因为只能抓http和https数据...

    A Loity 评论0 收藏0
  • 面试宝典

    摘要:有谈谈面试与面试题对于前端面试的一些看法。动态规划算法的思想及实现方法帮大家理清动态规划的解决思路以及原理方法前端经典面试题从输入到页面加载发生了什么这是一篇开发的科普类文章,涉及到优化等多个方面。极客学院前端练习题道练习题,面试季练练手。 由数据绑定和排序引入的几个 JavaScript 知识点 在 JavaScript 的数据绑定和做简单的表格排序中遇到的几个知识点 [[JS 基础...

    neu 评论0 收藏0

发表评论

0条评论

pekonchan

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<