CSS-块级布局
相关定义
自适应布局:一套代码,多设备自适应显示。
响应式布局:多套代码,不同设备尺寸范围布局方案不同。
布局样式
弹性盒
弹性盒子是一种用于按行或按列布局元素的一维布局方法 。元素可以膨胀以填充额外的空间, 收缩以适应更小的空间。
Flex 基本概念
Flex 用来为盒状模型提供最大的灵活性,弹性盒子。
采用 Flex 布局的元素,称为 Flex 容器,它的所有子元素自动成为容器成员。
容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴的开始位置(与边框的交叉点)叫做main start,结束位置叫做main end;交叉轴的开始位置叫做cross start,结束位置叫做cross end。
项目默认沿主轴排列。单个项目占据的主轴空间叫做main size,占据的交叉轴空间叫做cross size。

语法
display: flex; /* 将对象作为弹性伸缩盒显示 */
display: inline-flex; /* 将对象作为内联块级弹性伸缩盒显示 */
块级会默认 width = 100%,而内联样式需要指定 width,或者内容撑开 width。
父元素属性
flex-direction 主轴方向
决定主轴方向,即子元素排列方向。
.box {
flex-direction: row | row-reverse | column | column-reverse;
}
flex 默认横向。
row(默认值):主轴为水平方向,起点在左端。row-reverse:主轴为水平方向,起点在右端。column:主轴为垂直方向,起点在上沿。column-reverse:主轴为垂直方向,起点在下沿。
flex-wrap 换行
默认情况下,项目都排在一条线(又称”轴线”)上。flex-wrap属性定义,如果一条轴线排不下,如何换行。
.box{
flex-wrap: nowrap | wrap | wrap-reverse;
}
nowrap(默认值):不换行。wrap:换行,第一行在上方。wrap-reverse:换行,第一行在下方。
flex-flow 联合属性
flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap。
.box {
flex-flow: <flex-direction> || <flex-wrap>;
}
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:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。
align-items 交叉轴上对齐方式
align-items属性定义项目在交叉轴上如何对齐。
.box {
align-items: flex-start | flex-end | center | baseline | stretch;
}
默认交叉轴为纵轴:
flex-start:交叉轴的起点对齐。flex-end:交叉轴的终点对齐。center:交叉轴的中点对齐。baseline: 项目的第一行文字的基线对齐。stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。
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(默认值):轴线占满整个交叉轴。
子元素属性
order 排列顺序
order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。
.item {
order: <integer>;
}
flex-grow 放大比例
flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。
.item {
flex-grow: <number>; /* default 0 */
}
如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。
flex-shrink 缩小比例
flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
.item {
flex-shrink: <number>; /* default 1 */
}
设置为0时,不缩小。负值对该属性无效。
如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。
flex-basis 占主轴空间大小
flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。
.item {
flex-basis: <length> | auto; /* default auto */
}
它可以设为跟width或height属性一样的值(比如350px),则项目将占据固定空间。
flex-basis 属性设置的 0 和 0%,表示的不一样,0% 的效果和 auto 的效果是一样的。
The issue is related to the usage of percentage. Using
0or0pxis trivial since you will set the initial height to be0and then the element will grow to fill the remaining space.Using
N%is a different story because in this case you are setting the initial height to be based on the parent height.Percentages: relative to the flex container’s inner main size ref
In your case, the flex container doesn’t have any explicit size since your are using only a
min-heightdefinition so we cannot resolve the percentange value and it will fail toauto
flex 联合属性
flex属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。
.item {
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)。
建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。
参考链接:
缩写语法:
| 单值语法 | 等同于 | 备注 |
|---|---|---|
| flex: initial | flex: 0 1 auto | 初始值,常用 |
| flex: 0 | flex: 0 1 0% | 适用场景少 |
| flex: none | flex: 0 0 auto | 推荐 |
| flex: 1 | flex: 1 1 0% | 推荐 |
| flex: auto | flex: 1 1 auto | 适用场景少 |
其中:
flex:0 1 0%表示flex-grow是0,flex-shrink是1,因此元素尺寸会收缩但不会扩展,在加上flex-basis:0%表示建议支持是0,因此,设置flex:0的元素的最终尺寸表现为最小内容宽度;flex:0 0 auto表示元素尺寸不会收缩也不会扩展,再加上flex-basis:auto表示固定尺寸由内容决定,由于元素不具有弹性,因此,元素内的内容不会换行,最终尺寸通常表现为最大内容宽度。
需要注意单值语法会不会被 loader 插件进行转换,浏览器自动推算不生效。可能会出现和预想不一样的效果。
应用场景:
flex: none;当flex子项的宽度就是内容的宽度,且内容永远不会换行,则适合使用flex:none,这个场景比flex:0适用的场景要更常见。flex:1的尺寸表现更为内敛(优先牺牲自己的尺寸)。当希望元素充分利用剩余空间,同时不会侵占其他元素应有的宽度的时候,适合使用flex:1,这样的场景在Flex布局中非常的多。不确定可分配到的空间,且子元素不会撑开父元素空间。flex: 1;和flex: 1 1;最后浏览器推算的是一样的。flex:auto的尺寸表现则更为霸道(优先扩展自己的尺寸)。当希望元素充分利用剩余空间,但是各自的尺寸按照各自内容进行分配的时候,适合使用flex:auto。flex:auto多用于内容固定,或者内容可控的布局场景,
总结:
flex:initial表示默认的flex状态,无需专门设置,适合小控件元素的分布布局,或者某一项内容动态变化的布局;flex:0适用场景较少,适合设置在替换元素的父元素上;flex:none适用于不换行的内容固定或者较少的小控件元素上,如按钮。flex:1适合等分布局;flex:auto适合基于内容动态适配的布局;
align-self 当前元素对齐方式
align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。
.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
auto(默认值):表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。flex-start:交叉轴的起点对齐。flex-end:交叉轴的终点对齐。center:交叉轴的中点对齐。baseline: 项目的第一行文字的基线对齐。stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。
参考链接
Flex 布局教程:语法篇 - 阮一峰: https://www.ruanyifeng.com/blog/2015/07/flex-grammar.html
Flex 布局教程:实例篇 - 阮一峰:https://www.ruanyifeng.com/blog/2015/07/flex-examples.html
A Complete Guide to Flexbox : https://css-tricks.com/snippets/css/a-guide-to-flexbox/
网格
网格是一个用于web的二维布局系统。利用网格,你可以把内容按照行与列的格式进行排版。
Grid概念
网格布局,它将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局。

行和列:网格布局有行和列的概念。
单元格:行和列的交叉区域。
网格线:划分网络的线。
与 Flex 的区别
Grid 布局与 Flex 布局有一定的相似性,都可以指定容器内部多个项目的位置。但是,它们也存在重大区别。
Flex 布局是轴线布局,只能指定”项目”针对轴线的位置,可以看作是一维布局。Grid 布局则是将容器划分成”行”和”列”,产生单元格,然后指定”项目所在”的单元格,可以看作是二维布局。Grid 布局远比 Flex 布局强大。
语法
.container {
display: grid | inline-grid;
}
grid:块级元素inline-grid:内联块级元素
父元素属性
grid-template-columns 列 & grid-template-rows 行
grid-template-columns 划分容器的列,定义每一列的列宽。
grid-template-rows 划分容器的行,定义每一列的行高。
none关键字,所有的列和其大小都将由grid-auto-columns属性隐式的指定。绝对单位
百分比
repeat()函数,简化重复值。接受两个参数,重复的次数和重复的值。auto-fill关键字,如果希望每一行(列)容纳尽可能多的单元格,这时可以使用auto-fill关键字表示自动填充。fr关键字,为了方便表示比例关系,网格布局提供了fr关键字。如果两列的宽度分别为1fr和2fr,就表示后者是前者的两倍。fr可以与绝对长度的单位结合使用,这时会非常方便。minmax()函数产生一个长度范围,表示长度就在这个范围之中。它接受两个参数,分别为最小值和最大值。auto关键字表示由浏览器自己决定长度。网格线名称,可以使用方括号指定网格线的名称,方便以后引用。网格线可以拥有多个名字。
/* Keyword value 这个关键字表示不明确的网格。所有的列和其大小都将由 grid-auto-columns 属性隐式的指定。 */
grid-template-columns: none;
/* <track-list> values */
grid-template-columns: 100px 1fr;
grid-template-columns: [linename] 100px;
grid-template-columns: [linename1] 100px [linename2 linename3];
grid-template-columns: minmax(100px, 1fr);
grid-template-columns: fit-content(40%);
grid-template-columns: repeat(3, 200px);
/* <auto-track-list> values */
grid-template-columns: 200px repeat(auto-fill, 100px) 300px;
grid-template-columns: minmax(100px, max-content)
repeat(auto-fill, 200px) 20%;
grid-template-columns: [linename1] 100px [linename2]
repeat(auto-fit, [linename3 linename4] 300px)
100px;
grid-template-columns: [linename1 linename2] 100px
repeat(auto-fit, [linename1] 300px) [linename3];
/* Global values */
grid-template-columns: inherit;
grid-template-columns: initial;
grid-template-columns: unset;
grid-template-areas 区域
网格布局允许指定”区域”(area),一个区域由单个或多个单元格组成。
网格区块(grid areas)和网格项(grid item)沒有关联,但是它们可以和一些网格定位属性(grid-placement properties)关联起来
grid-template-areas属性用于定义区域。
- none:网格容器没有定义任何的网格区块(grid areas)。
- string+:每一个给定的字符串会生成一行,一个字符串中用空格分隔的每一个单元(cell)会生成一列。多个同名的,跨越相邻行或列的单元称为网格区块(grid area)。非矩形的网格区块是无效的。string 可以是 grid-area-name。
CSS 类中设置 grid-area-name。如:(grid-area也可为子元素指定区域)
.a { grid-area: a }
/* Keyword value */
grid-template-areas: none;
/* <string> values */
grid-template-areas: "a b"; /* 一行 两列 */
grid-template-areas: "a b b"
"a c d"; /* 两行 三列 */
grid-template-areas: "a a ." /* .表示空的表格 */
"a a ."
". b c";
/* Global values */
grid-template-areas: inherit; /* 继承 */
grid-template-areas: initial; /* 默认值 */
grid-template-areas: unset; /* 未设置 */
注意,区域的命名会影响到网格线。每个区域的起始网格线,会自动命名为
区域名-start,终止网格线自动命名为区域名-end。比如,区域名为
header,则起始位置的水平网格线和垂直网格线叫做header-start,终止位置的水平网格线和垂直网格线叫做header-end。
grid-template 联合属性
grid-template,CSS属性简写,用以定义网格中rows、columns与areas。
/* 值为关键词 */
grid-template: none;
/* 为 grid-template-rows / grid-template-columns */
grid-template: 100px 1fr / 50px 1fr;
grid-template: auto 1fr / auto 1fr auto;
grid-template: [linename] 100px / [columnname1] 30% [columnname2] 70%;
grid-template: fit-content(100px) / fit-content(40%);
/* 为 grid-template-areas grid-template-rows / grid-template-column */
grid-template: "a a a"
"b b b";
grid-template: "a a a" 20%
"b b b" auto;
grid-template: [header-top] "a a a" [header-bottom]
[main-top] "b b b" 1fr [main-bottom]
/ auto 1fr auto;
/* 为全局值 */
grid-template: inherit;
grid-template: initial;
grid-template: unset;
row-gap 行间距 & column-gap 列间距 & gap 联合间距
row-gap属性设置行与行的间隔(行间距)。
column-gap属性设置列与列的间隔(列间距)。
gap属性是row-gap和column-gap的合并简写形式。
.container {
row-gap: 20px;
column-gap: 20px;
}
.container {
gap: 20px 20px; /* <row-gap> <column-gap> */
}
.container {
gap: 20px; /* <row-gap> = <column-gap> */
}
grid-auto-flow 子元素顺序
划分网格以后,容器的子元素会按照顺序,自动放置在每一个网格。默认的放置顺序是”先行后列”,即先填满第一行,再开始放入第二行,即下图数字的顺序。
row(默认值):先行后列column:先列后行dense:剩下的位置如何摆放。“稠密”堆积算法,如果后面出现了稍小的元素,则会试图去填充网格中前面留下的空白。这样做会填上稍大元素留下的空白,但同时也可能导致原来出现的次序被打乱。如果省略它,使用一种「稀疏」算法,在网格中布局元素时,布局算法只会「向前」移动,永远不会倒回去填补空白。这保证了所有自动布局元素「按照次序」出现,即使可能会留下被后面元素填充的空白。
/* Keyword values */
grid-auto-flow: row;
grid-auto-flow: column;
grid-auto-flow: dense;
grid-auto-flow: row dense;
grid-auto-flow: column dense;
/* Global values */
grid-auto-flow: inherit;
grid-auto-flow: initial;
grid-auto-flow: unset;
justify-items 单元格内水平位置 & align-items 单元格内垂直位置 & place-items 联合属性
justify-items属性设置单元格内容的水平位置(左中右)。
align-items属性设置单元格内容的垂直位置(上中下)。
place-item属性是align-items属性和justify-items属性的合并简写形式。
- start:对齐单元格的起始边缘。
- end:对齐单元格的结束边缘。
- center:单元格内部居中。
- stretch:拉伸,占满单元格的整个宽度(默认值)。
.container {
justify-items: start;
align-items: start;
}
.container {
place-items: start start; /* <align-items>, <justify-items> */
}
.container {
place-items: start; /* <align-items> = <justify-items> */
}
justify-content 整体内容水平位置 & align-content 整体内容垂直位置 & place-content 联合属性
justify-content属性是整个内容区域在容器里面的水平位置(左中右)。
align-content属性是整个内容区域的垂直位置(上中下)。
place-content 属性是align-content属性和justify-content属性的合并简写形式。
- start: 对齐容器的起始边框。
- end :对齐容器的结束边框。
- center: 容器内部居中。
- stretch: 项目大小没有指定时,拉伸占据整个网格容器。
- space-around: 每个项目两侧的间隔相等。所以,项目之间的间隔比项目与容器边框的间隔大一倍。
- space-between: 项目与项目的间隔相等,项目与容器边框之间没有间隔。
- space-evenly: 项目与项目的间隔相等,项目与容器边框之间也是同样长度的间隔。
grid-auto-columns 自动创建列 & grid-auto-rows 自动创建行
grid-auto-columns 指定了隐式创建的网格纵向轨道(track)的宽度。
grid-auto-rows 用于指定隐式创建的行轨道大小。
有时候,一些项目的指定位置,在现有网格的外部。比如网格只有3列,但是某一个项目指定在第5行。这时,浏览器会自动生成多余的网格,以便放置项目。
grid-auto-columns属性和grid-auto-rows属性用来设置,浏览器自动创建的多余网格的列宽和行高。它们的写法与grid-template-columns和grid-template-rows完全相同。如果不指定这两个属性,浏览器完全根据单元格内容的大小,决定新增网格的列宽和行高。
.container {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
grid-auto-rows: 50px;
}
划分好的网格是3行 x 3列,但是,8号项目指定在第4行,9号项目指定在第5行。
grid 合并属性
grid属性是grid-template-rows、grid-template-columns、grid-template-areas、 grid-auto-rows、grid-auto-columns、grid-auto-flow这六个属性的合并简写形式。
/* <'grid-template'> values */
grid: none;
grid: "a" 100px "b" 1fr;
grid: [linename1] "a" 100px [linename2];
grid: "a" 200px "b" min-content;
grid: "a" minmax(100px, max-content) "b" 20%;
grid: 100px / 200px;
grid: minmax(400px, min-content) / repeat(auto-fill, 50px);
/* <'grid-template-rows'> /
[ auto-flow && dense? ] <'grid-auto-columns'>? values */
grid: 200px / auto-flow;
grid: 30% / auto-flow dense;
grid: repeat(3, [line1 line2 line3] 200px) / auto-flow 300px;
grid: [line1] minmax(20em, max-content) / auto-flow dense 40%;
/* [ auto-flow && dense? ] <'grid-auto-rows'>? /
<'grid-template-columns'> values */
grid: auto-flow / 200px;
grid: auto-flow dense / 30%;
grid: auto-flow 300px / repeat(3, [line1 line2 line3] 200px);
grid: auto-flow dense 40% / [line1] minmax(20em, max-content);
/* Global values */
grid: inherit;
grid: initial;
grid: unset;
子元素属性
gird-column-start & grid-column-end & grid-row-start & grid-row-end 指定边框
项目的位置是可以指定的,具体方法就是指定项目的四个边框,分别定位在哪根网格线。
grid-column-start属性:左边框所在的垂直网格线grid-column-end属性:右边框所在的垂直网格线grid-row-start属性:上边框所在的水平网格线grid-row-end属性:下边框所在的水平网格线
值为网格线序列号或者网格线名称。
使用span关键字,表示”跨越”,即左右边框(上下边框)之间跨越多少个网格。
使用这四个属性,如果产生了项目的重叠,则使用z-index属性指定项目的重叠顺序。
grid-column & grid-row 边框合并属性
grid-column属性是grid-column-start和grid-column-end的合并简写形式。
grid-row属性是grid-row-start属性和grid-row-end的合并简写形式。
.item {
grid-column: <start-line> / <end-line>;
grid-row: <start-line> / <end-line>;
}
.item-1 {
grid-column: 1 / 3;
grid-row: 1 / 2;
}
/* 等同于 */
.item-1 {
grid-column-start: 1;
grid-column-end: 3;
grid-row-start: 1;
grid-row-end: 2;
}
grid-area 指定区域
grid-area属性指定项目放在哪一个区域。值可以为指定的 grid-area-name
grid-area 是一种对于 grid-row-start (en-US)、grid-column-start (en-US)、grid-row-end (en-US) 和 grid-column-end (en-US) 的简写,通过基线(line),跨度(span)或没有(自动)的网格放置在 grid row 中指定一个网格项的大小和位置,继而确定 grid area 的边界。
/* Keyword values */
grid-area: auto;
grid-area: auto / auto;
grid-area: auto / auto / auto;
grid-area: auto / auto / auto / auto;
/* <custom-ident> values */
grid-area: some-grid-area;
grid-area: some-grid-area / another-grid-area;
/* <integer> && <custom-ident>? values */
grid-area: some-grid-area 4;
grid-area: some-grid-area 4 / 2 another-grid-area;
/* span && [ <integer> || <custom-ident> ] values */
grid-area: span 3;
grid-area: span 3 / span some-grid-area;
grid-area: 2 span / another-grid-area span;
/* Global values */
grid-area: inherit;
grid-area: initial;
grid-area: unset;
justify-self 单元格内容水平位置 & align-self 单元格内容的垂直位置 & place-self 联合属性
justify-self属性设置单元格内容的水平位置(左中右),跟justify-items属性的用法完全一致,但只作用于单个项目。
align-self属性设置单元格内容的垂直位置(上中下),跟align-items属性的用法完全一致,也是只作用于单个项目。
place-self属性是align-self属性和justify-self属性的合并简写形式。
- start:对齐单元格的起始边缘。
- end:对齐单元格的结束边缘。
- center:单元格内部居中。
- stretch:拉伸,占满单元格的整个宽度(默认值)。
.item-1 {
justify-self: start;
align-self: start;
}
.item-1 {
place-self: start start; /* <align-self> <justify-self> */
}
.item-1 {
place-self: start; /* <align-self> = <justify-self> */
}
参考链接
A Complete Guide to Grid - CSS Tricks
更多阅读
格式上下文
BFC - 块级格式上下文
Block formatting contexts
具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器所没有的一些特性。
触发BFC
- body 根元素
- 浮动元素:float 除 none 以外的值
- 绝对定位元素:position (absolute、fixed)
- display 为 inline-block、table-cells、flex、table-caption
- overflow 除了 visible 以外的值 (hidden、auto、scroll)
应用
- BFC 可以包含浮动的元素(清除浮动)
- BFC 可以阻止元素被浮动元素覆盖
IFC - 内联格式上下文
IFC(Inline formatting contexts) 的线框高度由其包含行内元素中最高的实际高度计算而来,不受到竖直方向的 padding / margin 影响。
IFC 中的 line box 一般左右都贴紧整个 IFC,但是会因为 float 元素而扰乱。
float 元素会位于 IFC 与 line box 之间,使得 line box 宽度缩短。
同个 IFC 下的多个 line box 高度会不同。
IFC 中不能有块级元素,当插入块级元素时(如 p 中插入 div)会产生两个匿名块与 div 分隔开,即产生两个 IFC,每个 IFC 对外表现为块级元素,与 div 垂直排列。
应用
水平居中:当一个块要在环境中水平居中时,设置其为 inline-block 则会在外层产生 IFC,通过 text-align 则可以使其水平居中。
垂直居中:创建一个 IFC,用其中一个元素撑开父元素的高度,然后设置其 vertical-align: middle,其他行内元素则可以在此父元素中垂直居中。
GFC - 网格布局格式化上下文
GrideLayout formatting contexts
触发条件
设置 display 值为 grid。
FFC - 自适应格式上下文
Flex formatting contexts
触发条件
display 值为 flex 或者 inline-flex 的元素将会生成自适应容器(flex container)。
通过设置元素的 display 属性为 flex 或 inline-flex 可以得到一个伸缩容器。
设置为 flex 的容器被渲染为一个块级元素,而设置为 inline-flex 的容器则渲染为一个行内元素。
伸缩容器中的每一个子元素都是一个伸缩项目。伸缩项目可以是任意数量的。伸缩容器外和伸缩项目内的一切元素都不受影响。
实践
flex:
聊天界面
瀑布流
grid:
- 等分响应式
- 固定列宽,改变列数量
- 去掉右侧空白
- 补全空缺