深入理解css中position属性及z-index属性
深入理解 css 中 position 属性及 z-index 属性
在网页设计中,position 属性的使用是非常重要的。有时如果不能认识清楚这个属性,将会给我们带来很多意想不到的困难。
position 属性共有四种不同的定位方法,分别是 static、fixed、relative、absolute,sticky。最后将会介绍和 position 属性密切相关的 z-index 属性。
第一部分:position: static
static 定位是 HTML 元素的默认值,即没有定位,元素出现在正常的流中,因此,这种定位就不会收到 top,bottom,left,right 的影响。
如 html 代码如下:
1 2 3 | <div class = "wrap" > <div class = "content" ></div> </div> |
css 代码如下:
1 2 | .wrap{width: 300px;height: 300px; background: red;} .content{position: static ; top:100px; width: 100px;height: 100px; background: blue;} |
效果图如下:
我们发现,虽然设置了 static 以及 top,但是元素仍然出现在正常的流中。
第二部分:fixed 定位
fixed 定位是指元素的位置相对于浏览器窗口是固定位置,即使窗口是滚动的它也不会滚动,且 fixed 定位使元素的位置与文档流无关,因此不占据空间,且它会和其他元素发生重叠。
html 代码如下:
1 | <div class = "content" >我是使用fix来定位的!!!所以我相对于浏览器窗口,一直不动。</div> |
css 代码如下:
1 2 | body{height:1500px; background: green; font-size: 30px; color:white;} .content{ position: fixed; right:0;bottom: 0; width: 300px;height: 300px; background: blue;} |
效果图如下:
即右下角的 div 永远不会动,就像经常弹出来的广告!!!
值得注意的是:fixed 定位在 IE7 和 IE8 下需要描述!DOCTYPE 才能支持。
第三部分:relative 定位
相对定位元素的定位是相对它自己的正常位置的定位。
关键:如何理解其自身的坐标呢?
让我们看这样一个例子,hmtl 如下:
1 2 3 | <h2>这是位于正常位置的标题</h2> <h2 class = "pos_bottom" >这个标题相对于其正常位置向下移动</h2> <h2 class = "pos_right" >这个标题相对于其正常位置向右移动</h2> |
css 代码如下:
1 2 | .pos_bottom{position:relative; bottom:-20px;} .pos_right{position:relative;left:50px;} |
效果图如下:
即 bottom:-20px;;向下移动。 left:50px; 向右移动。
即可以理解为:移动后是移动前的负的位置。
比如上例中,移动后是移动前负的 bottom:-20px; 即移动后是移动前 bottom:20px; 也就是说,移动后是移动前的向下 20px;
又如:left:50px; 移动后是移动前左边的 -50px; 那么也就是说移动后是移动前的右边的 50px。
即:移动后对于移动前:如果值为负数,则直接换成整数;如果值为整数,则直接改变相对方向。
弄清楚了 relative 是如何移动的,下面我们看一看移动之后是否会产生其他的影响。
html 代码如下:
1 2 3 | < h2 >这是一个没有定位的标题</ h2 > < h2 class="pos_top">这个标题是根据其正常位置向上移动</ h2 > < p >< b >注意:</ b > 即使相对定位元素的内容是移动,预留空间的元素仍保存在正常流动。</ p > |
css 代码如下:
1 | h2.pos_top{position:relative;top:-35px;} |
效果图如下:
根据之前的说法,top:-35px;值是负数,则直接换成正数,即移动后相对与移动前向上偏移了 35px;我们发现于上,移动后和上面的元素发生了重叠;于下,即使相对元素的内容移动了,但是预留空间的元素仍然保存在正常流动,也就是说相对移动之后,不会对下面的其他元素造成影响。
注意:top:20px;是指子元素的 margin 外侧和包裹元素的 border 内侧之间的距离是 20px。
第四部分:absolute 定位
绝对定位的元素相对于最近的已定位父元素,如果元素没有已定位的父元素,那么它的位置相对于 <html>。
下面举几个例子:
例子 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <! DOCTYPE html> < html lang="en"> < head > < meta charset="UTF-8"> < title >绝对定位</ title > < style > body{background:green;} .parent{ width: 500px;height: 500px;background: #ccc;} .son{ width: 300px;height: 300px;background: #aaa;} span{position: absolute; right: 30px; background: #888;} </ style > </ head > < body > < div class="parent"> < div class="son"> < span >什么?</ span > </ div > </ div > </ body > </ html > |
效果如下:
即我只在 span 中设置了 position:absolute;而在其父元素中都没有,于是它的位置是相对于 html 的。
例 2:
1 | .son{position: relative; width: 100px;height: 100px;background: #aaa; } |
相较于上一个例子,我只修改了 class 为 son 的元素的 css,设置为 position:relative;效果图如下:
于是,我们发现现在 span 的位置是相对于设有 position 属性的 class 为 son 的父元素的。
例 3:
1 | .parent{position: absolute; width: 300px;height: 300px;background: #ccc;} |
这个例子我只是修改了第一个例子中的 css-- 设置了 position:absolute;效果如下:
于是我们发现,现在 span 的定位是相对于具有 position:absolute 的属性的 class 为 parent 的父元素。
例 4:
1 | .parent{position:fixed; width: 300px;height: 300px;background: #ccc;} |
相对于例 1,我添加了 fixed 的 position 属性,发现结果和例 3 是一模一样的。
例 5:
1 | .parent{position:static; width: 300px;height: 300px;background: #ccc;} |
相对于例 1,我添加了 static 的 position 属性(即 html 的默认属性),结果和例 1 是一样的。
综上所述,当某个 absolute 定位元素的父元素具有 position:relative/absolute/fixed 时,定位元素都会依据父元素而定位,而父元素没有设置 position 属性或者设置了默认属性,那么定位属性会依据 html 元素来定位。
第五部分:重叠的元素 --z-index 属性
首先声明:z-index 只能在 position 属性值为 relative 或 absolute 或 fixed 的元素上有效。
基本原理是:z-index 的值可以控制定位元素在垂直于显示屏幕方向(z 轴)上的堆叠顺序 (stack order), 值大的元素发生重叠时会在值小的元素上面。
下面我们通过几个例子继续来理解这个属性。
例 1:
即 son1 和 son2 是 parent 的两个子元素,效果图如下:
这是没有使用 z-index,我们发现 son2 在 son1 之上,这是因为 son2 在 html 中排在了 son1 之后,所以后来者将前者覆盖,如果我们颠倒以下两者的顺序,就会发现蓝色 (son1) 在上了。
例 2:
在 son1 中加入 z-index:1;可以发现效果如下:
也就是说 son2 的 index 值是小于 1 的。
如果我们给 son2 也加上 z-index:1; 呢?结果得到黄色 (son2) 就在上面了。(因为一旦 z-index 值相等,情况就和都不设置 index 值一样了)
例 3:
在 son2 中加入 z-index:5; 可以发现效果如下:
即黄色 (son2) 又在上面了,这个很简单,不作过多讨论。
例 4:
在父元素添加 z-index:10;
在 son1 和 son2 添加 z-index:5; 这样理论上父元素就会在上面(黄色覆盖蓝色和黄色);
结果如下:
结果没有变!!!!! 这就说明父元素和子元素不能做 z-index 的比较!!!但真的是这样吗?看下一个例子:
例 5:
把两个子元素的 z-index 值同时设置为 -5;父元素不设置 z-index 属性。结果如下:
成功!!说明在父元素和子元素之间还是可以作比较的!!!只是需要我们把子元素的 z-index 值设为负数。
例 6:
我们在例 5 的基础上再给父元素添加一个 z-index:10,讲道理 ~ 应该也可以得到和例 5 相同的结果吧!!
然而.... 看来我们不能设置父元素的 z-index 值,否则就不能出现我们想要的效果。下面再看一个有趣的例子!
例 7:
我们根据例 6 的经验不设置父元素的值,现在设置 son1(蓝色) 的 z-index 为 5,son2 的 z-index 为 -5,看下面的结果:
即 son1 在最上面,父元素在中间,son2 在最下面。
对于 z-index 的探索就这样结束了吗??当然没有,看下面几个更为有趣的例子吧。
例 8:
代码如下:
效果如下:
虽然 parent1 和 parent2 分别是 son1 和 son2 的父元素,按照我们之前的理解,父元素是不可添加 z-index 值的,否则会导致错误。但是这里 parent1 和 parent2 相对于 body 又是子元素,他俩是同级的,所以就可以进行比较了。且此时 parent1 的子元素 son1(蓝色)在上。
例 9:
如果我们在例 7 的基础上,把 parent2 的 z-index 值设为 20,就会发现如下效果:
即 parent2 在上的同时 son2 也会同时在上。这也就是所谓的“拼爹”了!!
例 10. 同样在例 7 的基础上,我们不设置 parent1 和 parent2 和 son2 的 index 值,而只设置 son1 的 z-index 值为 10,效果如下:
即原本在下面的蓝色 son1 被提上来了,而没有把父元素(parent1)提上了,诶,不孝顺啊!!
例 11. 显然,在例 10 的基础上,如果我们把 son2 的 index 值设置的比 son1 的大,如 20,那么 son2 就会覆盖 son1 了,并且都在两个父元素只上了!!
效果如下图:
例 12. 当然,如果我们把两个 son 的 z-index 都设置位负数如 -5,那么两者就都会被父元素所覆盖:
第六部分:脱离文档流导致的问题
我们知道如果使用 position:absolute 和 position:fixed 都会导致元素脱离文档流,由此就会产生相应的问题。举例如下:
<!DOCTYPE html> <html> <head> <title>position</title> <style> .div1{ background-color: red; padding:20px; } .div2{ width: 200px; height: 200px; background-color: blue; } </style> </head> <body> <div class="div1"> <div class="div2"></div> </div> </body> </html>
这时效果如下:
即子元素将父元素撑了起来。
但是一旦子元素的 position 为 fixed 或者是 absolute,那么它就会脱离文档流,这样的后果是父元素无法被撑开,如下所示:
<!DOCTYPE html> <html> <head> <title>position</title> <style> .div1{ background-color: red; padding:20px; position: relative; } .div2{ position: absolute; // 添加 position:absolute 使其脱离文档流 width: 200px; height: 200px; background-color: blue; } </style> </head> <body> <div class="div1"> <div class="div2"></div> </div> </body> </html>
最终效果如下所示:
解决方法 1:在 js 中设置父元素高度等于子元素的高度。
解决方法 2:给父元素强行设置高度。(对于宽度导致的类似问题就强行设置宽度)
第七部分:position: sticky;
这一部分内容是 2017-3-13 补充的, 之前没有了解到这个属性,几天才知道这个属性就是我经常使用 js 使用的方法,就是在一个内容中,我们可以固定一个部分,然后到了另一个内容,又会固定另外一个部分。
同样也可以设置 top 值, 这个值是 border 上边缘和包裹元素的下边缘之间的距离,但是一旦滚动起来,就是和浏览器顶部的距离了,话不多说,直接上 demo,一看便懂。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>alink</title> <style> body { margin: 0; padding: 0; } .wrap {border: 20px solid blue;} .header { position: sticky; top: 20px; border: 20px solid red; margin-top: 20px; } </style> </head> <body> <div class="wrap"> <div class="header"> 这是头部 </div> <div class="content"> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> 这是内容部分<br> </div> </div> <div class="wrap"> <div class="header"> 这是另一个头部 </div> <div class="content"> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> 这是另一个内容<br> </div> </div> </body> </html>
第八部分:总结
这一部分知识还是非常有意思的,希望大家可以继续探索,当然如果通过这篇博文给予大家一点点的帮助那就再好不过了!