1. 为什么使用定位?
我们先来看一个效果,同时思考一下用标准流或浮动能否实现类似的效果?
- 小黄色块在图片上移动,吸引用户的眼球
- 当我们滚动窗口的时候,盒子是固定屏幕某个位置的
要实现以上效果,标准流或浮动都无法快速实现,所以,我们脑海应该有三种布局机制的上下顺序:
标准流在最底层 (海底) ------- 浮动的盒子在中间层 (海面) ------- 定位的盒子在最上层(天空)
2. 定位详解
定位也是用来布局的,它有两部分组成:定位模式 + 边偏移
边偏移
简单说,我们定位的盒子,是通过边偏移来移动位置的。
在 CSS 中,通过 top、bottom、left 和 right 属性定义元素的边偏移:(方位名词)
| 边偏移属性 | 示例 | 描述 |
|---|---|---|
top | top: 80px | 顶端偏移量,定义元素相对于其父元素上边线的距离。往下是正,往上是负。 |
bottom | bottom: 80px | 底部偏移量,定义元素相对于其父元素下边线的距离。往上是正,往下是负。 |
left | left: 80px | 左侧偏移量,定义元素相对于其父元素左边线的距离。往右是正,往左是负。 |
right | right: 80px | 右侧偏移量,定义元素相对于其父元素右边线的距离。往左是正,往右是负。 |
定位的盒子有了边偏移才有价值, 一般情况下,凡是有定位地方必定有边偏移。
定位模式(position)
在 CSS 中,通过 position 属性定义元素的定位模式,语法如下:
选择器 { position: 属性值; }
静态定位是css中的默认定位方式,也就是没有定位。在此定位方式中设置:top,bottom,left,right,z-index 这些属性都是无效的。
定位模式是有不同分类的,在不同情况下,我们用到不同的定位模式。
| 值 | 语义 |
|---|---|
relative | 相对定位 |
absolute | 绝对定位 |
fixed | 固定定位 |
① 相对定位(relative)
相对定位是元素相对于它原来在标准流中的位置来说的(自恋型)。
- 相对于自己原来在标准流中位置来移动的。
- 原来在标准流的区域继续占有,后面的盒子仍然以标准流的方式对待它。
② 绝对定位(absolute)
绝对定位是元素以带有定位的父级元素来移动位置 (拼爹型)。
- 不保留原来的位置,完全脱标,完全不占位置。
- 父元素没有定位,则以浏览器可视窗口为准定位。
- 父元素要有定位,则元素依据最近的已经定位的父元素进行定位。
子绝父相
刚才咱们说过,绝对定位,要和带有定位的父级搭配使用,那么父级要用什么定位呢? 定位口诀:子绝父相,子级是绝对定位,父级要用相对定位。
疑问:为什么在布局时,子级元素使用绝对定位时,父级元素就要用相对定位呢? 观察下图,思考一下在布局时,左右两个方向的箭头图片以及父级盒子的定位方式。
分析:
- 方向箭头叠加在其他图片上方,应该使用绝对定位,因为绝对定位完全脱标,完全不占位置。
- 父级盒子应该使用相对定位,因为相对定位不脱标,后续盒子仍然以标准流的方式对待它。如果父级盒子也使用绝对定位,会完全脱标,那么下方的广告盒子会上移,这显然不是我们想要的。
结论:父级要占有位置,子级要任意摆放,这就是子绝父相的由来。
③ 固定定位(fixed)
上面我们说了,绝对定位是元素以带有定位的父级元素来移动位置,如果父元素没有定位,则以浏览器可视窗口为准定位。固定定位是绝对定位的一种特殊形式:固定定位只认浏览器可视窗口 —— 浏览器可视窗口 + 边偏移属性 来设置元素的位置。
- 完全脱标,完全不占位置。
- 跟父元素没有任何关系,只认浏览器,所以不随滚动条滚动。
补充:定位的盒子层级是最高层的,我们只要保证当前的这个盒子是定位的就会压住标准流和浮动盒子。
3. 定位案例
① 哈根达斯
父元素使用相对定位,左上和右下的两个子元素使用绝对定位。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
div {
width: 310px;
height: 190px;
border: 1px solid #ccc;
margin: 50px auto;
padding: 10px;
position: relative; /* 根据子绝父相最合适 */
}
.topIcon {
position: absolute; /* 绝对定位 不占有位置 */
top: 0;
left: 0; /* 孩子加了绝对定位,如果父级没有定位,以浏览器为准 */
}
.bottomIcon {
position: absolute;
right: 0;
bottom: 0;
}
</style>
</head>
<body>
<div>
<img src="media/top_tu.gif" alt="" class="topIcon">
<img src="media/adv.jpg" alt="">
<img src="media/br.gif" height="54" width="60" alt="" class="bottomIcon">
</div>
</body>
</html>
② 仿新浪头部和广告
新浪案例分析:
- 顶部图片固定在浏览器可视窗口顶部,不会随窗口一起滚动;
- 左右两侧的广告图片固定在浏览器可视窗口的左右两侧,不会随窗口一起滚动;
- 注意:底部的内容图片初始显示在顶部图片的下方,如何解决?(使用margin)
步骤 1:顶部图片和底部内容
- 顶部图片固定在浏览器可视窗口顶部,所以我们使用固定定位,在使用固定定位时,如果盒子中没有内容,需要指定宽度,否则没有东西撑开盒子啊。
- 底部内容在顶部图片下方,由于顶部图片是固定定位,不占位置,所以我们设置底部内容图片的顶部
margin,可以让底部盒子初始显示在顶部图片的下方。
.top {
/* 注意:使用固定定位时,如果盒子中没有内容,需要指定宽度,否则没有东西撑开盒子啊 */
width: 100%;
height: 44px;
background: url(media/top.png) no-repeat top center;
position: fixed;
left: 0px;
top: 0px;
}
.box {
width: 1002px;
/* 顶部的 44px 的 margin 可以让 box 显示在顶部图片下方 */
margin: 44px auto;
}
步骤 2:左右两侧广告
左右两侧的广告图片固定在浏览器可视窗口的左右两侧,所以我们使用固定定位。
.ad-left,
.ad-right {
position: fixed;
top: 100px;
}
.ad-left {
left: 0px;
}
.ad-right {
right: 0px;
}
4. width、继承、和三种布局机制的联系
- 标准流中,块级子元素会继承父元素width属性
- 行内(实际上是不能设置宽度)、行内块元素不会继承父元素width属性
- 浮动元素脱离标准流,子元素不继承父元素的width属性
- 同理,绝对定位、固定定位元素脱离标准流,子元素不继承父元素的width属性,所以绝对定位、固定定位要设置宽度
5. 定位扩展
① 绝对定位的盒子居中
绝对定位、固定定位的盒子不能通过设置 margin: auto 设置水平居中,因为这是标准流的做法。
在使用绝对定位时要想实现水平居中,可以按照下图的方法:
left: 50%;:让盒子的左侧移动到父级元素的水平中心位置。margin-left: -100px;:让盒子向左移动自身宽度的一半。
② 堆叠顺序(z-index)
上面我们说了,定位的盒子层级是最高的,定位的盒子会压住标准流和浮动盒子。但是当有多个盒子都是定位的时候,可能会出现盒子重叠的情况,加了定位的盒子,默认后来居上,后面的盒子会压住前面的盒子。
使用 z-index 层叠属性可以调整盒子的堆叠顺序,如下图所示:
z-index 的特性如下:
- 属性值:正整数、负整数或 0,默认值是 0,数值越大,盒子越靠上。
- 如果属性值相同,则按照书写顺序,后来居上。
- 数字后面不能加单位。
z-index只能应用于定位的元素,其他标准流、浮动无效。
③ 定位改变display属性
前面我们讲过,display 是显示模式,可以改变显示模式有以下方式:
- 可以用 inline-block 转换为行内块。
- 可以用浮动 float 默认转换为行内块(类似,并不完全一样,因为浮动是脱标的)。
- 绝对定位和固定定位也和浮动类似,有默认转换的特性,转换为行内块。
所以:
- 一个行内元素,如果加了浮动、绝对定位、固定定位,不用转换,就可以给这个盒子直接设置宽度和高度等。
- 浮动元素、绝对定位、固定定位的元素都不会触发外边距合并的问题,也就是说,我们给盒子添加了浮动或者定位,就不会有垂直外边距合并的问题了,因为垂直外边距合并的问题只在标准流出现。
6. 综合演练 - 淘宝轮播图
父元素使用相对定位,左右箭头以及下面的指示条使用绝对定位,指示条里面的小li使用浮动。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style>
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
}
.slider {
width: 520px;
height: 280px;
background-color: pink;
margin: 50px auto;
position: relative; /* 子绝父相 */
}
.arrow-l,
.arrow-r {
position: absolute; /* 绝对定位 */
width: 24px;
height: 36px;
/*display: block; 使用定位之后a标签不用转换,可以直接设置宽高 */
top: 50%; /* 这个%是按照父级高度的来进行计算 */
margin-top: -18px; /* 上走是负值, 自己高度的一半 */
}
.arrow-l {
left: 0;
}
.arrow-r {
right: 0;
}
.circle {
width: 65px;
height: 13px;
background: rgba(255, 255, 255, 0.3);/* 盒子背景半透明 */
position: absolute;
bottom: 15px; /* 因为是底边对齐 */
left: 50%;
margin-left: -32px;
border-radius: 6px;
}
.circle li { /* 0011 */
width: 9px;
height: 9px;
background-color: #B7B7B7;
float: left;
margin: 2px;
border-radius: 50%; /* 圆角的做法 */
}
.circle .current { /* 注意权重问题,优先级 0020 */
background-color: #f40;
}
</style>
</head>
<body>
<div class="slider">
<img src="media/taobao.jpg" alt="">
<a href="#" class="arrow-l"><img src="media/left.png" ></a>
<a href="#" class="arrow-r"><img src="media/right.png" ></a>
<ul class="circle">
<li class="current">
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
</body>
</html>
7. 定位小结
| 定位模式 | 是否脱标占有位置 | 移动位置基准 | 模式转换(行内块) | 是否可以使用边偏移 | 使用情况 |
|---|---|---|---|---|---|
| 相对定位relative | 不脱标,占有位置 | 相对自身位置移动 | 不能 | 可以 | 基本单独使用 |
| 绝对定位absolute | 完全脱标,不占有位置 | 相对于定位父级移动位置 | 能 | 可以 | 要和定位父级元素搭配使用 |
| 固定定位fixed | 完全脱标,不占有位置 | 相对于浏览器移动位置 | 能 | 可以 | 单独使用,不需要父级 |
8. 网页布局总结
一个完整的网页,有标准流、浮动、定位一起完成布局的,每个都有自己的专门用法。
- 标准流可以让盒子上下排列或者左右排列的。
- 浮动可以让多个块级元素一行显示或者左右对齐盒子,浮动的盒子就是按照顺序左右排列 。
- 定位最大的特点是有层叠的概念,就是可以让多个盒子前后叠压来显示,但是每个盒子需要有 z-index 数值。