Flex Layout 详解

栏目: Html · 发布时间: 5年前

内容简介:总想写flex,却一直拖——拖——拖,今天算是写完了。与以往的文章不同,这篇文章更像是写给自己看的,所以有些术语不会再解释,如看不懂,可以先去这篇文章里看看术语.简单的说,flex container的每个孩子都是一个flex item,而每个flex item都是一个flex-level box,另外,由于在计算computed value时flex item会发生块级化,因此每个flex item也是一个block container。而对于没有html元素包裹的连续文字,会被自动包裹在一个匿名的blo

总想写flex,却一直拖——拖——拖,今天算是写完了。与以往的文章不同,这篇文章更像是写给自己看的,所以有些术语不会再解释,如看不懂,可以先去这篇文章里看看术语.

Flex Container

  1. display为flex的元素会产生一个flex container,该container在正常流内以block-level的形式存在。

  2. display为inline-flex的元素会产生一个flex container,该container在正常流内以inline-level的形式存在。

  3. 每个flex container都会为它的内容建立一个flex formatting context,这与block container为它的内容建立一个block formatting context很类似。但是,flex container并不是block container, 诸如:

  • float和clear在flex container里面无效(也就是flex item即使设置了float和clear也不起作用)

  • vertical-align在flex item上也不起作用

  • flex container的margin不会与它的内容的margin重叠

  • ::first-line和::first-letter伪元素在flex container上不起作用

注意:当元素为绝对定位元素、浮动元素或根元素时,display属性值的computed value的计算规则参照下表
Specified value Computed value
inline-table table
inline, table-row-group, table-column, table-column-group, table-header-group, table-footer-group, table-row, table-cell, table-caption, inline-block block
inline-flex flex
others same as specified

Flex Item

简单的说,flex container的每个孩子都是一个flex item,而每个flex item都是一个flex-level box,另外,由于在计算computed value时flex item会发生块级化,因此每个flex item也是一个block container。而对于没有html元素包裹的连续文字,会被自动包裹在一个匿名的block container flex item里。

释1: 块级化 —— 尽管有的flex item的display属性值为inline,但是在计算computed value时,也会被设为block.

释2: block container ——该box只能包含block-level box或是建立一个inline formatting context且只能包含inline-level box

1. flex item为绝对定位元素

因为为绝对定位元素,所以该flex item会脱离流。效果就如同该flex item的static position box(在计算绝对定位元素位置时,会先假设它的position为static,处于正常流中,然后得出一个static position,再依据这个static position去定位。)为flex container的content box。也就是该flex container里面只有该flex item的static position box,这个flex container是个匿名的flex container。

例1:

div.parent {
display: flex;
width: 1000px;
height:400px;
border: solid 2px rgba(75, 234, 12, 0.7);
border-radius: 8px;
}
div.parent > div {
border-radius: 8px;
flex: 1 1 auto;
color: #fff;
text-align: center;
line-height: 200px;
font-size: 26px;
}
div.first-child {
width: 200px;
height: 200px;
background-color: rgb(64, 166, 249);
}
div.second-child {
width: 400px;
height: 200px;
background-color: rgb(255, 141, 75);
}
复制代码
<div class="parent">
<div class="first-child">first-child</div>
<div class="second-child">second-child</div>
</div>
复制代码

效果如下:

Flex Layout 详解

现在为div.first-child加上绝对定位。div.first-child改为:

div.first-child {
Width: 200px;
height: 200px;
background-color: rgb(64, 166, 249);
position: absolute;
}
复制代码

效果如下:

Flex Layout 详解

选中div.second-child可以看到,它的宽度独占1000px。

Flex Layout 详解

如果给绝对定位flex item加上align-self: center,它会处于它所在的flex container的交叉轴的中心位置。修改div.first-child如下:

div.first-child {
width: 200px;
height: 200px;
background-color: rgb(64, 166, 249);
position: absolute;
align-self: center;
}
复制代码

效果如下:

Flex Layout 详解

而一旦为绝对定位flex item设置了top/bottom,它就会参照第一个父级定位元素去移动,align-self也就失效了。现在设置div.parent为相对定位元素,修改成:

div.parent {
display: flex;
Width: 1000px;
height:400px;
border: solid 2px rgba(75, 234, 12, 0.7);
border-radius: 8px;
position:relative;
}
复制代码

为div.first-child设置偏移量,修改如下:

div.first-child {
width: 200px;
height: 200px;
background-color: rgb(64, 166, 249);
position: absolute;
align-self: center;
left: 50px;
top: 50px;
}
复制代码

效果如下:

Flex Layout 详解

对比上图,可以看到交叉轴上div.first-child距离div.parent的上边缘只有上图的一半,也就是50px,同时div.first-child距离div.parent的左边缘也是50px。

2. flex item的margin和padding

  • 相邻的flex item的margin不会重叠(flex container的margin也不会与flex item的margin重叠)。
  • margin和padding若设置为百分比,则百分比是基于flex container的inline size(若writing mode是horizontal,则inline size为宽度;若mode是vertical,则inline size 为高度 )。

例子:

div.parent {
display: flex;
flex-wrap: wrap;
width: 400px;
height: auto;
background-color: rgba(15, 241, 170, 0.42);
border-radius: 8px;
margin-top: 50px;
}
div.parent > div {
border-radius: 8px;
flex: 1 1 auto;
color: #fff;
text-align: center;
line-height: 200px;
font-size: 26px;
}
div.first-child {
width: 200px;
height: 200px;
background-color: rgb(64, 166, 249);
margin-top: 50px;
margin-bottom: 50px;
}
div.second-child {
width: 400px;
height: 200px;
background-color: rgb(255, 141, 75);
margin-top: 50px;
}
复制代码

效果如下:

Flex Layout 详解

可以看到div.parent距离root box的上边缘有50px,而div.first-child的上边缘距离div.parent的上边缘也有50px,他们并没有重叠。div.first-child及div.second-child的margin-top也没有重叠。

如果div.parent的display为block,并且div.parent及div.first-child的border宽度均为0,它和div.first-child的margin-top会发生重叠。修改div.parent如下:

div.parent {
display: block;
width: 400px;
height: auto;
background-color: rgba(15, 241, 170, 0.42);
border-radius: 8px;
margin-top: 50px;
}
复制代码

效果如下:

Flex Layout 详解

鼠标定位到div.parent上,可以看到它的margin-top和div.first-child的margin-top确实重叠了。同理,div.first-child与div.second-child的margin-top也重叠了。

Flex Layout 详解

3. 折叠的flex item

  1. Flex item可以设置visibility: collapse,达到折叠的效果。效果类似于table的行折叠。
  2. Flex item即使折叠了,但依然有个隐形的空壳存在,为的是保证flex container的cross size的稳定。如果flex container仅有一个flex line(每条flex line上按main size方向依次摆放flex item,类似于line box),那么某个flex item折叠可能会影响flex container 的main size,但是不会影响flex container的cross size。
  3. 尽管折叠的flex item不会被渲染,但依然会出现在dom 树上。为了计算折叠的flex item的那个空壳的大小,在dom树形成的过程中,flex layout 会先假设所有item都没有折叠,然后在由dom树形成渲染树的过程中,会将折叠的flex item用一个保留了原始的cross size的空壳替换掉。

例子:

div.collapse-example {
  display: flex;
  > ul.nav {
    height: auto;
    margin: 0;
    margin-right: 20px;
    > li {
      margin-bottom: 5px;
      border-radius: 4px;
      text-align: center;
      font-size: 18px;
      display: flex;
      flex-flow: column;
    }
    > li:target,
    > li:hover {
      cursor: pointer;
      > a {
        border-top-left-radius: 8px;
        border-top-right-radius: 8px;
        font-weight: bold;
      }
      > ul {
        border-radius: 8px;
      }
      a {
        color: #343434 !important;
      }
    }
    > li:not(:target):not(:hover) > ul {
      height: 0;
      overflow: hidden;
      visibility: collapse;
    }
  }
  ul {
    padding: 0 10px;
    > li {
      list-style: none;
    }
  }
}
复制代码
<div className="collapse-example">
        <ul class="nav">
          <li>
            <a href="#">About</a>
            <ul>
              <li>
                <a href="#">introduction</a>
              </li>
              <li>
                <a href="#">blog</a>
              </li>
            </ul>
          </li>
          <li>
            <a href="#">Product</a>
            <ul>
              <li>
                <a href="#">book</a>
              </li>
              <li>
                <a href="#">beautiful-closes</a>
              </li>
            </ul>
          </li>
          <li>
            <a  href="#">Contact</a>
            <ul>
              <li>
                <a href="#">email</a>
              </li>
              <li>
                <a href="#">weixin</a>
              </li>
            </ul>
          </li>
        </ul>
        <article id="main">
            This is an Example 
        </article>
      </div>
复制代码

效果如下:

Flex Layout 详解

鼠标移到菜单上,子菜单会显示出来

4. flex item的automatic minimum size

min-width和min-height有了一个新的初始化值,即auto,表示自动设置的min size。

对于flex item,当min-width或min-height的specified value设置为auto,相应的used value是基于内容来设置的。这个值怎么定呢?

对于min-width,一般,取主轴上width的specified value与主轴上min-content size(一个box的最小size,该size不会导致overflow)的较小值; 如果主轴上width没有specified value, 但是有个ratio且交叉轴上width设置了specified value,则根据ratio及交叉轴width的specified value得出一个转换后的size,再取这个size和主轴上min-content size的较小值;如果既没有设定主轴width的specified value有没有ratio,那么直接取主轴上min-content size。

同理min-height。

通常,automatic minimum size取值合理,但是如果是以下情况,还是为min size设置一个具体的值比较好。

  1. 当flex item的content是一篇较大的文档,给min-width或min-height设置成字体相关的值比较好,例如min-width: 12em。使用 automatic minimum size会导致溢出。
  2. 当flex item有较多的孩子节点时,automatic minimum size的取值需要基于min-content size, 而 layout engine为了找到min-content size需要一一遍历所有的孩子节点,有损性能。如果直接给min size设置specified value,就不必去找min-content size了。

注意:ratio表示一个元素的width与height的比例关系,一般通过给padding-top设定百分比来表达一个固定比例。

aspect ratio padding-top value
1:1 100%
16:9 56.25%
4:3 75%
3:2 66.66%
8:5 62.5%

定向和排序

flex container的内容可以按照一定的方向和顺序排列。主要依靠flex container的flex-direction和flex-wrap以及flex item的order。

但是有点需切记,不可依靠flex-direction/flex-wrap 的-reverse值 以及order来代替flex item的原本顺序,会影响页面的可访问性。

1. flex-direction

Name: flex-direction   Value: row | row-reverse | column | column-reverse   Initial: row  Applies to: flex containers  Inherited: no  Percentages: n/a

2. flex-wrap

Name: flex-wrap   Value: nowrap | wrap | wrap-reverse   Initial: nowrap   Applies to: flex containers   Inherited: no   Percentages: n/a

flex: nowrap表示flex container为单行,内容大小超出则调整flex item的大小以免溢出。

Flex Layout 详解

flex: wrap 表示在内容过多时flex container会换行

Flex Layout 详解

flex: wrap-reverse 表示在内容过多时flex container会换行,但cross-start及cross-end方向调换。

Flex Layout 详解

3. Order

Name: order  Value:   Initial: 0  Applies to: flex items  Inherited: no  Percentages: n/a

order可以设置flex item的位置。 这些flex item会在文档顺序的基础上再基于order属性值进行再排序,然后按照再 排序 的结果渲染出来。如果某些flex item的order值相同,则按照它们在文档里的顺序渲染。

例子:

div.parent {
display: flex;
width: 400px;
height: auto;
border: solid 2px rgba(15, 241, 170, 0.42);
border-radius: 8px;
}
div.parent > div {
border-radius: 8px;
flex: 1 1 auto;
color: #fff;
text-align: center;
line-height: 200px;
font-size: 26px;
}
div.first-child {
width: 200px;
height: 200px;
background-color: rgb(64, 166, 249);
}
div.second-child {
width: 400px;
height: 200px;
background-color: rgb(255, 141, 75);
order: -1;
}
复制代码

效果如下:

Flex Layout 详解

灵活性

1. flex-grow

当一个flex line还有多余的空间可扩展,这些空间如何分配给该行的flex item呢?用flex-grow, 它用来设置某个flex item可扩展多少比例的多余空间。取值为number,默认为0。

2. flex-shrink

当一个flex line的空间不足,这些缺失的空间如何分担给该行的flex item呢?用flex-shrink,它表示某个flex item需要缩小多少比例的空间,取值为number,默认为1。

3. flex-basic

定义了分配多余空间(可为正数亦可为负数)前该flex item所占的main size,浏览器会根据该值来计算主轴上的多余空间。可设定如下属性值:

  • auto: 当specified value为auto时,按如下步骤取值。 第一步:采用的used value为flex item的main size(即主轴上的width或height的属性值), 第二步:如果这个used value依然为auto,那么used value 会基于 flex item的content 得到一个具体值。
  • content: 基于flex item的content得到一个automatic size。
  • <width>: 和width或height的设置方式一样,可设为<length> 或 <percentage>

默认值为auto。当主轴为水平方向,设置了flex-basic,则flex item的width值会失效。例如,如果某个flex item的flex-basic设为0,则把该flex item的宽度视为0,即使它本身width为100px,这个100px也会被纳入多余空间中,供flex inline的所有flex item一起分配。

4. flex

flex属性为flex-grow flex-shrink flex-basic的缩写,默认值为0 1 auto,可设定的值为:

  • initial: 0 1 auto,当有多余空间时,没有弹性;当空间不足时,flex item可以缩小。
  • auto: 1 1 auto,flex会有充足的弹性
  • none: 0 0 auto, flex会完全没有弹性
  • <positive-number>: 1 auto
  • <flex-grow> <flex-shrink> <flex-basic>: 若flex-grow省略了,默认值取1;若flex-shrink省略了,默认值取1;若flex-basic省略了,默认值取0。

通常,flex item不会缩小到比min content sizes还要小。为防万一,我们可以为flex item设置min-width或min-height。

对齐

1. 使用auto margin对齐

  • 如果设置了flex-grow,auto margin 会被设置为0;若设置了flex-basis,没有设置flex-grow,那么在主轴方向上,根据flex-basis计算出的多余的空间都会分配给auto margin
  • auto margin的优先级高于justify-content及align-self,轴上任何多余的空间(不包括负的空间)都会分配给auto margin。
  • 如果box在某个轴上发生溢出了,则auto margin会被忽略,且box在该轴的尾部溢出。(如果既有auto margin, 又有justify-content/align-self/align-items,依然是忽略justify-content/align-self/align-items,采用auto margin,只不过此时因为overflow,接着会忽略auto margin, 在轴的尾部溢出)

总的来说,当存在auto margin时,又有多余的空间(不包括负的空间),则优先级如下:

flex-grow > auto margin > justify-content/align-self/align-items

如果box在轴上只剩下负的空间(即溢出),则auto margin被忽略。

例子:

div.parent {
display: flex;
flex-wrap: nowrap;
justify-content: center;
width: 1000px;
height: auto;
border: solid 5px rgba(15, 241, 170, 0.42);
border-radius: 8px;
}
div.parent > div {
border-radius: 8px;
flex: 1 1 auto;
color: #fff;
text-align: center;
line-height: 200px;
font-size: 26px;
}
div.first-child {
width: 200px;
height: 200px;
background-color: rgb(64, 166, 249);
margin-left: auto;
}
div.second-child {
width: 400px;
height: 200px;
background-color: rgb(255, 141, 75);
}
复制代码

现在div.parent的justify-content设为center, div.first-child及div.second-child设置了flex: 1 1 auto(其中flex-grow: 1, flex-shrink: 1, flex-basis: auto); 同时div.first-child设置了margin-left为auto,效果如下:

Flex Layout 详解

可以看到div.first-child及div.second-child均扩展了,justify-content及auto margin没起作用。

现在设置div.first-child及div.second-child的flex为0 1 auto,修改如下:

div.parent > div {
border-radius: 8px;
flex: 0 1 auto;
color: #fff;
text-align: center;
line-height: 200px;
font-size: 26px;
}
复制代码

效果如下:

Flex Layout 详解

可以看到,剩余空间都被div.first-child的auto margin-left 占据了。

现在去掉div.first的auto margin,修改如下:

div.first-child {
width: 200px;
height: 200px;
background-color: rgb(64, 166, 249);
}
复制代码

效果如下:

Flex Layout 详解

现在,justify-content起作用了。

2.justify-content对齐

justify-content用来设置flex-item在主轴上的对齐方式。

Name: justify-content  Value: flex-start | flex-end | center | space-between | space-around  Initial: flex-start  Applies to: flex containers  Inherited: no

效果如下:

Flex Layout 详解

3. align-items和align-self

align-items定义了flex container中flex-item在交叉轴上的对齐方式,有点类似justify-content,是针对所有flex item。

align-self定义了某个flex item在交叉轴上的对齐方式,会覆盖align-items的值。

Name: align-items  Value: flex-start | flex-end | center | baseline | stretch  Initial: stretch  Applies to: flex containers  Inherited: no
Name: align-self  Value: auto | flex-start | flex-end | center | baseline | stretch  Initial: auto  Applies to: flex items  Inherited: no
  • auto: 对于flex-item,可以设置align-self为auto, auto值的computed value会设置为flex container的align-items的值。
  • center: flex item的margin box 在交叉轴方向上处于flex line的中间位置。如果flex line的高度比flex item的还要低,则flex item在交叉轴的首尾两端溢出相等部分。
  • baseline: flex item会依照flex line的baseline对齐。在交叉轴方向上,baseline与flex item的margin box的上边缘距离最远的那个flex item会被放置在交叉轴的开始位置。
  • stretch: 若flex item的 cross size的computed value为auto(如果flex-direction为row,那么cross size就是flex item的height),且交叉轴方向的margin均不为auto,那么align-items/align-self为stretch时,flex item会被拉伸。flex item的cross size的used value会尽可能的接近flex line的高度,如果flex item设置了min(max)-width(height),那么这个used value会受它们的限制。

效果如下图:

Flex Layout 详解

4. align-contents

Name: align-content  Value: flex-start | flex-end | center | space-between | space-around | stretch  Initial: stretch  Applies to: multi-line flex containers  Inherited: no

align-content定义了flex line在flex container的交叉轴方向上的对齐方式,类似于justify-content,都属于flex container属性。只不过它要对齐的对象是flex line,且在交叉轴方向,而justify-content要对齐的对象是flex item,在主轴上。

属性值如下:

space-around: flex container中的flex line之间的空间相等,第一个flex line与 flex container的margin box的上边缘之间的空间只有flex line之间的空间的一半。

效果如下:

Flex Layout 详解
注明:本篇文章中少数图片来源网络,如有侵权,请立即联系本人删除。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Pro JavaScript Design Patterns

Pro JavaScript Design Patterns

Dustin Diaz、Ross Harmes / Apress / 2007-12-16 / USD 44.99

As a web developer, you’ll already know that JavaScript™ is a powerful language, allowing you to add an impressive array of dynamic functionality to otherwise static web sites. But there is more power......一起来看看 《Pro JavaScript Design Patterns》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

MD5 加密
MD5 加密

MD5 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具