一文搞懂grid布局 和 flex 布局及其区别
CSS3常用的两种布局及其区别
前言: 不久以前,所有 HTML 页面的布局还都是通过 table、float 以及其他的 CSS 属性来完成的。面对复杂页面的布局,却没有很好的办法。然而 Flexbox 的出现,便轻松的解决了复杂的 Web 布局。 现在,又出现了一个构建 HTML 最佳布局体系的新竞争者。它就是强大的 CSS Grid 布局。
grid和flex区别是什么?适用什么场景?
- Flexbox 是一维布局系统,适合做局部布局,比如导航栏组件。
- Grid 是二维布局系统,通常用于整个页面的规划。
- 二者从应用场景来说并不冲突。虽然 Flexbox 也可以用于大的页面布局,但是没有 Grid 强大和灵活。二者结合使用更加轻松。
flex和grid布局是什么?有哪些属性?
关于flex布局
简述 flexbox 是一种一维的布局,是因为一个 flexbox 一次只能处理一个维度上的元素布局,一行或者一列。
特点:
Flexbox布局(Flexible Box)模块旨在提供一个容器里的项目布局(基于一维),即使他们的大小是未知或者是动态的。
缺点:
浏览器兼容性比较差,只能兼容到ie9以上。
概念:
flexbox 的两根轴线: 当使用 flex 布局时,首先想到的是两根轴线 — 主轴和交叉轴。 主轴由
flex-direction
定义,另一根轴垂直于它。 我们使用 flexbox 的所有属性都跟这两根轴线有关, 所以有必要在一开始首先理解它。
- 按作用目标划分
作用在父容器上 | 作用在子项上 |
---|---|
flex-direction | flex-grow |
flex-wrap | flex-shrink |
flex-flow | flex-basis |
justify-content | flex |
align-items | align-self |
align-content | order |
- flex容器
flexbox 的区域就叫做 flex 容器。创建 flex 容器, 应把一个容器的
display
属性值改为flex
或者inline-flex
。 完成这一步之后,容器中的直系子元素就会变为 flex 元素。子元素CSS属性都会有一个初始值,以下属性默认值会设置如下:
flex-direction: row; // 默认水平排列,从左到右
flex-basis: auto; // 默认长度根据内容决定
flex-wrap: nowrap;// 默认不换行
父元素属性
- display:flex
- 设置flex容器:
display:flex | inline-flex
// flex 将对象作为弹性伸缩盒显示
// inline-flex 将对象作为内联块级弹性伸缩盒显示
- flex-direction
- 主轴方向由 flex-direction 定义,可以取4个值:
flex-direction:row | row-reverse | column | column-reverse
// row 水平方向排列,从左到右(默认值)
// row-reverse 水平方向排列,从右到左,和row相反
// column 垂直方向排列,从上到下
// column-reverse 垂直方向排列,从下到上
如图:
- 交叉轴 交叉轴垂直于主轴,如果你的flex-direction (主轴) 设成了 row 或者 row-reverse 的话,交叉轴的方向就是沿着列向下的。 如果主轴方向设成了 column 或者 column-reverse,交叉轴就是水平方向。
- flex-wrap
- 是否换行,由 flex-wrap 设置,可以取3个值:
flex-wrap: nowrap | wrap | wrap-reverse
// nowrap flex的元素被摆放到到一行,这可能导致溢出 flex 容器。(默认值)
// wrap flex元素被打断到多个行中。
// wrap-reverse 和 wrap 的行为一样,但是 cross-start 和 cross-end 互换。
- flex-flow
- flex-flow 是 flex-direction 和 flex-wrap 组合的简写属性 。第一个指定的值为 flex-direction ,第二个指定的值为 flex-wrap。
flex-flow: row wrap;
- align-items
- align-items 属性可以使元素在交叉轴方向对齐。
align-items: stretch | center | flex-start | flex-end
stretch // 弹性元素被在侧轴方向被拉伸到与容器相同的高度或宽度
flex-start // 元素向侧轴起点对齐。
flex-end // 元素向侧轴终点对齐。
center // 元素在侧轴居中。如果元素在侧轴上的高度高于其容器,那么在两个方向上溢出距离相同。
- align-content
- align-content 属性设置了浏览器如何沿着弹性盒子布局的纵轴和网格布局的主轴在内容项之间和周围分配空间。
- 该属性对单行弹性盒子模型无效。(即:带有 flex-wrap: nowrap)。
- align-content 和 align-items 实现效果相同,区别在于前者对flex容器内的多行flex元素生效,后者单行或者多行都会生效:
align-content: stretch | center | flex-start | flex-end
stretch // 弹性元素被在侧轴方向被拉伸到与容器相同的高度或宽度
flex-start // 元素向侧轴起点对齐。
flex-end // 元素向侧轴终点对齐。
center // 元素在侧轴居中。如果元素在侧轴上的高度高于其容器,那么在两个方向上溢出距离相同。
- justify-content
- justify-content属性用来使元素在主轴方向上对齐
justify-content: stretch | flex-start | flex-end | center | space-around | space-between
start // 从行首开始排列。每行第一个元素与行首对齐,同时所有后续的元素与前一个对齐。
flex-start // 从行首起始位置开始排列
flex-end // 从行尾位置开始排列
center // 居中排列
space-around // 均匀排列每个元素每个元素周围分配相同的空间
space-between // 均匀排列每个元素首个元素放置于起点,末尾元素放置于终点
space-evenly // 均匀排列每个元素每个元素之间的间隔相等
子元素属性
- flex-gow
- 定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。
flex-grow: number | 0;
// 0 为0则表示剩余空间不重新分配;(默认值)
// number 为正整数则按比例分配多余空间
- flex-shrink
- 定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小
flex-shrink: 1 | 0
// 1 空间不足时将缩小
// 0 空间不足时不缩小
- flex-basis
- 给上面两个属性分配多余空间之前,计算项目是否有多余空间,默认值为auto,即项目本身的大小
flex-basis: number | auto;
// number 一个长度单位或者一个百分比,规定灵活项目的初始长度。
// auto 长度等于灵活项目的长度。如果该项目未指定长度,则长度将根据内容决定。(默认值)
- flex
- flex属性是
flex-grow
、flex-shrink
、flex-basis
的简写,默认为 0,1,auto。
- flex属性是
flex:1;
// flex: 0, 1, auto(默认值)
- align-self
- align-self 属性则施加在 flex 容器中的 item 上,允许单个项目有与其他项目不一样的对齐方式,如果想设置某一个item有不一样的对齐方式的时候,可以用它。
align-self: stretch | center | flex-start | flex-end
stretch // 单个弹性元素被在侧轴方向被拉伸到与容器相同的高度或宽度
flex-start // 元素向侧轴起点对齐。
flex-end // 元素向侧轴终点对齐。
center // 元素在侧轴居中。如果元素在侧轴上的高度高于其容器,那么在两个方向上溢出距离相同。
- order
- 规定了弹性容器中的可伸缩项目在布局时的顺序。元素按照 order 属性的值的增序进行布局。值越小排序越往前。
order: 5 | -1; // 正数或负数
关于grid布局
简述 网格布局(Grid)是最强大的 CSS 布局方案。 Grid 将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局。网格是一组相交的水平线和垂直线,它定义了网格的列和行。我们可以将网格元素放置在与这些行和列相关的位置上。
特点:
- 固定和灵活的轨道尺寸;
- 可以使用行号,名称或通过定位网格区域将项目放置在网格上的精确位置;
- 可以将多个项目放入网格单元格或区域中,它们可以彼此部分重叠。
缺点:
兼容性比较差。
概念:
采用网格布局的区域,称为"容器"(container)。容器内部采用网格定位的子元素,称为"项目"(item)。
<div class="container">
<div class="item">
111
</div>
<div class="item">
222
</div>
</div>
容器属性
- display: grid
- 设为网格布局以后,容器子元素(项目)的float、display: inline-block、display: table-cell、vertical-align和column-*等设置都将失效。
display: grid;
// grid 块级元素(默认值)
// inline-grid 行级块元素
- grid-template-columns
- 定义每一列的列宽
grid-template-columns: 100px 100px 100px; // 三个值代表设置三列并且值为100px
- grid-template-rows
- 定义每一行的行高
grid-template-rows: 100px 100px 100px; // 三个值代表设置三行并且值为100px
- repeat() & auto-fill 关键字 & fr 关键字 & minmax() & auto 关键字 & 网格线的名称
grid-template-columns、grid-template-rows设置的行或者列比较多的时候,可以使用repeat()这个函数简化重复的值
// 如上面代码可以改写成这样
// repeat()接受两个参数,第一个参数是重复的次数(上例是3),第二个参数是所要重复的值。
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
// repeat()重复某种模式也是可以的。
grid-template-columns: repeat(2, 100px 20px 80px);
// 表示自动填充,直到容器放不下为止,auto-fill关键字
grid-template-columns: repeat(auto-fill, 100px);
// 为了方便表示比例关系,网格布局提供了fr关键字(fraction 的缩写,意为"片段")。如果两列的宽度分别为1fr和2fr,就表示后者是前者的两倍。
grid-template-columns: 1fr 1fr;
// minmax()函数产生一个长度范围,表示长度就在这个范围之中。它接受两个参数,分别为最小值和最大值。
grid-template-columns: 1fr 1fr minmax(100px, 1fr);
// auto关键字表示由浏览器自己决定长度。
grid-template-columns: 100px auto 100px;
// grid-template-columns属性和grid-template-rows属性里面,还可以使用方括号,指定每一根网格线的名字,方便以后的引用。
grid-template-columns: [c1] 100px [c2] 100px [c3] auto [c4];
grid-template-rows: [r1] 100px [r2] 100px [r3] auto [r4];
- grid-row-gap
- 设置行与行的间隔(行间距)
grid-row-gap: 20px;
- grid-column-gap
- 设置列与列的间隔(列间距)
grid-column-gap: 20px;
- grid-gap
- grid-gap属性是grid-column-gap和grid-row-gap的合并简写形式,语法如下。
// 如果省略了第二个值就默认为第二个等于第一个值
grid-gap: <grid-row-gap> <grid-column-gap>;
grid-gap: 20px 20px;
- grid-template-areas
- 网格布局允许指定"区域"(area),一个区域由单个或多个单元格组成。grid-template-areas属性用于定义区域。
grid-template-areas: 'a b c'
'd e f'
'g h i';
// 多个单元格合并成一个区域的写法如下。
grid-template-areas: 'a a a'
'b b b'
'c c c';
// 实例
grid-template-areas: "header header header"
"main main sidebar"
"footer footer footer";
- grid-auto-flow
- 划分网格以后,容器的子元素会按照顺序,自动放置在每一个网格。默认的放置顺序是"先行后列",即先填满第一行,再开始放入第二行,即下图数字的顺序。
// 这个顺序由grid-auto-flow属性决定,默认值是row,即"先行后列"。也可以将它设成column,变成"先列后行"。
grid-auto-flow: column;
- justify-items
- justify-items属性设置单元格内容的水平位置(左中右)
justify-items: start | end | center | stretch;
// start:对齐单元格的起始边缘。
// end:对齐单元格的结束边缘。
// center:单元格内部居中。
// stretch:拉伸,占满单元格的整个宽度(默认值)
- align-items
- align-items属性设置单元格内容的垂直位置(上中下)
align-items: start | end | center | stretch;
// start:对齐单元格的起始边缘。
// end:对齐单元格的结束边缘。
// center:单元格内部居中。
// stretch:拉伸,占满单元格的整个宽度(默认值)
- place-items
- place-items属性是align-items属性和justify-items属性的合并简写形式。
place-items: <align-items> <justify-items>;
place-items: start end;
- justify-content
- justify-content属性是整个内容区域在容器里面的水平位置(左中右)
justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
- align-content
- align-content属性是整个内容区域的垂直位置(上中下)
align-content: start | end | center | stretch | space-around | space-between | space-evenly;
- place-content
- place-content属性是align-content属性和justify-content属性的合并简写形式。
place-content: <align-content> <justify-content>
place-content: space-around space-evenly;
- grid-auto-columns & grid-auto-rows
- 用来设置,浏览器自动创建的多余网格的列宽和行高。
grid-auto-columns: 50px;
grid-auto-rows: 50px;
- rid-template
- grid-template属性是grid-template-columns、grid-template-rows和grid-template-areas这三个属性的合并简写形式。
rid-template: <grid-template-columns> <grid-template-rows> <grid-template-areas>
- grid
- grid属性是grid-template-rows、grid-template-columns、grid-template-areas、 grid-auto-rows、grid-auto-columns、grid-auto-flow这六个属性的合并简写形式。
grid: <grid-template-rows> <grid-template-columns> <grid-template-areas> <grid-auto-rows> <grid-auto-columns> <grid-auto-flow>
项目属性
- grid-column-start
- 项目左边框所在的垂直网格线
grid-column-start: 1; // 1为左边框从第一根开始
- grid-column-end
- 项目右边框所在的垂直网格线
grid-column-end: 2; // 2为右边框从在二根结束
- grid-row-start
- 项目上边框所在的水平网格线
grid-row-start: 1; // 1为上边框从第一根开始
- grid-row-end
- 项目下边框所在的水平网格线
grid-row-end: 2; // 2为下边框从在二根结束
上述四个项目属性值既可以为数字也可以为网格线名
//如上图所示,1号项目就是从第二根垂直网格线开始第四根结束
.item1{
grid-column-start: 2;
grid-column-end: 4;
background: red;
}
- grid-column
- grid-column属性是grid-column-start和grid-column-end的合并简写形式
grid-column: <start-line> / <end-line>;
grid-column: 1 / 3;
/* 等同于如下代码 */
grid-column-start: 1;
grid-column-end: 3;
- grid-area
- grid-area属性指定项目放在哪一个区域。
grid-area: e; // e 为区域名称
grid-area: <row-start> / <column-start> / <row-end> / <column-end>; // 也可以直接指定项目位置
- justify-self & align-self & place-self
justify-self
属性设置单元格内容的水平位置(左中右),跟justify-items
属性的用法完全一致,但只作用于单个项目。align-self
属性设置单元格内容的垂直位置(上中下), 跟align-items
属性的用法完全一致,也是只作用于单个项目。place-self
属性是align-self
属性和justify-self
属性的合并简写形式。
justify-self: start | end | center | stretch;
align-self: start | end | center | stretch;
place-self: <align-self> <justify-self>;
//start:对齐单元格的起始边缘。
//end:对齐单元格的结束边缘。
//center:单元格内部居中。
//stretch:拉伸,占满单元格的整个宽度(默认值)。
总结:
- Grid 布局与 Flex 布局有一定的相似性,都可以指定容器内部多个项目的位置。但是,它们也存在重大区别。
- Grid 可以做Flexbox做不了的事,Flexbox 比 Grid 兼容性更好,他们可以共同工作。Grid item可以成为flexbox容器,flex item可以成为grid 容器。
- 综上所述,可以根据业务场景需要选择相应布局。
转载自:https://juejin.cn/post/6940627375537258527