学习建议
定位、浮动是 CSS 核心知识点,必须熟练掌握。
1.文档流的概念指什么?有哪种方式可以让元素脱离文档流?
- 文档流指的是浏览器在页面放置HTML元素所用的的方法。
- 首先考虑块元素,块元素从上向下流,各个块元素之间有一个换行,默认的,每个块元素会占据页面的整个宽度。
- 然后内联元素在块元素内部从左上方流向右下方。如果需要多行,浏览器会自动换行,在垂直方向上扩展外围块元素,来包含这些内联元素。
- 使用浮动
float
、绝对定位position:absolute
和固定定位position:fixed
可以让元素脱离文档流。
2.有几种定位方式,分别是如何实现定位的,使用场景如何?
通过使用position属性,可以选择4种不同类型的定位,其值如下(来源自W3C):
值 | 描述 |
---|---|
inherit | 规定应该从父元素继承 position 属性的值。 |
static | 默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)。 |
relative | 生成相对定位的元素,相对于其正常位置进行定位。因此,"left:20" 会向元素的 LEFT 位置添加 20 像素。 |
absolute | 生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位。元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。 |
fixed | 生成绝对定位的元素,相对于浏览器窗口进行定位。元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。 |
通过W3C的描述大致了解了position属性各个值的含义,接下来通过一个个的demo我们来分析各个值。
- static
默认值static,没有定位。我们写一个例子来看看,接下里的demo都会以这个例子为参考。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>demo1</title>
<style type="text/css">
.ct{
width: 300px;
border: 1px solid black;
}
.ct p{
background: #EEEEEE;
}
</style>
</head>
<body>
<div class="ct">
<p>1.饥人谷·最有爱的前端社区</p>
<p>2.这里的教学最人性</p>
<p>3.这里的导师帮帮哒</p>
<p>4.这里的服务最周到</p>
<p>5.这里的课程最实用</p>
</div>
</body>
</html>
这就是position属性默认状态下的页面,文档流里的元素都处在正常的位置。
- relative:
相对定位relative,我们拿上一个默认static页面列子作为参考:
我们给第二个<p>
加上position:relative并设置left和top值,看看有什么变化:
.ct p:nth-child(2){
position: relative;
top: 20px;
left: 20px;
}
从上图我们看到:
1.第二个p元素的位置发生了变化,相对它自身向下和向右移动了20px;
2.第二个p元素挡住了与它有重叠部分其他元素的内容。
3.其他元素的位置没有发生变化。
所以使用相对定位时,如果设置了移动属性,那么会导致元素相对自身位置发生变化,而覆盖掉其他的元素框。但是在文档流中,它仍然占据着原来的位置,所以其他元素的位置不会发生变化。
除外,使用相对定位的另外一个重要的作用就是产生一个新的定位上下文(在CSS规范中叫做包含块),那么什么是定位上下文呢,在本文的第三个回答中有详细解释。
- absolute
绝对定位absolute,我们还是用默认static页面的列子作为参考
我们对第三个<p>
使用position:absolute,并且为了弄清楚absolute定位的参考对象,我们对<p>
的父元素<div>
做不同的设置;
div不设置定位元素:
.ct{
width: 300px;
border: 1px solid black;
}
.ct p{
background: #EEEEEE;
}
.ct P:nth-child(3){
position: absolute;
right: 20px;
background: red;
}
div设置定位元素:
.ct{
position: relative;
/*position: absolute;*/
/*position: fixed;*/
width: 300px;
border: 1px solid black;
}
.ct p{
background: #EEEEEE;
}
.ct P:nth-child(3){
position: absolute;
right: 20px;
background: red;
}
无论div设置成absolute、relative和fixed的哪一种,其结果都一样:
从上面的图来看:
1.第三个p元素脱离了文档流,其他的几个p元素忽略了第三个p元素,重新排列了,且父元素的高度缩小,。
2.通过背景色我们看到,第三个p元素的宽度收缩了,与其内容文字的宽度相等。
3.第三个P元素遮挡住了与它有重叠部分元素的内容。
4.第三个P元素的位置发生了变化,在div没有设置定位元素时,它跳出了div相对于整个页面定位,而div设置了定位元素时,它相对于div定位。
总结一下就是生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位(也可以说是根据最近的定位上下文来定位)。元素会具有收缩性,如果没有设置宽度,元素会根据内容自动调整宽度(也就是说absolute具有自适应宽度的特性,在下面的float属性会提到)。元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。绝对定位使元素脱离文档流,因此不占据空间。
-
fixed
最后还是用默认static的列子做对比,
我们给第四个p元素设置position:fixed看看:
.ct{
position: relative;
/*position: absolute;*/
/*position: fixed;*/
width: 300px;
border: 1px solid black;
}
.ct p{
background: #EEEEEE;
}
.ct P:nth-child(4){
position: fixed;
top: 200px;
left: 20px;
background: red;
}
fixed其实特性跟absolute都一样,唯一的区别在于定位不一样,fixed永远是根据浏览器窗口来定位,无论其他元素怎么设置,都影响不了它。
3.absolute, relative, fixed偏移的参考点分别是什么?
absolute, relative, fixed偏移的参考点实际就是他们的定义上下文。
定义上下文,CSS规范叫它“包含块”,所以我们先学习一下定位元素包含块(参考CSS权威指南):
- "根元素"的包含块(也称为初始包含块)由用户代理建立。在HTML中,根元素就是HTML元素,不过有些浏览器会使用body元素,不过有些浏览器会使用body作为根元素,在大多浏览器中,初始包含块是一个视窗大小的矩形。
- 对于一个非根元素,如果其position值是relative或static,包含块则由最近的快级框、表单元素或行内组先框的内容边界构成。
- 对于一个非根元素,如果其position值是absolute,包含块设置为最近的position值不是static的祖先元素(可以是任何类型)。这个过程如下:
- 如果这几个祖先是块级元素,包含块则设置为该元素的内边距边界,换句话说,就是由边框界定的区域。
- 如果这个祖先是行内元素,包含块则设置为该祖先元素的内容边界。在从左向右读的语言中,包含块的上边界和左边界是该祖先元素中的第一个框内容区的上边界和左边界,包含块的下边界和右边界是最后一个框内容区的下边界和右边界。在从右向左度的语言中,包含块的右边界对应于第一个框的右内容边界,包含块的左边界则取自最后一个框的左内容边界。上下边界也是一样。
- 如果没有祖先,元素的包含块定义为初始包含块。
好吧,这段理论知识是长了点,但解释的很清楚了。但是光是看文字迷迷糊糊的,来点图文更容易记忆。
- absolute的定位
浏览器会递归查找该元素的所有父元素,如果找到一个设置了position:relative/absolute/fixed的元素,就以该元素为基准定位,如果没找到,就以浏览器边界定位。
上图中的“某一层祖先元素”就是该absolute元素的定位上下文了。
这也就是为什么我们说relative的一个重要功能就是重新定义定位上下文,所以一般情况下,我们会将relative与absolute配套使用,方便我们对absolute元素定位。
- relative的定位
relative元素的定位永远是相对于元素自身位置的,和其他元素没关系,也不会影响其他元素。
- fixed的定位
fixed元素的定位永远是相对于浏览器边界的,和其他元素没有关系。
z-index 有什么作用? 如何使用?
z-index属性设置一个定位元素沿Z轴的位置,Z轴定义为垂直延伸到显示区的轴。如果为正数,则离用户更近,为负数则表示离用户更远。
Z-index仅能在定位元素上奏效
通过demo来看看如果使用:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
div{
width: 100px;
height: 100px;
background: pink;
position: absolute;
z-index: -1;
}
</style>
</head>
<body>
<div></div>
<p>1.饥人谷·最有爱的前端社区</p>
<p>2.这里的教学最人性</p>
<p>3.这里的导师帮帮哒</p>
<p>4.这里的服务最周到</p>
<p>5.这里的课程最实用</p>
</body>
</html>
从上图可以看出,当div设置了定位元素absolute并且z-index为负一时,此时文字在div区域的上面。
我们将z-index改为1看看效果:
div{
width: 100px;
height: 100px;
background: pink;
position: absolute;
z-index: 1;
}
上图我们可以看出,此时div区域已经在文字上面了。
还有一种情况,如果z-index的值相同怎么办?看demo:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
div{
width: 100px;
height: 100px;
background: pink;
position: absolute;
z-index: 1;
}
p{
position: absolute;
z-index: 1;
}
</style>
</head>
<body>
<div></div>
<p>饥人谷·最有爱的前端社区</p>
</body>
</html>
上图看出,p和div的z-index值都是1,但是文字还是div区域的上方。
所以,如果2个元素的z-index的值相同,那么后面的元素会悬浮在前面的元素上面。
5.position:relative和负margin都可以使元素位置发生偏移?二者有什么区别?
- position:relative可以使元素发生偏移,但是在文档流中,它仍然占据着原来的位置,所以其他元素的位置不会发生变化。
- 负margin:通过负margin进行偏移的元素,它会放弃偏移前占据的空间,这样它后面文档流中的其它元素就会“流”过来填充这部分空间,所以其他元素的位置发生了变化。
看demo:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
.ct{
width: 400px;
height: 400px;
border: 1px solid black;
margin-left: 100px;
}
.box{
width: 100px;
height: 100px;
}
.box:nth-child(1) {
background: pink;
}
.box:nth-child(2) {
background: green;
position: relative;
left: -50px;
top: -50px;
}
.box:nth-child(3) {
background: yellow;
}
</style>
</head>
<body>
<div class="ct">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
</div>
</body>
</html>
看上图,我们对第二个box使用relative,使它向左上移动了50px,但是另外2个box的位置没有发生改变。
那么我们对第二个box改为使用负margin呢,看看效果:
.box:nth-child(2) {
background: green;
margin-left: -50px;
margin-top: -50px;
}
可以很明显的看到,除了第二个box自身移动意外,第三个box跟着向上移动了50px。
所以,使用负margin会改变其他元素的位置,而relative不会。
6.如何让一个固定宽高的元素在页面上垂直水平居中?
使用绝对定位position:absolute和负margin可以做到。
看demo:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
.ct{
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: #EEEEEE;
}
.box{
width: 100px;
height: 100px;
background: white;
position: absolute;
top: 50%;
left: 50%;
margin-left: -50px;
margin-top: -50px;
}
</style>
</head>
<body>
<div class="ct">
<div class="box"></div>
</div>
</body>
</html>
分析上面代码:
先使用position:absolute,设置left和top为50%,让box的左上角原点位于页面的中心,再使用负margin使box向左上移动它宽高的一半,这样就能使box在页面中垂直居中了。
7.浮动元素有什么特征?对其他浮动元素、普通元素、文字分别有什么影响?
浮动,float,看了一些资料后发现浮动其实是一个非常能体现出人们对于CSS属性灵活利用和深度开发的特性了。
float被设计出来的初衷是用于文字环绕效果,即对一个图片使用float之后,它周围的文字会环绕着它,就像这样:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
img{
float: left;
}
</style>
</head>
<body>
<div>
<p>
![饥人谷logo](http://upload-images.jianshu.io/upload_images/2419272-41ec5eec530166e4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
1.饥人谷·最有爱的前端社区2. 这里的教学最人性 3.这里的导师帮帮哒 4.这里的服务最周到 5.这里的课程最实用
</p>
</div>
</body>
</html>
后来网页慢慢的发展,我们需要使用排版和布局,而使用table布局将导致代码量大、混乱、不利于SEO,后来发现使用float+div是一种不错的排版解决方法。
所以现在绝大多数情况下使用float就是为了横向排版或者多列布局了。
float的用处说完了,就要说一下它的特性了:
- float具有破坏性;
先看demo:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
div{
border: 1px solid black;
}
</style>
</head>
<body>
<div>
![饥人谷logo](http://upload-images.jianshu.io/upload_images/2419272-41ec5eec530166e4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
</div>
</body>
</html>
这里一个img包裹在一个父元素div里面,我们对img使用float看看效果:
img{
float: left;
}
从上图我们可以看到,作为父元素的div高度无法被撑开。
这就是float的破坏性,它会破坏父元素的原本结构,使得父元素的高度发生坍塌,而造成这一现象的根本原因是:float会使元素脱离文档流。
- float具有自适应性;
还是看一个demo:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
div{
border: 1px solid black;
}
</style>
</head>
<body>
<div>
饥人谷·最有爱的前端社区
</div>
</body>
</html>
我们给这个div使用float试试:
div{
border: 1px solid black;
float: left;
}
如图,在使用float之后,这个div的宽度发生了变化,不再是默认的整个页面宽度,而是把内容的这些文字包裹了,这就是float的自适应性(absolute也有这种特性),块级元素设置了float之后,如果不手动设置宽度,其宽度会根据内容自动调整。
- float可以清除缝隙
按照惯例,看demo:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
div{
border: 1px solid black;
padding: 5px;
}
img{
border: 1px solid red;
}
</style>
</head>
<body>
<div>
[站外图片上传中……(3)]
[站外图片上传中……(4)]
[站外图片上传中……(5)]
</div>
</body>
</html>
上图可以看到3张图片之间是有缝隙的,我们给他们设置float看看:
img{
border: 1px solid red;
float: left;
}
上图可以看到img增加了float属性后,互相之间没有了缝隙,紧紧的贴合了一起。
所以这也是为什么float属性适合用于排版,就是这种特性使得各元素严丝合缝,就好像砌砖头一样。
在这里,我们需要注意的是,使用float之后的元素会变为块元素,对上图中的img审查元素看看:
确实,img的display显示的block。
在这里只列举了一些float布局上的特性,其实关于float的特性其实还有很多,有一些很好的博客可以参考:
float是如何工作的
float深入剖析
根据上面的列子回答另外一个问题;
一个元素设置了浮动,同级的浮动元素会跟随着一起浮动,直到遇到其他浮动元素的边框,就像砌砖头一样。
由于浮动元素会脱离文档流,其他的普通元素会忽视浮动元素,后面的元素会占据浮动元素的文档流空间。
虽然浮动元素会脱离文档流,但是文字是始终能察觉浮动元素的存在, 会围绕着浮动元素,这也是设计浮动元素的初衷。
8.清除浮动指什么? 如何清除浮动?
上一个问答提到,float是具有破坏性的,它会导致父元素的高度发生坍塌,影响其他元素的位置,所以为了避免这种影响, 我们需要使用清除浮动。
清除浮动有下面几个方法:
1.浮动父元素:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
div{
border: 1px solid black;
padding: 5px;
float: left;
}
img{
border: 1px solid red;
float: left;
}
</style>
</head>
<body>
<div>
[站外图片上传中……(6)]
[站外图片上传中……(7)]
[站外图片上传中……(8)]
</div>
</body>
</html>
让父元素也浮动并不是一个很好的方法,可能会造成新的麻烦,要谨慎使用。
2.为父元素添加overflow
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
div{
border: 1px solid black;
padding: 5px;
overflow: auto;
/*overflow: overlay;*/
/*overflow: hidden;*/
/*overflow: scroll;*/
}
img{
border: 1px solid red;
float: left;
}
</style>
</head>
<body>
<div>
[站外图片上传中……(9)]
[站外图片上传中……(10)]
[站外图片上传中……(11)]
</div>
</body>
</html>
使用overflow属性来清除浮动有一点需要注意,不能使用visible值,其他的属性值都行。
3.clear:both
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
.ct{
border: 1px solid black;
padding: 5px;
}
img{
border: 1px solid red;
float: left;
}
.clear{
clear: both;
}
</style>
</head>
<body>
<div class="ct">
[站外图片上传中……(12)]
[站外图片上传中……(13)]
[站外图片上传中……(14)]
<div class="clear"></div>
</div>
</body>
</html>
在需要使用清除浮动元素的下面添加一个div元素并且定义它的样式为“clear:both”,这种方法会增加额外的div标签,可能会造成一些影响。
4.clearfix
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
.clearfix{
border: 1px solid black;
padding: 5px;
}
img{
border: 1px solid red;
float: left;
}
.clearfix:after{
content:"";
display: block;
clear: both;
}
.clearfix{
*zoom:1;/*兼容ie低版本*/
}
</style>
</head>
<body>
<div class="clearfix">
[站外图片上传中……(15)]
[站外图片上传中……(16)]
[站外图片上传中……(17)]
</div>
</body>
</html>
这种方法是目前最受推荐的,使用伪元素在元素后面创建一个元素块,然后利用clear:both来清除浮动。
本文版权归本人和饥人谷所有,转载请注明来源。