阅读 1482
🍍Flex 和 Grid布局完全掌握

🍍Flex 和 Grid布局完全掌握

Flex 布局

设计理念:

flex 布局是轴线弹性布局(一维布局),主要的两大块 flex 盒子(容器)和 flex 项,而 flex 项时根据外部容器决定内部尺寸的思想;

实现原理:

Flex 排版三个步骤:分行、计算主轴、计算交叉轴。

基础介绍:

布局方式:

display: flex; 将对象作为弹性伸缩盒展示,用于块级元素;

display: inline-flex; 将对象作为弹性伸缩盒展示,用于行内元素。

属性:

box上的容器属性:

flex-direction:flex主轴方向

row | row-reverse | column | column-reverse

flex-wrap:flex 子项是否换行

nowrap | wrap | wrap-reverse

flex-flow:复合属性(flex-direction flex-wrap);

flex-flow: row-reverse wrap;
复制代码

justify-content:用于指定主轴(水平方向)上Flex子项的对齐方式

flex-start | flex-end | center | space-between | space-around

align-items:用于指定侧轴(垂直方向)上Flex子项的对齐方式

stretch | flex-start | flex-end | center | baseline

stretch:默认值,当Flex子项未设置高度或者高度值为auto时,stretch起作用,将Flex子项高度设置为行高度。这里需要注意,在只有一行的情况下,行的高度为容器的高度,即Flex子项高度为容器的高度

align-content:调整子项之间的中间间距;该属性只作用于多行的情况下,用于多行的对齐方式,在只有一行的Flex容器上无效;

stretch | flex-start | flex-end | center | space-between | space-around

子项属性:

order:该属性用来指定Flex子项的排列顺序,数值越小,越靠前,可以为负数;

align-self:用来单独指定某Flex子项的对齐方式;

auto | flex-start | flex-end | center | baseline | stretch

先继承 父元素的 align-items ,如果没有则默认 stretch。

flex:复合属性:

是flex-grow 、 flex-shrink 和 flex-basis 的简写属性,用来指定Flex子项如何分配空间;

// flex 简写 => 为等同于的意思
flex: none; => flex: 0 0 auto;
flex: auto; => flex: 1 1 auto;
flex: 1; => flex: 1 1 0%;
flex: 0 auto; 或 flex: initial; => flex: 0 1 auto; 即三项都是默认值
复制代码

flex-grow:

用来指定 Flex 子项的扩展比例,不可以为负数,Flex容器会根据Flex子项设置的扩展比例作为比率来分配剩余空间。取值:数值,默认值为0,表示即使存在剩余空间,Flex子项也不会扩展。

flex-shrink:

用来指定Flex子项的收缩比例,不可以为负数,Flex容器会根据Flex子项设置的收缩比例作为比率来收缩各个Flex子项;

取值:数值,默认值为1,表示所有子项在剩余空间为负数时,等比例收缩

注意:flex-shrink只能在不换行的情况下使用。

flex-basis:

用来指定Flex子项的基础占据的空间,不可以为负数。设置 flex-grow 进行分配剩余空间,或者使用 flex-shrink 进行收缩都是在 flex-basis 的基础上进行的(在 设定的 flex-basis基础上 进行 等比例的扩展和收缩)具体扩展及收缩多少的计算方式在下面会讲;

取值:默认值 auto | 长度/宽度 | 百分比 | content

【🍉难点】flex 子项的几种表现形式:

这个难点是写这篇文章的初衷!

1.0 当子项 flex-basis 的值以及 width(或者height)的值均不是 auto 时(也就是设置了固定值 px、百分比、数值):

1.1 若 content 内容的长度同时大于 flex-basis 的值以及 width(或者height)的值,此时以flex-basis与width(或者height)中值大的为准 (如下图:紫色块以 120px为准);

但是,如果子项设置了overflow: hidden;或者overflow: auto;,此时以flex-basis值为准(如下图:紫色块以 33.33%为准);

1.2 若 content 内容长度同时小于 flex-basis 的值以及width(或者height)的值,此时以flex-basis值为准;(如下图:均以 33.33%为准);

1.3 若 content 内容长度小于 flex-basis 的值,大于width(或者height)的值,此时以 flex-basis值为准;

1.4 若content长度大于flex-basis的值,小于width(或者height)的值,此时以content自身长度值为准;

2.0 当子项 width(或者height)的值为 auto 时:

如果 content 内容的长度大于 flex-basis设置的值,此时以 content 自身长度值为准,且不能进行flex-shrink 收缩。相反如果内容的长度小于 flex-basis 设置的值,则会使用 flex-basis 设置的值;

3.0 当存在最小值 min-widthmin-height)时,且 flex-basis的值小于最小值时,宽度以最小值为准,当 flex-basis的值大于最小值时,以 flex-basis的值为准。【也就是 min-width 的权重更高】。

以 flex-basis 为准

以 min-width 为准

4.0 当所有子元素宽度之和大于父元素宽度且 flex-shrink 均 大于1 时,flex-shrink 启用;

.container {
  display: flex;
  width: 300px;
  height: 300px;
  margin-top: 20px;
}
.left {
  flex: 1 2 200px;
  background: #4d9df8;
}
.right {
  flex: 2 1 250px;
  background: yellowgreen;
}
复制代码

以下分别为 left 和 right 的宽度计算公式:

left 的 width =【left 的 flex-basis - (left 的 flex-basis + right 的 flex-basis - 父元素的 width) * (left 的 flex-basis * left 的 flex-shrink)/(left 的 flex-basis * left 的 flex-shrink + right 的 flex-basis * right 的 flex-shrink))

5.0 当所有子元素宽度之和小于父元素宽度 且 flex-grow 均 大于1 时,flex-grow 启用;

.container {
  display: flex;
  width: 730px;
  height: 300px;
  margin-top: 20px;
}
.left {
  flex: 1 2 200px;
  background: #4d9df8;
  }
.right {
  flex: 2 1 250px;
  background: yellowgreen;
}
复制代码

以下分别为 left 和 right 的宽度计算公式:

left 的 flex-basis + (父元素的 width - left 的 flex-basis - right 的 flex-basis)* left 的 flex-grow /(left 的 flex-grow + right 的 flex-grow)

Grid 布局

Grid 布局则是将容器划分成"行"和"列",产生单元格,然后指定"项目所在"的单元格(二维布局),同时处理行和列的关系。Grid 布局远比 Flex 布局强大。

自己用 Grid 实现的一些特殊布局:

属性快速索引目录

容器属性

说明

子项目属性

说明

grid-template

grid-columns/rows

grid-template-areas

grid-area

grid-gap

justify-self

place-items

align-self

place-content

place-self

grid-auto-flow

控制没有明确指定位置的grid子项目的放置方式;

grid-auto-rows/columns

隐式网格的属性指定

一、容器属性

1.1.0 display 属性

// 开启 grid 网格布局
display: grid;
display: inline-grid;
复制代码

注意,设为网格布局以后,容器子元素(项目)的float、display: inline-block、display: table-cell、vertical-align 和 column-*等设置都将失效。

1.2.0 grid-template-columns 属性,grid-template-rows 属性

容器指定了网格布局以后,接着就要划分行和列。grid-template-columns属性定义每一列的列宽,grid-template-rows属性定义每一行的行高。

.container {
  display: grid;
  grid-template-columns: 100px 100px 100px;
  grid-template-rows: 100px 100px 100px;
}
.container {
  display: grid;
  grid-template-columns: 33.33% 33.33% 33.33%;
  grid-template-rows: 33.33% 33.33% 33.33%;
}
.container {
  display: grid;
  grid-template-columns: repeat(3, 33.33%);
  grid-template-rows: repeat(3, 33.33%);
}
// 单个 单元格 项的宽度或者高度一定,但是 盒子的宽度高度未知的情况下,要让 单元格自动填充,在一行或一列内尽可能多的填充单元格,则会用到 auto-fill 关键词
grid-template-columns: repeat(auto-fill, 100px);


// 为了方便表示比例关系,网格布局提供了fr关键字(fraction 的缩写,意为"片段")。如果两列的宽度分别为1fr和2fr,就表示后者是前者的两倍。
grid-template-columns: 100px 1fr 2fr;
// 最小值最大值 minmax
grid-template-columns: 1fr 1fr minmax(100px, 1fr);
// 自适应
grid-template-columns: 100px auto 100px;
// 定义网格线名称(4竖线,4横线)
.container {
  display: grid;
  grid-template-columns: [c1] 100px [c2] 100px [c3] auto [c4];
  grid-template-rows: [r1] 100px [r2] 100px [r3] auto [r4];
}
复制代码

1.3.0 grid-row-gap 属性,grid-column-gap 属性,grid-gap 属性

设置 网格 行与行 列与列 的间隔

.container {
  grid-row-gap: 20px;
  grid-column-gap: 10px;
}
.container {
  grid-gap: 20px 10px;
}
复制代码

1.4.0 grid-template-areas 属性

给单元格划分区域

.container {
  display: grid;
  grid-template-columns: 100px 100px 100px;
  grid-template-rows: 100px 100px 100px;
  grid-template-areas: 'a b c' 'd e f' 'g h i';
}
// a b c d e f g h i 每个字母对应9个单元格中其中一个单元格(网格子项)
复制代码

1.5.0 grid-auto-flow 属性

设置网格 排版的 原则;

默认值 row 先排行再排列;column 先列后行;row-dense 
grid-auto-flow: row; // 默认
grid-auto-flow: column; 
grid-auto-flow: row-dense; // 先行后列,尽量填满行,不留空格
grid-auto-flow: column-dense; // 先列后行,尽量填满列,不留空格
复制代码

1.6.0 justify-items 属性;align-items 属性;place-items 属性

单元格内容的对齐方式:

.container {
  justify-items: start | end | center | stretch; // stretch 拉伸占据
  align-items: start | end | center | stretch;
}
// 合并写法
place-items: start end; // 上面的 justify-items align-items 的简写形式
复制代码

1.7.0 justify-content 属性;align-content 属性;place-content 属性

justify-content属性是整个内容区域在容器里面的水平位置(左中右),align-content属性是整个内容区域的垂直位置(上中下);

.container {
  justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
  align-content: start | end | center | stretch | space-around | space-between | space-evenly;
}
// 合并写法
place-content: space-around space-evenly;
复制代码

1.8.0 grid-auto-columns 属性和 grid-auto-rows 属性

当网格中有子项目 存在于 布局之外时,grid-auto-columns 属性和 grid-auto-rows 属性用来设置浏览器自动创建的多余网格的列宽和行高。

它们的写法与 grid-template-columns 和 grid-template-rows 完全相同。如果不指定这两个属性,浏览器完全根据单元格内容的大小,决定新增网格的列宽和行高。

二、项目属性

2.1 grid-column-start/end、grid-row-start/end 属性

根据容器划分的网格线,定义项目边框的起始、结束的网格线位置的一些属性;

2.1.1 基础用法

grid-column-start属性:左边框所在的垂直网格线;

grid-column-end属性:右边框所在的垂直网格线;

grid-row-start属性:上边框所在的水平网格线;

grid-row-end属性:下边框所在的水平网格线;

.item-1 {
  // 指定该项目的四个边框的位置
  grid-column-start: 1; // 左边框是第一根网格线
  grid-column-end: 3; // 右边框是第三根网格线
  grid-row-start: 2; // 上边框是第二根网格线
  grid-row-end: 4; // 下边框是第四根网格线
}
复制代码

指定具体网格线的时候,除了使用数值,也可以使用 网格线名称;

2.1.2 span 关键字

这四个属性的值还可以使用 span 关键字,表示"跨越",即左右边框(上下边框)之间跨越多少个网格。

.item-1 {
  grid-column-start: span 2; // 左边框到右边框跨越 2 个网格;
}
复制代码

span 关键字的效果图

使用这四个属性,如果产生了项目的重叠,则使用 z-index 属性指定项目的重叠顺序。

2.1.3 合并简写写法

// 上面例子的合并简写写法
.item-1 {
  // 指定该项目的四个边框的位置
  grid-column: 1/3;
  grid-row: 2/4;
}
// 或者用 span 关键词
.item-1 {
  // 指定该项目的四个边框的位置
  grid-column: 1/span 2;
  grid-row: 2/span 3;
}
.item-1 {
  // 斜杠之后的可以省略,则默认跨越一个网格线,效果如下图;
  grid-column: 1;
  grid-row: 1;
}
复制代码

默认跨越第一个网格线

2.2 grid-area 属性

属性指定项目放在哪一个区域,可以用 区域名称指定,也可以用 网格线 位置指定;

.container-areas {
  display: inline-grid;
  grid-template-columns: 100px 100px 100px;
  grid-template-rows: 100px 100px 100px;
  /* 给容器划分区域,并命名 */
  grid-template-areas: 'backBtn title header' 'nav container container' 'footer . .';
}
  /* 1.0 直接指定 项目的 所在 区域 */
.areasitem-backBtn {
  background-color: #c077af;
  /* 使用区域名称指定 项目的 位置 */
  grid-area: backBtn;
  color: #fff;
}
.areasitem-header {
  background-color: #4dc7ec;
  grid-area: header;
  color: #fff;
}
/* 2.0 使用网格线指定 */
.item-1 {
  background-color: #ef342a;
  // 2 / 4 / 3 / 1 分别为 上下右左 的网格线位置;
  grid-area: 2 / 4 / 3 / 1;
}
复制代码

2.3 justify-self、align-self 属性

设置单元格内容的水平、垂直位置,类似于 justify-items、align-items 相同的用法,但是只作用于 单个项目;

.item {
  justify-self: start | end | center | stretch;
  align-self: start | end | center | stretch;
}
复制代码

合并简写形式:

place-self: center center;
复制代码

三、参考链接:

阮一峰:

www.ruanyifeng.com/blog/2019/0…

张鑫旭:

www.zhangxinxu.com/wordpress/2…

四、Grid 其他知识点

  • 在Grid布局中,float,display:inline-block,display:table-cell,vertical-align以及column-*这些属性和声明对grid子项是没有任何作用的。
文章分类
前端
文章标签