CSS布局
Contents
1 flex弹性布局
Flex布局的目标是提供一种更有效的方式来布局、对齐和分配容器中子元素的空间,即使它们的大小是未知的或动态的。
flex布局背后的主要想法是让容器能够改变其内部元素的宽度/高度(和顺序),来更好地填充可用空间(主要是适应各种显示设备和屏幕大小)。即或将物品展开以填满可用的空闲空间,或将物品缩小以防止溢出。
最重要的是,flexbox布局与常规布局不同,是方向无关的(区块是基于垂直的,内联是基于水平的)。
注意:Flex布局最适合组件和小规模布局,而Grid布局则适合更大规模的布局。
flex属性按作用范围分为container和items两类
1.1 container
display:flex
:定义容器为flex布局flex-direction
:规定flex容器主轴方向,默认为row- row|row-reverse|column|column-reverse
flex-wrap
:允许换行,默认为nowrap(因为默认情况下,子项总是挤在同一行,即子项宽度定义无效)- nowrap|wrap|wrap-reverse
flex-flow
:前两者的简写形式- flex-flow:column wrap
justify-content
:规定主轴方向的排列形式
align-items
:规定元素垂直轴方向的排列形式
align-content
:当垂直轴上有额外的空间且元素大于一行时,规定全体元素在垂直轴上的排列方式,类似于justify-content在主轴上对齐单个元素。
gap
,row-gap
,column-gap
:指定元素间最小间距,当space过大时,定义gap是不起作用的
1.2 items
order
:默认情况下,items按源顺序排列。order属性可以控制它们在容器中的顺序,默认为0flex-grow
:定义元素在空间足够时自动放大的比例(可以用来自动填满剩余空间),默认为0flex-shrink
:定义元素在空间不足时自动收缩的比例,默认为1flex
:flex-grow
,flex-shrink
和flex-basis
的简写,默认值为0 1 auto
,后两个参数是可选的align-self
:单独定义元素在垂直轴方向的排列形式,同align-items
1.3 align-items与align-content区别
条件 | 属性(是否有效果) | ||
items | container | align-items | align-content |
单行 | 不指定高度 | 是 | 否 |
固定高度 | 是 | 否(当设置flex-warp:warp时,有效果) | |
多行 | 不指定高度 | 是 | 否 |
固定高度 | 是 | 是 |
align-items
属性是针对单独的每一个flex子项起作用,它的基本作用单位是每一个子项,在所有情况下都有效果align-content
属性是将flex子项作为一个整体起作用,它的基本作用单位是子项构成的行,只在两种情况下有效果:- 子项多行且指定flex容器高度
- 子项单行,指定flex容器高度且设置了
flex-wrap:warp
2 grid栅格布局
CSS Grid Layout是一种基于二维网格的布局系统,是第一个专为解决布局问题而发明的CSS模块
grid属性按作用范围分为grid container和grid items两类
2.1 grid container
-
display: grid | inline-grid
:定义容器为grid或inline-grid布局 -
grid-template-columns | grid-template-rows
:定义网格的行与列,可以是长度,也可以是百分数或者fr
- 定义重复的部分,可以使用repeat关键字,例如
repeat(3,20px)
,等同于20px 20px 20px
fr
表示将区间按比例设置为容器空闲空间(去掉指定px的部分)的一部分。例如,这将把每个项目设置为网格容器宽度的三分之一:1fr 1fr 1fr
- 定义重复的部分,可以使用repeat关键字,例如
-
grid-template-areas
:通过引用由grid-area属性指定的网格区域的名称来定义网格模板。重复网格区域的名称会导致内容跨越这些单元格。.
表示空单元格,none
表示不定义此区域。语法本身提供了网格结构的可视化。-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
.item-a { grid-area: header; } .item-b { grid-area: main; } .item-c { grid-area: sidebar; } .item-d { grid-area: footer; } .container { display: grid; grid-template-columns: 50px 50px 50px 50px; grid-template-rows: auto; grid-template-areas: "header header header header" "main main . sidebar" "footer footer footer footer"; }
-
-
grid-template
:在单个声明中设置rows、columns和areas的简写。例如-
1 2 3 4 5 6
.container { grid-template: "header header header" 25px "footer footer footer" 25px / auto 50px auto; }
等价于
1 2 3 4 5 6 7
.container { grid-template-rows: 25px 25px grid-template-columns: auto 50px auto; grid-template-areas: "header header header" "footer footer footer"; }
-
-
column-gap | row-gap | grid-column-gap | grid-row-gap
:指定内部间隙宽度,例如:-
1 2 3 4 5 6
.container { grid-template-columns: 100px 50px 100px; grid-template-rows: 80px auto 80px; column-gap: 10px; row-gap: 15px; }
-
-
gap | grid-gap
:定义间隙的简写,写法为<row-gap> <column-gap>
-
justify-items
:对每个区域内的网格项沿主轴方向进行排列,选项有start|end|center|stretch
,单独调整某个网格项可使用justify-self
属性start
:
end
:
center
:
stretch
:
-
align-items
:对每个区域内的网格项沿垂直轴方向进行排列,选项有start|end|stretch|center
,单独调整某个网格项可使用align-self
属性- 示例效果同上,自行脑补
-
place-items
:justify-items
与align-items
的简写,例如place-items: center | end
-
justify-content
:当网格的总尺寸小于容器的尺寸时(例如全部用px定义网格尺寸),可以使用此属性定义网格整体沿容器主轴方向的排列方式。选项有start|end|stretch|center|space-around|space-between|space-evenly
start
:
end
:
center
:
stretch
:
space-around
:
space-between
:
space-evenly
(间隔宽度相等):
-
align-content
:当网格的总尺寸小于容器的尺寸时(例如全部用px定义网格尺寸),可以使用此属性定义网格整体沿容器垂直轴方向的排列方式。选项有start|end|stretch|center|space-around|space-between|space-evenly
- 效果同上,自行脑补
-
grid-auto-flow
:划分网格以后,容器的子元素会按照顺序,自动放置在每一个网格。默认的放置顺序是"先行后列",即先填满第一行,再开始放入第二行。这个属性由grid-auto-flow
确定,默认为row
。column
:表示从第一列开始,按从上到下的顺序依次填充。row-dense
:表示“先行后列”,并且尽可能紧密填满,尽量不出现空格column-dense
:表示“先列后行”,并且尽可能紧密填满,尽量不出现空格
2.2 grid items
-
grid-column-start | grid-column-end | grid-row-start | grid-row-end
:指定网格项的占位标识,允许数字、线名、span等值,例如1 2 3 4 5 6
.item-b { grid-column-start: 1; grid-column-end: span col4-start; grid-row-start: 2; grid-row-end: span 2; }
-
grid-column | grid-row
:以上属性的简写。示例:1 2 3 4
.item-c { grid-column: 3 / span 2; grid-row: third-line / 4; }
-
grid-area
:以上所有的简写,示例:1 2 3
.item-d { grid-area: 1 / col4-start / last-line / 6; }
-
justify-self
:定义当前网格项内容在网格内部的沿主轴的排列方式,选项有start|end|center|stretch
-
align-self
:定义当前网格项内容在网格内部的沿垂直轴的排列方式,选项有start|end|center|stretch
-
place-self
:以上两项属性的简写,例如place-self: center end
3 面试常考布局
3.1 三栏布局
3.1.1 float浮动实现
从左至右三部分的float属性分别设置为left、left、right,中间部分的宽度使用calc函数计算(100%-side宽度*2)
|
|
3.1.2 position定位实现
父相对,子绝对,定义各元素的left和right属性值即可。
|
|
3.1.3 flex布局实现
|
|
3.1.4 table布局实现
利用display属性的table结合table-cell,实现三栏布局
|
|
3.1.5 grid布局实现
|
|
3.2 圣杯&双飞翼布局
- 圣杯布局是讨论「三栏液态布局」的实现,它最早出自于谁或许不得而查了,但最早的完美实现是来自于 Matthew Levine 于2006年在「A LIST APART」上写的一篇文章,它主要讲述了网页中关于最佳圣杯的实现方法。
所谓液态布局是相对固态布局而言的,固态布局就是固定值不变的布局,液态就好比在容器里到了一杯水,它可以随着容器宽度的变化而自适应宽度。
-
在这篇文章中,作者指出了当时的一些实现方式所存在的问题,如:必须按照源顺序(在 DOM 中表现为先写 Left,然后 Middle,最后,Right)等,它将可能导致代码不够灵活,尤其是从 DOM 的载入顺序上来说,中间的内容不能被首先加载。
-
因此他给出一个方案,它将:
- 两边栏固定,中间自适应;
- 允许中间一栏最先出现;
- 允许任意一栏放在最上面;
- 仅需一个额外的
div
标签 - 仅需非常简单的 CSS,带上最少的兼容性补丁
-
过程:
-
先写header、container、footer三个div,并将三栏放入container中,其中,center部分写在最前面
1 2 3 4 5 6 7 8 9 10 11
<body> <div id="header">#header</div> <div id="container"> <div id="center" class="column">#center</div> <div id="left" class="column">#left</div> <div id="right" class="column">#right</div> </div> <div id="footer">#footer</div> </body>
-
为元素添加基本样式。由于container设置了内边距,因此中间栏看起来就处在了网页的中间,但左右两栏由于排在中间栏的后面,且因为空间不够被挤到了中间栏的下面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
#container .column { float: left; /* 三栏均向左浮动 */ } #container { /* 将内边距设置为左右两栏的宽度 */ padding-left: 200px; padding-right: 150px; } #center { width: 100%; /* 基于父容器container的宽度 */ } #left { width: 200px; /* LC width */ } #right { width: 150px; /* RC width */ } #footer { clear: both; /* 清除 footer 的上下文环境,以免跟上面三栏一起浮动 */ }
-
调整左右两栏的位置
- 首先,我们先将左侧栏的外边距设置为 -100%,这样一来,由于浮动的关系,左侧栏就能上位,与中间栏交叠在一起,并占据了左边。而右侧栏由于左侧栏的上位,自动向前浮动到了原来左侧栏的位置。
- 接着我们要用到相对定位属性(relative),并设置一个与左侧栏等宽的偏移量
- 右侧同理,不过不需要设置右偏移了
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#container .columns { float: left; /* 利用相对定位调整位置 */ position: relative; } #left { width: 200px; /* LC width */ margin-left: -100%; right: 200px; /* LC width */ } #right { width: 150px; /* RC width */ margin-right: -150px; /* RC width */ }
-
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>圣杯布局</title> <style> #container .column { float: left; position: relative; } #container { padding-left: 200px; padding-right: 150px; } #center { background-color: red; width: 100%; /*基于父容器container的width*/ } #left { right: 200px; margin-left: -100%; background-color: orange; width: 200px; } #right { margin-right: -150px; background-color: yellow; width: 150px; } #footer { clear: both } </style> </head> <body> <div id="header">#header</div> <div id="container"> <div id="center" class="column">#center</div> <div id="left" class="column">#left</div> <div id="right" class="column">#right</div> </div> <div id="footer">#footer</div> </body> </html>
-
Author gsemir
LastMod 2021-10-20