flex与grid布局详细资料整理(图文并茂!)

169 阅读10分钟

flex

基本概念

flexbox是一种一维的布局模型,它给flexbox的子元素之间提供了强大的空间分布和对齐能力。我们说它是一种一维的布局,是因为一个flexbox一次只能处理一个维度上的元素布局,一行或者一列,作为对比的是另外一个二维布局grid,可以同时处理行和列上的布局

两根轴线

主轴

由flex-direction定义,可以取四个值

  • row
  • row-reverse
  • column
  • column-reverse

If flex-direction is set to row the main axis runs along the row in the inline direction.

If flex-direction is set to column the main axis runs in the block direction.

交叉轴

交叉轴是垂直于主轴的,主轴是什么方向,交叉轴就是垂直于主轴的另一个方向。flexbox的特性是沿着主轴或者交叉轴对齐之中的元素

Flex容器

文档中采用了flexbox的区域就叫做flex容器,为了创建flex容器,将一个容器的display属性值改为flex或者inline-flex。之后容器中的直系子元素就会变为flex元素

  • 元素排列为一行 (flex-direction 属性的初始值是 row)。
  • 元素从主轴的起始线开始。
  • 元素不会在主维度方向拉伸,但是可以缩小。
  • 元素被拉伸来填充交叉轴大小。
  • flex-basis 属性为 auto。
  • flex-wrap属性为 nowrap。

这会让元素呈线性排列,并且把自己的大小作为主轴上的大小。如果有太多元素超出容器,它们会溢出而不会换行,如果一些元素比其他元素高,那么元素会沿交叉轴被拉伸来填满它的大小。

多行flex容器

使用flex-wrap可以将一维的flexbox应用到多行中。在这样做的时候,应该把每一行看做一个新的flex容器,任何空间分布都将在该行上发生,而不影响该空间其他行的分布。给flex-wrap赋值为wrap后,若项目的子元素总宽度大于容器最大宽度,子元素将会换行显示。若设置为nowrap,子元素将会缩小以适应容器,若不能缩小,则会溢出。

简写flex-flow

可以将flex-direction和flex-wrap简写为flex-flow。

flex子元素属性

首先介绍可用空间 available space 这个概念。这几个 flex 属性的作用其实就是改变了 flex 容器中的可用空间的行为。同时,可用空间对于 flex 元素的对齐行为也是很重要的。

假设在 1 个 500px 的容器中,我们有 3 个 100px 宽的元素,那么这 3 个元素需要占 300px 的宽,剩下 200px 的可用空间。在默认情况下,flexbox 的行为会把这 200px 的空间留在最后一个元素的后面。

This flex container has available space after laying out the items.

如果期望这些元素能自动地扩展去填充满剩下的空间,那么我们需要去控制可用空间在这几个元素间如何分配,这就是元素上的那些 flex 属性要做的事。

flex-basis

定义了该元素的空间大小,如果给元素设定了尺寸,那么它的值就是设定的尺寸;如果没有给元素设定尺寸,以包含的内容决定宽度;如果给basis设定了content,则一律以内容决定宽度;若设定了长度或百分比值,则根据这个值设定宽度;

根据以上规则知道了每一项的宽度,简单相加就能得到所有项的宽度总和。而知道了总和,再与容器宽度比较,就能知道容器里是不是还有剩余空间可供再次分配。这里有三种情况:

  1. 所有项宽度总和等于容器宽度,剩余空间为零
  2. 所有项宽度总和小于容器宽度,剩余空间为正
  3. 所有项宽度总和大于宽度宽度,剩余空间为负

剩余空间为正,代表有剩余空间可分配,也就是可伸缩项有条件扩展。至于如何扩展,那就要看每一项的flex-grow属性了。

剩余空间为负,代表可伸缩项宽度总和超出了容器宽度,也就是可伸缩项必须收缩才能适应容器宽度。至于如何收缩,就得看每一项的flex-shrink属性。

与width的区别

  1. 为0时

    width为0,完全不显示;basis为0,根据内容撑开宽度

  2. 非0时

    数值相同时两者等效;同时设置,basis优先级高

  3. basis为auto

    如设置了width由则元素尺寸由width决定,没有设置则由内容决定

  4. basis是主轴的尺寸,不一定是width

flex-basis:0与flex-basis:auto的区别

设置为0时(绝对弹性元素),此时相当于告诉flex-growflex-shrink在伸缩的时候不需要考虑我的尺寸;相反当设置为auto时(相对弹性元素),此时则需要在伸缩时将元素尺寸纳入考虑。下图可以看出如果grow值一样,元素尺寸一定是一样的

image.png

flex-grow

本属性用于设定在容器宽度大于元素总宽度时如何伸展

必须是正整数?,默认值为0,代表不扩展,只要有一项子元素的flex-grow不为0,就要对容器剩余宽度进行分配。分配规则如下

当前项可分得的剩余空间=(当前项grow值/所有项grow值之和)*剩余总宽度

flex-shrink

本属性用于设定在容器宽度小于元素总宽度时如何收缩

必须是正整数?,默认值为1,默认每一项都会收缩,shrink与grow不同,会进行按权收缩,规则如下

当前项收缩的宽度 = ( 当前项flex-shrink*当前项flex-basis / 所有项flex-shrink与各自flex-basis乘积之和 ) * 需收缩的总宽度

除了考虑shrink本身,也要考虑basis,如果每一项shrink都是1,那其实就是按照每一项basis的占比按权收缩,防止宽度小的元素被收缩为0宽度

flex

img

  • flex: 1 = flex: 1 1 0%
  • flex: 2 = flex: 2 1 0%
  • flex: auto = flex: 1 1 auto;
  • flex: none = flex: 0 0 auto; // 常用于固定尺寸 不伸缩

order

本属性用于调整子元素顺序,数值越小,越靠前,默认为0;值相同时,以dom元素的排列为准

轴线对齐方式

justify-content

image.png

align-item

单行对齐

image.png

image.png

image.png

image.png

image.png

多行对齐align-content

只在有多行元素时生效

默认值stretch,item与content同时为stretch时,效果为撑满交叉轴

image.png

content为stretch,item为flex-start或给弹性元素设置一个具体高度时,行与行之间会形成间距

image.png

content会以整行为单位拉伸撑满交叉轴,而item设置了高度或者顶对齐,不能使用高度进行拉伸,使用间距进行拉伸

item设为stretch,content设为flex-start,此时以行为单位,整体高度通过内容撑开,

image.png

image.png

align-self可以单独对某个元素设置交叉轴对齐方式

image.png

image.png

grid

基本概念

网格是一组相交的水平线和垂直线,它定义了网格的列和行,我们可以将网格元素放置在与这些行和列相关的位置上。

CSS 网格布局具有以下特点:

固定的位置和弹性的轨道的大小

你可以使用固定的轨道尺寸创建网格,比如使用像素单位。你也可以使用比如百分比或者专门为此目的创建的新单位 fr来创建有弹性尺寸的网格。

元素位置

你可以使用行号、行名或者标定一个网格区域来精确定位元素。网格同时还使用一种算法来控制未给出明确网格位置的元素。

创建额外的轨道来包含元素

可以使用网格布局定义一个显式网格,但是根据规范它会处理你加在网格外面的内容,当必要时它会自动增加行和列,它会尽可能多的容纳所有的列。

对齐控制

网格包含对齐特点,以便我们可以控制一旦放置到网格区域中的物体对齐,以及整个网格如何对齐。

控制重叠内容

多个元素可以放置在网格单元格中,或者区域可以部分地彼此重叠。然后可以 CSS 中的z-index属性来控制重叠区域显示的优先级。

网格容器

在元素上声明display:grid来创建一个网格容器,这个元素的所有直系子元素将成为网格元素,网格默认给这些元素创建单列网格;

网格轨道

通过grid-template-column和grid-template-rows属性来定义网格中的行和列,这些属性定义了网格的轨道。一个网格轨道就是网格中任意两条线之间的空间。

  1. grid-template-columns: 200px 200px 200px;=== grid-template-columns: repeat(3, 200px);

    固定的列宽与列数量;repeat可以简化重复的值

  2. grid-template-columns: repeat(auto-fill, 200px);

    自动填充,设定了列宽,但是不限定列数量,只要放得下就可以放置元素

  3. grid-template-columns: 1fr 2fr 1fr;

    自动将容器分成相等宽度的n份进行分配

  4. grid-template-columns: 1fr 1fr minmax(300px, 2fr);

    赋给一个网格元素最大最小的尺寸,第三个列宽最少也是要 300px,但是最大不能大于第一第二列宽的两倍。

  5. grid-template-columns: 100px auto 100px;

    第一第三列为 100px,中间由浏览器决定长度;auto最小为内容的宽度

rows属性与column相同,仅变为操作行

fr单位

轨道可以使用任何长度单位进行定义,新的fr单位代表网格容器中可用空间的一等份

隐式和显示网格

grid-template-columns 属性定义了自己的列轨道,让网格按所需的内容创建行,这些行会创建在隐式网格中。

可以在隐式网格中用 grid-auto-rowsgrid-auto-columns 属性来定义一个设置大小尺寸的轨道。网格自行创建的行或列会按照这个尺寸进行创建。

跨轨道放置网格元素

  • grid-column-start 属性:左边框所在的垂直网格线
  • grid-column-end 属性:右边框所在的垂直网格线
  • grid-row-start 属性:上边框所在的水平网格线
  • grid-row-end 属性:下边框所在的水平网格线
Diagram showing numbered grid lines.

网格间距

grid-row-gap 属性、grid-column-gap 属性分别设置行间距和列间距。grid-gap 属性是两者的简写形式。grid-row-gap: 10px 表示行间距是 10px,grid-column-gap: 20px 表示列间距是 20px。grid-gap: 10px 20px 实现的效果是一样的

img

其他高级属性

grid-template-areas

.wrapper {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: 120px  120px  120px;
  grid-template-areas:
    ". header  header"
    "sidebar content content";
  background-color: #fff;
  color: #444;
}
.sidebar {
  grid-area: sidebar;
}

.content {
  grid-area: content;
}

.header {
  grid-area: header;
}

img

以上代码表示将类 .sidebar .content .header所在的元素放在上面 grid-template-areas 中定义的 sidebar content header 区域中

grid-auto-flow

grid-auto-flow 属性控制着自动布局算法怎样运作,精确指定在网格中被自动布局的元素怎样排列。默认的放置顺序是"先行后列",即先填满第一行,再开始放入第二行,即下图英文数字的顺序 one,two,three...。这个顺序由 grid-auto-flow 属性决定,默认值是 row

grid-auto-flow: row dense,表示尽可能填满表格,效果如下图

imageimage

设置 grid-auto-flow: column,表示先列后行

当抉择该用网格还是弹性盒时,你可以问自己一个简单的问题

  • 我只需要按行或者列控制布局?那就用弹性盒子
  • 我需要同时按行和列控制布局?那就用网格