一个非前端开发者的CSS布局学习笔记

在 Web 前端开发中,CSS 布局是非常重要的知识技能。本篇文章主要是记录我在学习 CSS 布局知识时的学习笔记,阅读之前需要你了解部分的 CSS 和 HTML 知识。

几个重要的 CSS 布局相关属性

display 属性

display是 CSS 中非常重要的用来控制布局的属性, HTML 中每个元素都有一个默认的display属性,大多数元素该属性的默认值为blockinlineblock元素被称为块级元素,inline元素通常被称为行内元素。display属性值通常有如下几种取值:

  • block:块级元素。它会新开始一行,HTML 中大多数元素都默认为该值,如:divpform等元素。
  • inline:行内元素。它不会新开始一行,行内元素可以在段落中而不打乱段落布局。spana等元素默认为该值。
  • inline-block:它是 blockinline 的结合体,主要用来把块级元素变换为行内元素,方便布局。
  • flex:一种新的布局方式,可以让布局更简单。
  • none:设置为该值的元素会被隐藏,布局时此类型元素可以不用考虑。

margin 属性

margin属性用于指定本元素距离周围元素的距离,在布局时,会经常用到。

max-width 属性

max-width用于指定当前元素最大宽度,当父容器宽度变小时,元素宽度会减小,但是当父容器宽度变大时,该元素最大宽度为指定宽度。

盒子模型

CSS 元素由内容、内边距、边框、外边距组成,我们平时设置元素的 widthheight 等相关属性时,默认情况下,设置的都只是内容的大小,内边距,边框、外边距都可能会增大元素的实际大小。具体内容可能参考这篇文章:CSS 基础框盒模型介绍

如下所示,两个div元素都设置了同样的宽度,但是设置了外边距和边框的div元素明显实际宽度更大一些。

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<style>
#box-model .simple {
width: 500px;
margin: 20px auto;
border: 2px solid green;
}
#box-model .fancy {
width: 500px;
margin: 20px auto;
padding: 50px;
border: 10px solid green;
}
</style>

<div class="simple">
I'm use box-sizing, My width is 500px.
</div>
<div class="fancy">
I'm use box-sizing, My width is 500px.
</div>

box-sizing 属性

当把一个元素的 box-sizing 属性设置为 border-box 时,内边距和边框不会再增加元素的实际大小。

如下所示,两个div元素都设置了同样的宽度,但是设置了内边距和边框的div元素实际宽度没有变大。

代码示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<style>
#box-sizing .simple {
box-sizing: border-box;
width: 500px;
margin: 20px auto;
border: 2px solid green;
}
#box-sizing .fancy {
box-sizing: border-box;
width: 500px;
margin: 20px auto;
padding: 50px;
border: 10px solid green;
}
</style>

<div class="simple">
I'm use box-sizing, My width is 500px.
</div>
<div class="fancy">
I'm use box-sizing, My width is 500px.
</div>

使用 position 布局

position 属性

position 属性是 CSS 布局中常用的属性,可以有如下的取值:

  • static:默认值,当一个元素被设置为 static 时,表示元素不能被 positioned(主要为absolute服务)。
  • relative:与 static 基本一致,区别在于元素可以被 positioned
  • fixed:固定定位,元素会相对于整个视窗(可以理解为浏览器窗口)定位,即使页面发生滚动,它还是会停留在相同的位置。
  • absolute:绝对定位,与 fixed 相似,但它的定位是相对于最近的可以被 positioned 的祖先元素。

position 布局示例

使用 position 完成如下所示的布局:

代码示例:

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
<style>
#position-layout {
width: 90%;
margin: 0 auto;
position: relative;
border: 2px solid green;
}
#position-layout .nav {
position: absolute;
top: 0px;
left: 0px;
width: 200px;
padding-left: 20px;
border: 2px solid red;
box-sizing: border-box;
}
#position-layout section {
margin-left: 200px;
border: 2px solid orange;
box-sizing: border-box;
}
</style>

<div id="position-layout">
<div class="nav">
<li><a href="#">menuItem1</a></li>
<li><a href="#">menuItem2</a></li>
<li><a href="#">menuItem3</a></li>
</div>
<section>
This is a long section.This is a long section.This is a long
section.This is a long section.This is a long section.This is a long
section.This is a long section.This is a long section.This is a long
section.This is a long section.This is a long section.This is a long
section.
</section>
<section>
This is a long section too.This is a long section too.This is a long
section too.This is a long section too.This is a long section too.This
is a long section too.This is a long section too.This is a long section
too.This is a long section too.This is a long section too.This is a long
section too.This is a long section too.
</section>
</div>

使用 float 布局

float 属性

为了防止影响后续元素,在使用 float 时注意使用 clear 清除浮动。

float 可以用于实现如下所示的文字环绕图片效果:

代码示例:

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
<style>
#float {
overflow: auto;
border: 2px solid orange;
}
#float img {
width: 200px;
float: left;
margin: 0 1em 1em 0;
}
#float:after {
content: '.';
display: block;
height: 0;
clear: both;
visibility: hidden;
}
</style>
<div id="float">
<img
src="https://cn.bing.com/th?id=OHR.RhinosOxpecker_ZH-CN6392794613_1920x1080.jpg"
/>
<section>
犀牛(学名:Dicerorhinus)是哺乳类犀科的总称,有4属5种。是世界上最大的奇蹄目动物,
犀类动物腿短、体肥笨拙,体长2.2-4.5米,肩高1.2-2米,体重2000-5000千克。前后肢均三趾;
皮厚粗糙,并于肩腰等处成褶皱排列,毛被稀少而硬,甚或大部无毛;耳呈卵圆形,头大而长,颈短粗,长唇延长伸出;
头部有实心的独角或双角(有的雌性无角),起源于真皮,角脱落仍能复生;无犬齿;尾细短,身体呈黄褐、褐、黑或灰色。
栖息于低地或海拔2000多米的高地。夜间活动,独居或结成小群。生活区域从不脱离水源。食性因种类而异,
以草类为主,或以树叶、嫩枝、野果、地衣等为食物。母兽妊娠期18-19个月。寿命30-50年。
因犀牛角的装饰和药用价值而被大量捕捉,除白犀外均为濒危物种。分布于亚洲南部、东南亚和非洲撒哈拉以南地区
9月22日是“世界犀牛日”(World Rhino
Day)。2010年,“世界犀牛日”由南非世界自然基金会创办(WWF-South
Africa),现已为全世界广泛接受。该活动旨在关注全球稀有动物。
在渐新世出现了有史以来最大陆生哺乳动物——巨犀,它体格健壮和高大,体长约8米,身高5米。不过虽然巨犀和犀牛同属奇蹄目,但并不属于犀牛科。
中新世的后期,出现了独角犀牛的祖先。独角犀牛仅存爪哇犀牛和印度犀牛,均分布在亚洲。在中新世以后出现的犀牛体型与现代犀牛相接近。
其中有下唇比上唇略大些的大唇犀,下颌有两颗大牙向前伸出,生活在沼泽地带,以水中的植物为食。
上新世后期(约300万年前),双角犀牛出现。双角犀牛有苏门达腊犀、白犀牛和黑犀牛。第四纪时期人类已经出现,早期的犀牛以板齿犀、披毛犀为代表。
板齿犀个体巨大,5米长,身披厚甲,在额部生有大角,约2米长,牙齿的齿冠高,呈方柱状,草地上生活,
更新世时期在中国华北的及欧洲等地曾有板齿犀生活;披毛犀和猛犸象外形相似,巨大的身体及长着粗毛的厚皮可以抵御寒冷,长鼻上有一对巨角,
前面一支最长可达1米,生活在寒冷地带。这两种犀类先后在不同的时期都已经灭绝了。
在犀类的后代中,现仅残存有犀牛科的4属5种,主要分布在亚洲和非洲,其中分布在亚洲的犀牛已经濒临绝种。
主要是因为犀牛角作为药材,其实犀牛角跟指甲是一样的构造,随数量减少现在也不容易买到真正的犀牛角,
市场还得以购买是因为现在商贩懂得以牛角替代来获利,甚至用相似成分的猫狗爪磨成假货变换充数。
</section>
</div>

float 布局示例

使用 float 完成如下所示的布局:

代码示例:

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
47
48
<style>
#float-layout {
width: 90%;
margin: 0 auto;
border: 2px solid green;
}
#float-layout .nav {
float: left;
width: 200px;
padding-left: 20px;
border: 2px solid red;
box-sizing: border-box;
}
#float-layout section {
margin-left: 200px;
border: 2px solid orange;
box-sizing: border-box;
}
#float-layout:after {
content: '.';
display: block;
height: 0;
clear: both;
visibility: hidden;
}
</style>

<div id="float-layout">
<div class="nav">
<li><a href="#">menuItem1</a></li>
<li><a href="#">menuItem2</a></li>
<li><a href="#">menuItem3</a></li>
</div>
<section>
This is a long section.This is a long section.This is a long
section.This is a long section.This is a long section.This is a long
section.This is a long section.This is a long section.This is a long
section.This is a long section.This is a long section.This is a long
section.
</section>
<section>
This is a long section too.This is a long section too.This is a long
section too.This is a long section too.This is a long section too.This
is a long section too.This is a long section too.This is a long section
too.This is a long section too.This is a long section too.This is a long
section too.This is a long section too.
</section>
</div>

使用 inline-block 布局

使用 inline-block 的注意事项

  • vertical-align 属性会影响到 inline-block 元素,可能需要把它的值设置为 top
  • 需要设置每一列的宽度
  • 如果源代码中 inline-block 元素之间有空格或者换行,那么列之间会产生空隙。如果同行的元素使用了百分比宽度且加起来和是100%宽度,但是由于代码的换行,导致列之间有空隙,会出现元素无法排列在同一行的现象。

inline-block 布局示例

使用 inline-block 完成如下所示的布局:

代码示例:

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
47
48
49
50
51
52
53
<style>
#inline-block-layout {
width: 90%;
margin: 0 auto;
border: 2px solid green;
font-size: 0;
}
#inline-block-layout .nav {
display: inline-block;
vertical-align: top;
width: 25%;
padding-left: 20px;
border: 2px solid red;
box-sizing: border-box;
font-size: 16px;
}
#inline-block-layout .column {
display: inline-block;
vertical-align: top;
width: 75%;
border: 2px solid red;
box-sizing: border-box;
font-size: 16px;
}
#inline-block-layout .column section {
border: 2px solid orange;
box-sizing: border-box;
}
</style>

<div id="inline-block-layout">
<div class="nav">
<li><a href="#">menuItem1</a></li>
<li><a href="#">menuItem2</a></li>
<li><a href="#">menuItem3</a></li>
</div>
<div class="column">
<section>
This is a long section.This is a long section.This is a long
section.This is a long section.This is a long section.This is a long
section.This is a long section.This is a long section.This is a long
section.This is a long section.This is a long section.This is a long
section.
</section>
<section>
This is a long section too.This is a long section too.This is a long
section too.This is a long section too.This is a long section too.This
is a long section too.This is a long section too.This is a long
section too.This is a long section too.This is a long section too.This
is a long section too.This is a long section too.
</section>
</div>
</div>

使用 flexbox 布局

flextbox 是一种新的布局方式,可能会有一些旧的浏览器无法支持 flexbox 布局。使用flexbox布局可以轻松实现复杂的布局,可以非常容易的实现垂直居中和水平居中,使用起来极为方便。

flexbox 简单布局示例

使用 flexbox 完成如下所示的布局:

代码示例:

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
47
<style>
#flexbox-layout {
display: flex;
width: 90%;
margin: 0 auto;
border: 2px solid green;
}
#flexbox-layout .nav {
width: 200px;
padding-left: 20px;
border: 2px solid red;
box-sizing: border-box;
}
#flexbox-layout .column {
flex: 1;
border: 2px solid red;
box-sizing: border-box;
}
#flexbox-layout .column section {
border: 2px solid orange;
box-sizing: border-box;
}
</style>

<div id="flexbox-layout">
<div class="nav">
<li><a href="#">menuItem1</a></li>
<li><a href="#">menuItem2</a></li>
<li><a href="#">menuItem3</a></li>
</div>
<div class="column">
<section>
This is a long section.This is a long section.This is a long
section.This is a long section.This is a long section.This is a long
section.This is a long section.This is a long section.This is a long
section.This is a long section.This is a long section.This is a long
section.
</section>
<section>
This is a long section too.This is a long section too.This is a long
section too.This is a long section too.This is a long section too.This
is a long section too.This is a long section too.This is a long
section too.This is a long section too.This is a long section too.This
is a long section too.This is a long section too.
</section>
</div>
</div>

flexbox 复杂布局示例

实现如下所示四列布局方式,左边两列固定宽度,右边两列分别占剩下的空间1/3和2/3。

示例代码:

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
<style>
#flexbox-complex-layout {
display: flex;
width: 90%;
margin: 0 auto;
border: 2px solid green;
}
#flexbox-complex-layout .nav {
width: 200px;
min-width: 100px;
border: 2px solid red;
box-sizing: border-box;
}
#flexbox-complex-layout .carousel {
flex: none;
width: 200px;
border: 2px solid red;
box-sizing: border-box;
}
#flexbox-complex-layout .column1 {
flex: 1;
border: 2px solid red;
box-sizing: border-box;
}
#flexbox-complex-layout .column2 {
flex: 2;
border: 2px solid red;
box-sizing: border-box;
}
</style>

<div id="flexbox-complex-layout">
<div class="nav">
I have 200px width when the space is enough, otherwise my width is
100px.
</div>
<div class="carousel">
I have 200px width whenever the space is enough or not.
</div>
<div class="column1">
I have one third width of the left space.
</div>
<div class="column2">
I have two third width of the left space.
</div>
</div>

flexbox 水平与垂直居中示例

实现如下所示的水平与垂直方向上的居中。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<style>
#flexbox-easy-center {
display: flex;
width: 90%;
height: 100px;
margin: 0 auto;
align-items: center;
justify-content: center;
border: 2px solid green;
box-sizing: border-box;
}
#flexbox-easy-center section {
border: 2px solid green;
box-sizing: border-box;
}
</style>

<div id="flexbox-easy-center">
<section>
I'm in the middle of the container.
</section>
</div>

媒体查询与响应式

布局随着不同大小的视窗动态调整布局,这就被称为响应式布局,响应式布局可以通过媒体查询来实现。

如下图表示,当视窗的宽度大于600px时,采用两栏式布局,当宽度小于600px时,采用单栏式布局,菜单也切换为横向菜单。

示例代码:

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
47
48
49
50
51
52
53
54
<style>
#media-query {
width: 90%;
margin: 0 auto;
position: relative;
border: 2px solid green;
}
#media-query .nav {
padding-left: 20px;
border: 2px solid red;
box-sizing: border-box;
}
#media-query section {
border: 2px solid orange;
box-sizing: border-box;
}
@media screen and (min-width: 600px) {
#media-query .nav {
position: absolute;
top: 0px;
left: 0px;
width: 25%;
}
#media-query section {
margin-left: 25%;
}
}
@media screen and (max-width: 599px) {
#media-query .nav li {
display: inline;
}
}
</style>
<div id="media-query">
<div class="nav">
<li><a href="#">menuItem1</a></li>
<li><a href="#">menuItem2</a></li>
<li><a href="#">menuItem3</a></li>
</div>
<section>
This is a long section.This is a long section.This is a long
section.This is a long section.This is a long section.This is a long
section.This is a long section.This is a long section.This is a long
section.This is a long section.This is a long section.This is a long
section.
</section>
<section>
This is a long section too.This is a long section too.This is a long
section too.This is a long section too.This is a long section too.This
is a long section too.This is a long section too.This is a long section
too.This is a long section too.This is a long section too.This is a long
section too.This is a long section too.
</section>
</div>

元素居中

元素居中是常用的布局技巧,包括水平居中和垂直居中。下文的居中示例代码使用的通用CSS代码如下所示:

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
<style>
h4 {
text-align: center;
}

#align-center > div {
margin-top: 50px;
width: 100%;
height: 100px;
box-sizing: border-box;
}

#align-center .child {
height: 30px;
border: 2px solid black;
}

#vertical-center > div {
margin-top: 50px;
width: 100%;
height: 100px;
box-sizing: border-box;
}

#vertical-center .child {
height: 30px;
border: 2px solid black;
}
</style>

水平居中的常用方法

水平居中包括以下几种常见实现方式。水平居中效果如下图所示:

子元素为inline

父元素设置text-align: center,代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<style>
#align-center > .inline {
text-align: center;
border: 2px solid green;
}

#align-center > .inline > .child {
display: inline;
}
</style>
<div id="align-center">
<div class="inline">
<div class="child">I am inline</div>
</div>
</div>
子元素为block并且宽度固定

子元素设置margin: 0 auto,代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<style>
#align-center > .block-width {
border: 2px solid blue;
}

#align-center > .block-width > .child {
display: block;
width: 200px;
margin: 0 auto;
}
</style>
<div id="align-center">
<div class="block-width">
<div class="child">
I am block with width
</div>
</div>
</div>
子元素为block并且宽度不固定

设置子元素display: inline,设置父元素text-align: center,代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<style>
#align-center > .block-no-width {
border: 2px solid red;
text-align: center;
}

#align-center > .block-no-width > .child {
display: inline;
}
</style>
<div id="align-center">
<div class="block-no-width">
<div class="child">
I am block without width
</div>
</div>
</div>
使用transform

父元素设置position: relative,子元素使用绝对定位与transform配合实现,代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<style>
#align-center > .transform {
position: relative;
border: 2px solid orange;
}

#align-center > .transform > .child {
position: absolute;
transform: translate(-50%, 0);
left: 50%;
}
</style>
<div id="align-center">
<div class="transform">
<div class="child">
I am transform
</div>
</div>
</div>
使用flex

父元素设置flex布局与justify-content: center,代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
<style>
#align-center > .flex {
display: flex;
justify-content: center;
border: 2px solid purple;
}
</style>
<div id="align-center">
<div class="flex">
<div class="child">I am flex</div>
</div>
</div>

垂直居中的常用方法

垂直居中包括以下几种常见实现方式。水平居中效果如下图所示:

子元素为block

父元素设置position: relative,子元素使用绝对定位与margin配合实现,代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<style>
#vertical-center > .block {
position: relative;
border: 2px solid green;
}

#vertical-center > .block > .child {
display: block;
position: absolute;
margin: auto;
top: 0;
bottom: 0;
}
</style>
<div id="vertical-center">
<div class="block">
<div class="child">I am block</div>
</div>
</div>
子元素为inline

父元素设置line-heightheight值相等,代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<style>
#vertical-center > .inline {
border: 2px solid blue;
line-height: 100px;
}

#vertical-center > .inline > .child {
display: inline;
}
</style>
<div id="vertical-center">
<div class="inline">
<div class="child">I am inline</div>
</div>
</div>
子元素为inline-block

父元素添加after伪元素,子元素设置vertical-align: middle,代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<style>
#vertical-center > .inline-block {
border: 2px solid red;
}

#vertical-center > .inline-block:after {
content: '';
height: 100%;
display: inline-block;
vertical-align: middle;
}

#vertical-center > .inline-block > .child {
display: inline-block;
vertical-align: middle;
}
</style>
<div id="vertical-center">
<div class="inline-block">
<div class="child">I am inline-block</div>
</div>
</div>
使用transform

父元素设置position: relative,子元素使用绝对定义配合transform实现,代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<style>
#vertical-center > .transform {
position: relative;
border: 2px solid orange;
}

#vertical-center > .transform > .child {
position: absolute;
transform: translate(0, -50%);
top: 50%;
}
</style>
<div id="vertical-center">
<div class="transform">
<div class="child">I am transform</div>
</div>
</div>
使用flex

父元素设置flex布局与align-items: center,代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
<style>
#vertical-center > .flex {
display: flex;
align-items: center;
border: 2px solid purple;
}
</style>
<div id="vertical-center">
<div class="flex">
<div class="child">I am flex</div>
</div>
</div>

参考文档