flex & grid 布局

Flex

背景

布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性。它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现。

flex布局

  • 容器的声明
    Flex是Flexible Box的缩写,意为”弹性布局”
    任何容器,我们均可以将它指定为flex布局,行内元素也可以使用Flex布局,Webkit内核的浏览器,必须加上-webkit前缀
    设为Flex布局以后,子元素的float、clear和vertical-align属性将失效
  .box{
    display:flex;
    }


  .box{  
  display:inline-flex;
  }

  .box{
  display:-webkit-flex;
  display:flex;
}

概念


采用flex布局的元素,称为flex容器(flex container)。它的所有子元素自动成为容器成员,称为flex项目(flex item)
容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴的开始位置(与边框的交叉点)叫做main start,结束位置叫做main end;交叉轴的开始位置叫做cross start,结束位置叫做cross end。 项目默认沿主轴排列。单个项目占据的主轴空间叫做main size,占据的交叉轴空间叫做cross size

容器的属性

  1. flex-direction
    该属性决定主轴的方向

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

  2. flex-wrap
    如果一条轴线排不下,如何换行

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

    nowrap为默认值,代表不换行。
    wrap代表换行,但默认为第一行在上方。
    wrap-reverse代表换行,但默认为第一行在下方。

  3. flex-flow
    flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap
 .box {
  flex-flow: <flex-direction> || <flex-wrap>;
}
  1. justify-content
    justify-content属性定义了项目在主轴上的对齐方式。

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

    flex-start为默认值,代表项目在主轴上向起始方向对齐
    flex-end代表项目在主轴上向结束方向对齐
    center代表项目在主轴上居中对齐
    space-between代表项目在主轴上两端对齐,但第一个项目在主轴的起始位置,最后一个项目在主轴的结束位置
    space-around代表项目在主轴上等分间距,但第一个项目与最后一个项目距离主轴的两端保持一定的距离,这个距离为项目之间间距的1/2

  2. align-items
    align-items属性定义项目在交叉轴上如何对齐。

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


    flex-start代表项目在交叉轴上向起始方向对齐。
    flex-end代表项目在交叉轴上向结束方向对齐。
    center代表项目在交叉轴上居中对齐。
    baseline代表项目在交叉轴上向项目的第一行文字的基线对齐。
    stretch代表项目在交叉轴上拉伸对齐。

  3. align-content
    align-content属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。

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

    flex-start:与交叉轴的起点对齐。
    flex-end:与交叉轴的终点对齐。
    center:与交叉轴的中点对齐。
    space-between:与交叉轴两端对齐,轴线之间的间隔平均分布。
    space-around:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。
    stretch(默认值):轴线占满整个交叉轴。

项目的属性

  1. order
    order属性定义项目的排列顺序,数值越小,排列越靠前,默认为0

      .item {
      order: <integer>;
    }
    

2.flex-grow
flex-grow定义了项目的放大比例。如果所有伸缩项目的flex-grow设置了1,那么每个伸缩项目将设置为一个大小相等的剩余空间。如果你给其中一个伸缩项目设置了flex-grow值为2,那么这个伸缩项目所占的剩余空间是其他伸缩项目所占剩余空间的两倍。

ps:负值对该属性无效。

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

  1. flex-shrink
    类似于flex-grow,flex-shrink定义了项目的缩小比例。其默认值为1

如果所有项目的flex-shrink都为1,当空间不足时,都将等比例缩小

如果所有项目都为1,但其中一个项目的flex-shrink为0,即代表空间不足时,该项目缩小0倍,即为不缩小

ps:负值对该属性不起作用。

  1. flex-basis
    flex-basis定义了在分配多余空间之前,项目占据的主轴空间。览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。

      .item {
        flex-basis: <length> | auto; /* default auto */
    }
    

利用flex-basis,我们可以很容易实现页面布局中的常见问题:两栏/三栏布局

    <div class="box">
    <div class="left">left</div>
    <div class="main">main</div>
</div>


        .box {
    display: flex;
    height: 200px;
        }
        .left {
            background-color: yellow;
            flex-basis: 200px;
    /* flex-basis定义该项目在分配主轴空间之前提前获得200px的空间 */
            flex-grow: 0;
            /* flex-grow定义该项目不分配剩余空间 */
        }
        .main {
            background-color: green;
            flex-grow: 1;
            /* flex-grow定义main占满剩余空间 */
        }

5.flex
flex是flex-grow、flex-shrink和flex-basis的简写,默认值为0 1 auto。后两个属性可选。

.item {
    flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
  1. align-self
    align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。

Grid

概念

grid 布局。是一个基于网格的二维布局系统。grid是第一个专门为了解决那些我们一直使用 hack 手段而导致的页面布局问题而创建的CSS模块。
一个grid容器的内容:

  • 可以将应用程序分割成不同的空间
  • 可以定义子项的大小、位置以及层级。
  • 与表格类似的是:可以让Web设计师根据元素按列或行对齐排列。
  • 可以定位自己的位置,这样他们可以重叠和类似元素定位。
  • 可以通过结合CSS的媒体查询属性,根据不同的设备和可用空间调整元素的显示风格与定位,而不需要去改变文档结构的本质内容

浏览器支持

采用grid布局的元素,称为grid容器(grid container)。它的所有子元素自动成为容器成员,称为grid项目(grid item)。

分隔的线组成了网格的结构。它们可以是垂直的(“列网格线”)或者水平的(“行网格线”),也可以在行或列的任一边。下面的例子中黄色的线是一个列网格线的例子。
网格线
每条网格线具有默认的编号,从左到右和从上到下分别为1,2,3……

网格单元
网格单元是指两根毗邻的行网格线和列网格线中间的位置,它是一个单独的网格“单元”,如图所示,网格单元是指第 1 和 2 根行网格线和第 2 和 3 根列网格线中间的位置。

网格轨迹
网格轨迹是指两根毗邻线中间的位置,可以认为是网格的行或者列

网格区域
网格区域是指 4 根网格线包围的空间,一个网格空间可能由任意数量的网格单元构成

容器的属性

  1. disaplay
    display属性定义了一个网格容器,容器是展现为行内或块状由所给定的值而决定,此时,他的所有子元素进入grid文档流,称为grid项目

    .box {
        display: grid | inline-grid | subgrid;
    }
    

    grid定义了一个网格容器,它以块级元素的形式显示
    inline-grid定义了一个网格容器,它以内联元素的形式显示
    subgrid定义了一个网格容器,这个网格容器是其父级网格容器的一个子项。它的行和列的大小从父级网格容器中获取

  2. grid-template-columns | grid-template-rows
    grid-template-rows和grid-template-columns定义了一个网格的列数、行数以及网格的大小。

    .box {
            grid-template-columns: <track-size> ... | <line-name> <track-size> ...;
            grid-template-rows: <track-size> ... | <line-name> <track-size> ...;
        }
    

    定义网格单元的宽高,其单位可以是一个长度(如px、em、rem、vw、vh)或百分比,也可以是网格中自由空间的份数(单位为fr)
    定义网格线的名称,它不是必须值。可以一个你选择的任意名字,当没有显示设定时,它的名字以数字表示。

    .box {
        grid-template-columns: 40px 50px auto 50px 40px;
        grid-template-rows: 25% 100px auto;
    }
    

    .box {
        grid-template-columns: [first] 40px [line2] 50px [line3] auto [col4-start] 50px [five] 40px [end];
        grid-template-rows: [row1-start] 25% [row1-end] 100px [third-line] auto [last-line];
    }
    

一根网格线可以有多个名字,例如在下面的例子中第二根线有两个名字:row1-end 和 row2-start,命名方式以空格来作为间隔。

.box{
    grid-template-rows:[row1-start] 25% [row1-end row-start] 25% [row-end];
    }

定义了容器的重复部分,你可以使用CSS的repeat()方法来生成多个相同值:

.box {
    grid-template-columns: repeat(3, 20px [col-start]) 5%;
}

.box {
    grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start] 5%;
}

fr是一个特殊的单位,它可以类似于设定flex-grow时,给网格容器中的自由空间设置为一个份数,举个例子,下面的例子将把网格容器的每个子项设置为三分之一

.box {
    grid-template-columns: 1fr 1fr 1fr;
}

也是类似于flex-grow,自由空间是在固定子项确定后开始计算的(这里就如同flex-basis提前给予宽高那样),在下面的例子中自由空间是fr单位的总和但不包括50px:
.box {
grid-template-columns: 1fr 50px 1fr 1fr;
}

  1. grid-template-areas
    grid-template-areas可以配合gird-area定义一个显示的网格区域。
    grid-template-areas定义网格区域,然后使用grid-area调用声明好的网格区域名称来放置对应的网格项目

     <section class="grid">
        <div class="title">title</div>
        <div class="nav">nav</div>
        <div class="main">main</div>
        <div class="aside">aside</div>
        <div class="footer">footer</div>
    </section>  
    .grid {
            display: grid;
            grid-template-columns: 100px 100px 100px 100px 100px;
            grid-template-rows: 100px 100px 100px 100px;
            grid-template-areas: 'title title title title aside'
                                  'nav main main main aside'
                                  'nav main main main aside'
                                  'footer footer footer footer footer';
            font-size: 30px;
            text-align: center;
        }
        .title {
            grid-area: title;
            background-color: blue;
        }
        .nav {
            grid-area: nav;
            background-color: yellow;
        }
        .main {
            grid-area: main;
            background-color: gray;
        }
        .aside {
            grid-area: aside;
            background-color: green;
        }
        .footer {
            grid-area: footer;
            background-color: pink;
        }
    

  2. grid-column-gap|grid-row-gap
    grid-column-gap和grid-row-gap定义了网格之间的间距

       .box {
        grid-template-columns: 100px 50px 100px;
        grid-template-rows: 80px auto 80px;
        grid-column-gap: 10px;
        grid-row-gap: 15px;
    }
    

5.justify-items
justify-items定义了网格子项的内容和列轴对齐方式,即水平方向上的对齐方式

.box {
    justify-items: start | end | center | stretch;
}

start代表内容和网格区域的左边对齐
end代表内容和网格区域的右边对齐
center代表内容和网格区域的中间对齐
stretch为默认值,代表填充整个网格区域的宽度

  1. align-items
    类似于justify-items,align-items定义了网格子项的内容和行轴对齐方式,即垂直方向上的对齐方式。

     .box {
        align-items: start | end | center | stretch;
    }
    

start代表内容和网格区域的上边对齐
end代表内容和网格区域的下边对齐
center代表内容和网格区域的中间对齐
stretch为默认值,代表填充整个网格区域的高度

  1. justity-content|align-content
    justify-content属性定义了网格和网格容器列轴对齐方式

      .box {
        justify-content|align-content: start | end | center | stretch | space-around | space-between | space-evenly;
    }
    

    start代表网格在网格容器(左|上)边对齐
    end代表网格在网格容器(右|下)边对齐
    center代表网格在网格容器中间对齐
    stretch改变网格子项的容量让其填充整个网格容器宽度
    space-around代表在每个网格子项中间放置均等的空间,在始末两端只有一半大小
    space-between代表在每个网格子项中间放置均等的空间,在始末两端没有空间
    space-evenly代表在每个网格子项中间放置均等的空间,包括始末两端

  2. grid-auto-columns|grid-auto-rows
    grid-auto-columns与grid-auto-rows可以指定隐式网格。

       <div class="grid">
        <div class="box1">box1</div>
        <div class="box2">box2</div>
        <div class="box3">box3</div>
        <div class="box4">box4</div>
    </div>
          .grid {
            display: grid;
            grid-template-columns: 200px;
            grid-template-rows: 200px;
            text-align: center;
            font-size: 30px;
        }
        .box1 {
            background-color: pink;
            grid-column: 1;
            grid-row: 1;
        }
        .box2 {
            background-color: yellow;
            grid-column: 2;
            grid-row: 1;
        }
        .box3 {
            background-color: gray;
            grid-column: 1;
            grid-column: 2;
        }
        .box4 {
            background-color: blue;
            grid-column: 2;
            grid-row: 2;
        }
    


通过grid-auto-columns与grid-auto-rows属性,创建一个隐式的2×2的网格

grid-auto-columns: 300px;
grid-auto-rows: 300px;

  1. grid-auto-flow
    grid布局自身具有的自动布局算法会将网格子项自动放置起来,而grid-auto-flow属性控制自动布局算法如何工作

    .box {
     grid-auto-flow: row | column | row dense | column dense
    

    }

row为默认值,代表自动布局算法在每一行中依次填充,只有必要时才会添加新行。
column代表自动布局算法在每一列中依次填充,只有必要时才会添加新行。
dense代表告诉自动布局算法如果更小的子项出现时尝试在网格中填补漏洞。
10 grid
grid为以下属性的合并写法:grid-template-rows,grid-template-columns,grid-template-areas,grid-auto-rows,grid-auto-columns,grid-auto-flow。它也可以设置grid-column-gap和grid-row-gap。

.box {
    grid: none | <grid-template-rows> / <grid-template-columns> | <grid-auto-flow> [<grid-auto-rows> [/ <grid-auto-columns>]];
}