CSS布局-弹性盒子与网格布局

css的布局技术可以让我们控制他们的相对正常布局流、周边元素、父容器或者主视口/窗口的位置。常见的布局形式有:正常布局流、display属性布局、弹性盒子布局、网格布局、浮动布局、定位布局、表格布局、多列布局。

每种技术都有他们的用途,通过理解各个布局的相关理念,构建理想的布局方案。

一些布局技术会覆盖默认的布局技术;

display:默认的一些属性inlineblockinline-block在正常布局流中的表现形式为对应的盒模型的属性。

在CSS中实现页面的布局的主要方法是设定display的值,正常的布局流中所有的属性都有一个display的值,例如在段落下面显示另外一个段落,是因为他的display的值是block吗,如果在段落中添加了一个连接,这个段落并不会换行,是应为连接adisplay的属性值是inline

在讨论布局时,最重要的两个值是display:flexdisplay:grid

1 弹性布局:flex

主要解决问题:

  • 在父内容里面垂直居中一个块内容。

  • 使容器的所有子项占用等量的可用宽度/高度,而不管有多少宽度/高度可用。

  • 使多列布局中的所有列采用相同的高度,即使它们包含的内容量不同。

使用方法:在想要进行 flex 布局的父元素上应用display:flex,所有的子元素都会按照flex进行布局。

1
2
3
.wrapper {
display: flex;
}
1
2
3
4
5
<div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">Three</div>
</div>

除了可以设置父容器的属性以外,还有很多属性可以设置到flex items上,这些属性可以改变flex items在flex布局中占用宽/高的方式,允许它们通过伸缩来适应可用空间。

例如在所有的flex items上设置flex:1可以设置所有的flex items都伸展并填充容器。

1.1 flex模型说明

当元素表现为 flex 框时,它们沿着两个轴来布局:

flex_terms.png

  • 主轴(main axis)是沿着 flex 元素放置的方向延伸的轴(比如页面上的横向的行、纵向的列)。该轴的开始和结束被称为 main startmain end
  • 交叉轴(cross axis)是垂直于 flex 元素放置方向的轴。该轴的开始和结束被称为 cross startcross end
  • 设置了 display: flex 的父元素,被称之为 flex 容器(flex container)。
  • 在 flex 容器中表现为柔性的盒子的元素被称之为 flex 项flex item)。

在flex布局中提供了==行列==布局的选项,通过flex-direction设置,他可以指定主轴的方向,默认行布局值为row,按照语言的默认方向排成一排。使用column 值将改为列布局,还有row-reversecolumn-reverse 值反向排列 flex items。

1
flex-direction: row;

在布局中使用固定宽度或者固定高度,flex items可能会溢出弹性盒子,可以使用flx-wrap:wrap来避免这种情况。同时也可以设置每个flex items的最小宽度flex:200px,使用了以上属性,溢出的flex items将会移动到下一行。

可以将flex-directionflex-wrap缩写为 flex-flow

1
2
3
4
5
6
flex-direction: row;
flex-wrap: wrap;

/* 缩写为 */

flex-flow: row wrap;

上文中通过flex:200px 来控制flex items的宽度,如何动态的设置flex items 占用空间的比例呢?

1
flex: 1;

这是一个没有单位的比例值,表示每个 flex 项沿主轴的可用空间大小。例如设置为1代表每个flex items占用的空间是相等的,占用的空间是在设置 padding 和 margin 之后剩余的空间。因为这是一个比例值,所以数字的大小所产生的效果是一样的。

也可以指定flex的最小值flex: 1 2-00px;, 表示每个flex items先给出200px,然后剩余的空间按照分配的比例共享。

1.2 flex的缩写与全写

可以指定最多三个值的缩写属性:(不建议使用全写)

  • 第一个即上文中的无比例单位,也可以单独指定全写flex-grow: 1;
  • 第二个无单位比例是flex-shrink,一般用于溢出容器的flex items,他指定了从每个flex items取出多少溢出量,以阻止它们溢出它们的容器。(高级)
  • 第三个是最小值,可以单独指定全写flex-basis

1.3 弹性布局水平和垂直对齐

通过align-items控制flex items在交叉轴上的位置

  • 默认的值是 stretch,其会使所有 flex 项沿着交叉轴的方向拉伸以填充父容器。如果父容器在交叉轴方向上没有固定宽度(即高度),则所有 flex 项将变得与最长的 flex 项一样长(即高度保持一致)。
  • center 值会使这些项保持其原有的高度,但是会在交叉轴居中。
  • flex-startflex-end 这样使 flex 项在交叉轴的开始或结束处对齐所有的值。

可以在每个单独的flex items设置特殊的布局align-self: flex-end;

通过justify-content控制flex items在主轴上的位置。

  • 默认值是 flex-start,这会使所有 flex 项都位于主轴的开始处。
  • 使用 flex-end 来让 flex 项到结尾处,与上面的值相反。
  • 使用center 让 flex 项在主轴居中,但是每个元素之间不会有间隔。
  • 使用 space-around 让flex 项沿着主轴均匀地分布,在任意一端都会留有一点空间。
  • 使用 space-between,它和 space-around 非常相似,只是它不会在两端留下任何空间。

1.4 flex items 排序

弹性盒子可以改变flex items的布局的位置,而不会影响到dom元素的顺序。

1
2
3
button:first-child {
order: 1;
}
  • 所有 flex items 的默认 order 的值是0。
  • order 值大的 flex items 比 order 值小的在显示顺序中更靠后。
  • 相同 order 值的 flex 项按源顺序显示。所以假如你有四个元素,其 order 值分别是 2,1,1 和 0,那么它们的显示顺序就分别是第四,第二,第三,和第一。
  • 第三个元素显示在第二个后面是因为它们的 order 值一样,且第三个元素在源顺序中排在第二个后面。

也可以给 order 设置负值使它们比值为 0 的元素排得更前面。

2 网格布局:grid

网格是由一系列水平及垂直的线构成的一种布局模式。根据网格,我们能够将设计元素进行排列,帮助我们设计一系列具有固定位置以及宽度的元素的页面,使我们的网站页面更加统一。

一个网格通常还有许多的列与行,以及行与行、列与列之间的间隙,间隙一般称为沟槽。

img

与弹性盒子的区别:在定义网格后,网页并不会马上发生变化。因为display: grid的声明只创建了一个只有一列的网格,所以你的子项还是会像正常布局流那样从上而下一个接一个的排布

2.1 给网格设置列

1
2
3
4
.container {
display: grid;
grid-template-columns: 200px 200px 200px;
}

设置列的单位可以是具体的px,或者百分比也可以是fr,他比px和百分比更加的灵活,这个单位表示了一个可用空间的一个比例。

1
grid-template-columns: 1fr 1fr 1fe;

设置了fr,每一列的宽度们可以随着空间的变小而变小。

fr单位分配的是可用空间而非所有空间,所以如果某一格包含的内容变多了,那么整个可用空间就会减少,可用空间是不包括那些已经确定被占用的空间的。

2.2 网格间隙

使用 grid-column-gap属性来定义列间隙;使用 grid-row-gap来定义行间隙;使用 grid-gap 可以同时设定两者。

1
2
3
4
5
.container {
display: grid;
grid-template-columns: 2fr 1fr 1fr;
grid-gap: 20px;
}

间隙距离可以用任何长度单位包括百分比来表示,但不能使用fr单位。

2.3 重复构建行/列

可以使用repeat来重复构建具有某些宽度配置的某些列。

1
2
3
4
5
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 20px;
}

2.4 显式网格和隐式网格

显式网格是我们用grid-template-columnsgrid-template-rows 属性创建的。而隐式网格则是当有内容被放到网格外时才会生成的。显式网格与隐式网格的关系与弹性盒子的 main 和 cross 轴的关系有些类似。

隐式网格的行列大小默认是auto,大小会根据放入的内容自动调整。也可以使用grid-auto-rowsgrid-auto-columns手动设置隐式网格的大小。

简单来说,隐式网格就是为了放显式网格放不下的元素,浏览器根据已经定义的显式网格自动生成的网格部分。

2.4 minmax函数

函数为一个行/列的尺寸设置了取值范围。比如设定为 minmax(100px, auto),那么尺寸就至少为 100 像素,并且如果内容尺寸大于 100 像素则会根据内容自动调整。

浮动布局:例如float:left值可以让块级元素相互排成一行。

position:允许精准设置盒子中的盒子的位置,正常布局流中的默认值为static,他的值会引起不同元素的布局方式,例如将元素固定到浏览器左上角的。

表格布局:表格的布局方式,可以用在非表格内容上,可以使用display:table和相关属性在非表格元素上使用。

多列布局:multi-column-layout属性可以让快按照列布局,类似报纸的形式。