Flexbox完全指南[译]

2016-11-17  本文已影响107人  evelynlab

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

伸缩项目属性

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

背景

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

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

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

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

基本概念&术语

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

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

flexbox-eg1.jpg

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

flexbox-eg2.jpg

随着浏览器继续缩小,最终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:

<ul class="navigation">
  <li><a href="#">Home</a></li>
  <li><a href="#">About</a></li>
  <li><a href="#">Products</a></li>
  <li><a href="#">Contact</a></li>
</ul>

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

上述示例结果图:

flexbox-eg3.jpg

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

flexbox-eg4.jpg

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

<div class="wrapper">
  <header class="header">Header</header>
  <article class="main">
    <p>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.</p>  
  </article>
  <aside class="aside aside-1">Aside 1</aside>
  <aside class="aside aside-2">Aside 2</aside>
  <footer class="footer">Footer</footer>
</div>

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

上述示例结果图:

flexbox-eg5.jpg

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

flexbox-eg6.jpg

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

相关属性

其它资源

Bugs

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

浏览器支持

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

浏览器兼容性.png

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

上一篇下一篇

猜你喜欢

热点阅读