# CSS3教程 - 9 定位2
继续讲解定位...
# 9.7 水平布局
我们之前在盒子模型的章节讲过,水平方向的布局存在如下等式:
margin-left
+ border-left
+ padding-left
+ width
+ padding-right
+ border-right
+ margin-right
= 其父元素的宽度
当使用绝对定位时,需要添加 left
和 right
两个值(此时规则和之前一样,只是多添加了两个值)
left
+ margin-left
+ border-left
+ padding-left
+ width
+ padding-right
+ border-right
+ margin-right
+ right
= 其包含块内容区的宽度
当发生过度约束时(就是等式不成立的时候):
- 如果 9 个值中没有
auto
,则自动调整right
值以使等式成立(之前 7 个值的时候调整的是margin-right
) - 如果 9 个值中有
auto
,则自动调整auto
的值以使等式成立
可设置auto
的值:margin-left
、margin-right
、width
、left
、right
。
因为left
和right
的值默认是auto
,所以如果没有设置left
和right
,当等式不满足时,则会自动调整这两个值。
所以一个元素开启了绝对定位,又想让它在父元素中居中,则需要设置为如下:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style/reset.css" />
<style>
.box1 {
width: 300px;
height: 300px;
background-color: lightskyblue;
position: relative; /* 父相对定位 */
}
.box2 {
width: 100px;
height: 100px;
background-color: lightpink;
position: absolute; /* 子绝对定位 */
margin-left: auto;
margin-right: auto;
left: 0px;
right: 0px;
}
</style>
</head>
<body>
<div class="box1">
<div class="box2"></div>
</div>
</body>
</html>
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
- 首先父元素开启相对定位,子元素开启绝对定位;
- 子元素设置
margin-left
和margin-right
为auto
,left
和right
为0px
;这样左右的距离会被margin-left
和margin-right
平分,从而让元素居中。
显示效果:
设置 margin-left
和 margin-right
为 0px
,left
和 right
为 auto
可以让元素居中吗?
不可以,此时等式不成立,会自动调整 right
使等式成立,左移此时 box1 居左。
# 9.8 垂直布局
元素开启决定定位后,垂直方向布局的等式的也必须要满足:
top + margin-top + border-top + padding-top + height + padding-bottom + border-bottom + margin-bottom + top = 其包含块内容区的高度
通过这个等式,可以让元组在父元素中垂直居中。
举个栗子:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style/reset.css" />
<style>
.box1 {
width: 300px;
height: 300px;
background-color: lightskyblue;
position: relative; /* 父相对定位 */
}
.box2 {
width: 100px;
height: 100px;
background-color: lightpink;
position: absolute; /* 子绝对定位 */
margin-top: auto;
margin-bottom: auto;
top: 0;
bottom: 0;
}
</style>
</head>
<body>
<div class="box1">
<div class="box2"></div>
</div>
</body>
</html>
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
- 首先父元素开启相对定位,子元素开启绝对定位;
- 子元素设置
margin-top
和margin-bottom
为auto
,top
和bottom
为0px
;这样上下的距离会被margin-top
和margin-bottom
平分,从而让元素居中。
显示如下:
# 9.9 水平垂直居中
有了上面水平和垂直居中的方式,那么就可以很容易实现子元素在父元素中水平和垂直居中了。
代码如下:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style/reset.css" />
<style>
.box1 {
width: 300px;
height: 300px;
background-color: lightskyblue;
position: relative; /* 父相对定位 */
}
.box2 {
width: 100px;
height: 100px;
background-color: lightpink;
position: absolute; /* 子绝对定位 */
margin: auto;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
</style>
</head>
<body>
<div class="box1">
<div class="box2"></div>
</div>
</body>
</html>
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
- 首先父元素开启相对定位,子元素开启绝对定位;
- 设置
margin
为 auto, 则margin-left
、margin-right
、margin-top
、margin-bottom
都为 auto,此时 left、right、top、bottom 为0,则距离在水平和垂直方向上被 margin 平分,从而达到水平和垂直方向上的居中。
显示如下:
# 9.10 元素层级
前面讲到,元素开启定位后,会调高元素显示的层级,也就会显示在别的元素上面。
如果元素都开启定位后,那谁在上面,谁在下面呢?
先看一个例子:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style/reset.css" />
<style>
.box1 {
width: 100px;
height: 100px;
background-color: lightskyblue;
position: absolute; /* 绝对定位 */
}
.box2 {
width: 100px;
height: 100px;
background-color: lightpink;
position: absolute; /* 绝对定位 */
top: 50px;
left: 50px;
}
.box3 {
width: 100px;
height: 100px;
background-color: lightgreen;
position: absolute; /* 绝对定位 */
top: 100px;
left: 100px;
}
</style>
</head>
<body>
<div class="box1">1</div>
<div class="box2">2</div>
<div class="box3">3</div>
</body>
</html>
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
上面三个元素都开启了绝对定位,显示层级如何呢?
显示如下:
可以看到 box3 在最上面,box1在最下面。也就是说在没调整层级的时候,它们的层级是一样的,但是HTML 文档中后面的元素会覆盖前面的元素,因为 box3 在后面,所以 box3 显示在最上面。
元素开启定位后(非static),可以通过 z-index
来调整元素的层级。一个元素的位置其实是有三个维度 x/y/z
,Z轴是垂直于屏幕指向屏幕外的。
在上面代码的基础上,设置 box2 的层级:
.box2 {
width: 100px;
height: 100px;
background-color: lightpink;
position: absolute; /* 绝对定位 */
top: 50px;
left: 50px;
z-index: 1; /* 设置层级 */
}
2
3
4
5
6
7
8
9
10
如果元素未指定 z-index
,则默认是 z-index: auto
,其顺序依赖文档结构,可以理解为 z-index
为 0
。上面设置 box2 的 z-index
为 1,所以显示在 box1 和 box3 的上面。
显示如下:
可以通过z-index
属性来指定元素的层级, z-index
的合理范围为 -999 到 9999,建议设置为正值。值越大元素的层级越高,元素的层级越高,越优先显示。层级一样,那么优先显示 HTML 文档结构中后面的元素;另外祖先的元素的层级再高,也不会盖住后代元素。
# 9.11 轮播图练习
下面来进行一个布局和定位联系,制作一个轮播图。
因为当前没有学习 JS,所以轮播图还不能动,只是简单的完成布局。
最终效果:
# 1 编写框架
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style/reset.css" />
<style>
</style>
</head>
<body>
<ul class="image-wrapper">
<li><a href="javascript:void(0);"><img src="./image/html5.webp" /></a></li>
<li><a href="javascript:void(0);"><img src="./image/css3.webp" /></a></li>
<li><a href="javascript:void(0);"><img src="./image/javascript.webp" /></a></li>
<!-- 圆点 -->
<div class="point-wrapper">
<a href="javascript:void(0);"></a>
<a href="javascript:void(0);"></a>
<a href="javascript:void(0);"></a>
</div>
</ul>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
- 因为是轮播图,所以是多张图片,这里使用
<ul>
和<li>
,因为轮播图一般是可以点击的,所以使用<a>
标签包裹。 - 创建一个圆点列表,用于圆点的展示
现在没有样式,显示效果没眼看,继续...
# 2 编写CSS样式
- 首先
<ul>
宽高根据图片的宽高来调整,我这里图片宽度是400,高度240,所以设置<ul>
的宽高; - 多张图片是层叠在一起的,所以针对
<li>
开启绝对定位,<ul>
开启相对定位; - 这里让轮播图居中,所以设置
<ul>
的margin-left
和margin-right
为auto
;
所以添加样式如下:
.image-wrapper {
width: 400px;
height: 240px;
position: relative;
margin-top: 20px;
margin-left: auto;
margin-right: auto;
}
.image-wrapper li {
position: absolute;
}
2
3
4
5
6
7
8
9
10
11
12
13
显示如下:
可以看到现在显示的是最后一张图,因为三个 <li>
的层级是一样的,我们可以通过调整 <li>
的层级来切换图片的显示,这里没有 JS,所以通过 CSS 来选中图片,调整层级:
.image-wrapper li:nth-child(2) { /* 让第二张图片显示 */
z-index: 1;
}
2
3
显示如下:
下面来调整圆点指示器:
- 圆点指示器是在图片上面的,所以让包裹圆点的 div 进行绝对布局,并使用 left 和 bottom 控制其位置;
- 各个圆点还没有设置大小,所以没法显示,但是
<a>
是行内元素,无法设置宽高,所以需要将其设置为块元素,这样可以调整宽高,但是设置为块元素多个<a>
就会竖向排列,所以设置<a>
向左浮动,横向排列;因为元素浮动后,行内元素会变成块元素,所以就不用通过display:block
来设置<a>
为块元素了。 - 为了容易看见,我们先将
<a>
设置为红色背景; - 每个点有间隔,设置一下 margin;
所以添加样式如下:
.point-wrapper {
position: absolute; /* 设置为绝对定位 */
bottom: 15px;
left: 20px;
z-index: 100; /* 提高层级,显示在图片之上 */
}
.point-wrapper a {
float: left; /* 浮动 */
width: 12px;
height: 12px;
margin-left: 5px; /* 设置每个圆点间距 */
background-color: red;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
显示如下:
下面继续设置圆点的样式:
- 设置圆点为圆角 50%;
- 设置圆点为白色,有透明度的;
- 设置圆点鼠标悬浮后,添加白色边框;
所以继续添加样式:
.point-wrapper a {
float: left; /* 浮动 */
width: 12px;
height: 12px;
margin-left: 5px; /* 设置每个圆点间距 */
border-radius: 50%; /* 圆角50%,圆形 */
background-color: rgba(255, 255, 255, 0.6); /* 背景0.6透明度的白色 */
}
.point-wrapper a:hover { /* 鼠标悬浮样式 */
border: 2px solid rgba(255, 255, 255, 1); /* 添加一个白色边框 */
}
2
3
4
5
6
7
8
9
10
11
12
显示如下:
出现了一个问题,鼠标悬浮后因为添加了边框,导致圆点元素尺寸变大,导致圆点大小不一样。
可以先这样处理:
- 鼠标不悬浮的,也添加边框,透明的边框;
- 然后让背景颜色不要蔓延到内边距和边框;(这个后面将背景的时候再讲)
添加如下样式
.point-wrapper a {
float: left;
width: 12px;
height: 12px;
margin-left: 5px;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.6);
background-clip: content-box; /* 将背景颜色设置到内容区,不蔓延到边框和内边距 */
border: 2px solid transparent; /* 添加透明边框 */
}
2
3
4
5
6
7
8
9
10
显示效果:
# 9.12 下拉菜单练习
我们经常看到将鼠标悬浮到导航栏上的菜单,可以显示一个下拉菜单,下面就来实现这样的功能。
最终效果如下:
在实现上面的效果之前,先介绍一下如何使用纯 CSS 实现上面的小三角。
先看一下下面的代码:
<!DOCTYPE html>
<html>
<head>
<style>
.box1 {
width: 50px;
height: 50px;
border: 20px solid red;
border-color: red green blue yellow;
}
</style>
</head>
<body>
<div class="box1"></div>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- 代码很简单,就是给 div 设置了一个边框,每边的边框的颜色是不一样的。
显示如下:
可以看到各个边的边框是斜着的。如果将 div 的宽度和高度设置为 0 呢?
显示如下:
所以要想实现一个向上的小三角,现在只需要将上边框去掉,左右两个边框设置为透明即可(左右边框必须保留,不然没有小三角效果):
.box1 {
width: 0px;
height: 0px;
border: 20px solid transparent; /* 边框透明 */
border-top: none; /* 去掉上边框 */
border-bottom-color: blue; /* 设置下边框颜色 */
}
2
3
4
5
6
7
显示如下:
如果要实现向下、左右的三角也是同样的道理,当然你如果通过图片来实现也是可以的。
下面来实现下拉菜单。
首先先实现导航条:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style/reset.css" />
<style>
.nav {
width: 1000px;
height: 48px;
background-color: #e8e7e3;
margin: 50px auto; /* 左右margin auto,设置导航条居中,盒子模型章节讲过 */
}
/* li整体布局 */
.nav li {
float: left; /* 浮动li元素 */
line-height: 48px; /* 设置行高,这样文字就垂直居中了 */
}
.nav a {
display: block;
font-size: 18px;
color: #777777;
text-decoration: none;
padding: 0 38px; /* 让文字有一定的距离 */
}
/* 超链接悬浮效果 */
.nav li a:hover {
background-color: #3f3f3f;
color: #e8e7e3;
}
</style>
</head>
<body>
<ul class="nav">
<li><a href="#">前端</a></li>
<li><a href="#">后端</a></li>
<li><a href="#">数据库</a></li>
</ul>
</body>
</html>
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
- 导航条和之前学习浮动的时候,效果是一样的,这里进行了简化。
显示如下:
因为要显示下拉菜单,菜单是根据导航按钮来的,所以将菜单添加到导航按钮的 <a>
标签中:
<li>
<a class="database" href="#">
数据库
<div class="database-menu">
<div>MySQL</div>
<div>Oracle</div>
<div>SQL Server</div>
</div>
</a>
</li>
2
3
4
5
6
7
8
9
10
- 为了方便后面的操作,这里给
<a>
添加了一个class
。
添加完成,显示如下:
下面开始设置样式,下拉菜单不能影响别的元素的布局,所以要将下拉菜单脱离文档流,直接将下来菜单使用绝对定位,父元素 <a>
使用相对定位,也就是 父相子绝
,并设置下拉列表的样式。
.database {
position: relative; /* 父元素相对定位 */
}
.database-menu {
display: block;
width: 130px;
font-size: 14px;
line-height: 30px;
color: #777777;
background-color: white;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
position: absolute; /* 子元素绝对定位 */
left: 0;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
显示如下:
差不多了,设置一下下拉列表中每个选项的样式,和鼠标悬浮的样式:
.database-menu div {
padding: 10px;
}
.database-menu div:hover {
background-color: #CCCCCC;
}
2
3
4
5
6
显示如下:
下面添加一下小三角,通过 <a>
标签的伪元素添加就可以了:
.database::after {
display: block;
content: '';
width: 0;
height: 0;
border: 10px solid transparent;
border-top: none;
border-bottom-color: white;
position: absolute;
margin-left: auto; /* 为了让三角居中 */
margin-right: auto;
left: 0;
right: 0;
bottom: 0;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
显示如下:
现在显示的样式已经差不多了,现在调整一下显示,鼠标不悬浮的时候隐藏,鼠标悬浮的时候显示,将上面的 display
设置为 none;
,然后添加如下样式:
.database:hover .database-menu{
display: block;
}
.database:hover::after {
display: block;
}
2
3
4
5
6
完整代码如下:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style/reset.css" />
<style>
.nav {
width: 1000px;
height: 48px;
background-color: #e8e7e3;
margin: 50px auto; /* 左右margin auto,设置导航条居中,盒子模型章节讲过 */
}
/* li整体布局 */
.nav li {
float: left; /* 浮动li元素 */
line-height: 48px; /* 设置行高,这样文字就垂直居中了 */
}
.nav a {
display: block;
font-size: 18px;
color: #777777;
text-decoration: none;
padding: 0 38px; /* 让文字有一定的距离 */
}
/* 超链接悬浮效果 */
.nav li a:hover {
background-color: #3f3f3f;
color: #e8e7e3;
}
.database {
position: relative;
}
.database-menu {
display: none;
width: 130px;
font-size: 14px;
line-height: 30px;
color: #777777;
background-color: white;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
position: absolute;
left: 0;
}
.database-menu div {
padding: 10px;
}
.database-menu div:hover {
background-color: #CCCCCC;
}
.database::after {
display: none;
content: '';
width: 0;
height: 0;
border: 10px solid transparent;
border-top: none;
border-bottom-color: white;
position: absolute;
margin-left: auto; /* 为了让三角居中 */
margin-right: auto;
left: 0;
right: 0;
bottom: 0;
}
.database:hover .database-menu{
display: block;
}
.database:hover::after {
display: block;
}
</style>
</head>
<body>
<ul class="nav">
<li><a href="#">前端</a></li>
<li><a href="#">后端</a></li>
<li>
<a class="database" href="#">
数据库
<div class="database-menu">
<div>MySQL</div>
<div>Oracle</div>
<div>SQL Server</div>
</div>
</a>
</li>
</ul>
</body>
</html>
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# 9.13 思考
浮动可以布局,定位也可以布局,那什么时候使用浮动布局,什么时候使用定位?
一般在页面上进行大的布局的时候,例如整个页面的结构搭建,使用浮动来布局,当然,现在浮动使用的越来越少了,后面会讲到弹性盒布局。在小区域的模块布局、元素需要叠在一起,可以使用定位来调整。