CSS 定位(postion、z-index)

CSS 定位

  • CSS有三种基本的定位机制:普通流,浮动,绝对定位(absolute, fixed):
    • 普通流是默认定位方式,在普通流中元素框的位置由元素在html中的位置决定,这也是我们最常见的方式,其中 position: static 与 position: relative 属于普通流的定位方式
    • 浮动定位机制
    • 绝对定位包括 absolute和 fixed
position: static(默认) | relative | absolute | fixed | sticky | inherit
// 应用于所有元素。无继承性
/*
static:
元素框正常生成。块级元素生成一个矩形框,作为文档流的一部分,行内元素则会创建一个或多个行框,置于其父元素中。
元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)

relative:
生成相对定位的元素,相对于元素本身正常位置进行定位。
元素仍保持其未定位前的形状,它原本所占的空间仍保留。
常用于对其自身进行细微调整。
相对定位实际上被看作普通流定位模型的一部分,因为元素的位置相对于它在普通流中的位置

absolute:
生成绝对定位的元素,元素框从文档流完全删除,相对于 static 定位以外的第一个祖先元素(offset parent)进行定位。
元素原先在正常文档流中所占的空间会关闭,就好像该元素原来不存在一样。元素定位后生成一个块级框,而不论原来它在正常流中生成何种类型的框

fixed:
元素框的表现类似于将 position 设置为 absolute,不过其包含块是视窗本身(或者说是浏览器窗口)
常用于需要一直停留在窗口的元素

sticky:
CSS3新属性,兼容性较差,一般用JS实现。表现类似 position: relative 和 position: fixed 的合体,
在目标区域在屏幕中可见时,它的行为就像 position: relative; 
而当页面滚动超出目标区域时,它的表现就像 position: fixed,它会固定在目标位置

inherit:规定应该从父元素继承 position 属性的值。一般不使用
*/


// 三种定位机制使用了4个属性来描述定位元素各边相对于其包含块的偏移。这4个属性被称为偏移属性
top/right/bottom/left = <length> | <percentage> | auto(默认) | inherit
/*
应用于:定位元素(也就是 position 值不是 static 的元素)。无继承性

百分数:对于top和bottom,相对于包含块的 clientHeight;对于right和left,相对于包含块的 clientWidth

这些属性描述了距离包含块最近边的偏移。top描述了定位元素上外边界离其包含块的顶端有多远。如果top为正值,会把定位元素的上外边距边界下移,若为负值,则会把定位元素的上外边距移到其包含块的顶端之上。
类似地,left描述了定位元素的左外边距边界在其包含块左边界右边(正值)或左边(负值)有多远。如果是正值,会把定位元素的外边距边界移到包含块左边界右边,而负值则将其移到包含块左边界左边。
所以,正值会导致向内偏移,使边界朝着包含块的中心移动,而负值会导致向外偏移
偏移定位元素的外边距边界时,带来的影响是元素的所有一切(包含外边距、边框、内边距和内容)都会在定位的过程中移动

注意:
    定位元素的边界是指定位元素 margin 外侧的边界;包含块的包含区域是指包含块的 border 内侧的 padding + content 区域
    如果同时定义了 left 和 right 值,且 width 和 height 有值,那么 left 生效, right 无效,同样,同时定义了 top 和 bottom,top 生效。
*/

绝对定位(absolute)

定义
  • 相对定位可以看作特殊的普通流定位,元素位置是相对于它在普通流中位置发生变化,而绝对定位使元素的位置与文档流无关,也不占据文档流空间,普通流中的元素布局就像绝对定位元素不存在一样
  • 当元素绝对定位时,会从文档流中完全删除。绝对定位的元素的位置是相对于距离最近的非static祖先元素位置决定的。如果元素没有已定位的祖先元素,那么他的位置就相对于初始包含块html来定位,其边界根据偏移属性放置。元素定位后生成一个块级框,而不论原来它在正常流中生成何种类型的框。定位元素不会流入其他元素的内容,反之亦然
  • 因为绝对定位与文档流无关,所以绝对定位的元素可以覆盖页面上的其他元素,可以通过 z-index 属性控制叠放顺序,z-index 越高,元素位置越靠上
  • 注意:如果文档可滚动,绝对定位元素会随着它滚动,因为元素最终会相对于正常流的某一部分定位
宽度
  • 绝对定位宽度是收缩的,如果想撑满父容器,可以设置 width: 100%
  • 注意:当父容器里有 绝对定位 的子元素时,子元素设置 width: 100% 实际上指的是相对于父容器的 padding+content 的宽度。当子元素是非绝对定位的元素时,width: 100% 才是指子元素的 content 等于父元素的 content宽度
特性
  • absolute 和 float都可以触发元素的BFC属性,且都具有包裹性和破坏性,所以对于一些应用场景,这两个属性可以进行替换
  • 包裹性
    • 元素绝对定位后,会为其后代元素建立一个包含块。且若该绝对定位元素不设置宽度,宽度由内容撑开,也就是默认宽度为内容宽度
    • 注意:浮动的包含块会延伸,进而包含所有后代浮动元素,但绝对定位的包含块并不会包含后代的定位元素,只是作为后代定位元素的定位父级
  • 破坏性
    • 元素绝对定位后,会脱离文档流,若父级不设置高度,则父级高度塌陷;若父级为行内元素,无其他内容,则父级宽度也将塌陷
  • 去浮动
    • 元素绝对定位后,元素原来的浮动效果将失效
  • 偏移特性
    • 如果使用top、right、bottom、left这4个偏移特性来描述元素4个边的放置位置,那么元素的高度和宽度将由这些偏移隐含确定,元素将会拉伸
    • 使用偏移属性拉伸的绝对定位元素,其内部元素支持百分比 width/height 值。通常情况下,元素高度百分比要想起作用,需要父级窗口的高度值不是 auto;但是如果容器由绝对定位拉伸形成,百分比高度值也是支持的
display 解析
  • 当元素绝对定位后,元素可以改变display属性,但各浏览器解析不一致
    • IE8+浏览器解析正常
    • firefox和safari浏览器只有切换为display: none;时才会重新渲染,其他值相互切换时无效
    • chrome浏览器切换到display: inline;时渲染无效,其他值相互切换时渲染正常
    • IE7-浏览器将绝对定位的元素全部渲染为inline-block元素,只有切换为display: none;时才会重新渲染,其他值相互切换时无效
      • 解决IE7-浏览器绝对定位元素渲染为inline-block元素的bug很简单,只需要在绝对定位的元素外面套一个空的<div>即可
clip
  • 绝对定位或固定定位元素才可以使用clip属性。绝对定位元素常配合clip属性达到元素隐藏的效果
.hide{
    position: absolute;
    clip: rect(0, 0, 0, 0);
}  
静态位置
  • 当元素绝对定位后,若该元素的格式化属性不发生变化,则该元素处于静态位置
  • 元素的静态位置是指元素在正常流中原本的位置,更确切的讲,顶端的静态位置是从包含块的上边界到假想框的上外边距边界之间的距离。假想框是假设元素position 属性 为static 时元素的第一个框
  • 但对于居中对齐的行内元素(个人:还包括行内块状元素)来说,将元素设置为 absolute 或 fixed 会发生静态位置跳动问题。而 relative 或 static 则不会有此问题。这是因为元素默认的居中对齐是元素的内容中线对应父级块级元素中线,而当元素绝对定位或固定定位之后,定位元素左边界将与其父级块级元素的中线对齐。除了居中对齐,左对齐、右对齐都是利用元素自身的左边界去对齐
    <style type="text/css">
    * {
        padding: 0;
        margin: 0;
    }

    .box1 {
        width: 300px;
        height: 200px;
        margin: 20px;
        text-align: center;
        /*text-align: right;*/
        background-color: lightsalmon;
    }

    span {
        /*display: inline-block;*/
        position: absolute;
        background-color: lightblue;
    } 
    </style>
</head>
<body>
<div class="box1">
    <span>居中行内元素</span>
</div>
</body>
overflow
  • 当overflow在绝对定位元素和其包含块之间时,绝对定位元素不会被父级overflow属性剪裁
  • 比如:可以应用绝对定位元素的overflow属性失效实现按钮外置的效果
    <style type="text/css">
    .box {
        /*position: relative;*/
        width: 200px;
        height: 200px;
        margin: 30px;
        overflow: hidden;
        background-color: pink;
    }

    .close {
        position: absolute;
        margin: -30px 0 0 185px;
        width: 20px;
        line-height: 20px;
        text-align: center;
        border: 2px solid;
        border-radius: 50%;
        cursor: pointer;
    }
    </style>
</head>
<body>
<div class="box">
    <div class="in">测试内容</div>           
    <span class="close">×</span>
</div>
</body>

绝对定位的应用

自适应位置的跟随图标
  • 图标使用不依赖定位父级的absolute和margin属性进行定位,这样,当文本的字符个数改变时,图标的位置可以自适应
    <style type="text/css">
    div {
        width: 500px;
        height: 20px;
        margin: 30px;
        line-height: 20px;
    } 

    i {
        position: absolute;
        width: 28px;
        height: 11px;
        margin: -6px 0 0 2px;
        background: url(http://sandbox.runjs.cn/uploads/rs/26/ddzmgynp/hot.gif);
    }
    </style>
</head>
<body>
<div>改变文字长度不影响<i></i></div>
</body>
视频图片上的小图标提示
  • 一般在视频图片上的边角上都会有“自制”、“最新”、“1080p”等诸如此类的提示。使用不依赖的绝对定位属性,可以让父级元素不设置relative,拓展性更强
    <style type="text/css">
    i {
        position: absolute;
        width: 50px;
        height: 18px;
        padding: 2px;
        text-align: center;
        line-height: 18px;
        font-style: normal;
        color: white;
        background-color: orange;   
    }    

    .box {
        height: 200px;
        width: 200px;
        margin: 50px;
        border: 2px solid gray;
    }

    .in {
        display: inline-block;
        width: 100%;
        height: 100%;
        line-height: 100px;
        background-color: pink;
    }

    .rt {
        margin-left: -54px;
    }

    .lb {
        margin-top: -22px;
    }

    .rb {
        margin-top: -22px;
        margin-left: -54px;
    }
    </style>
</head>
<body>
<div class="box">
    <i class="lt">自制</i>
    <div class="in">测试内容</div><i class="rt">独家</i>
    <i class="lb">1080p</i>
    <span style="display: inline-block; width: 100%;"></span><i class="rb">最新</i>
</div>
</body>
下拉菜单
  • 一般地,下拉菜单作为一个组件需要使用在各种场景中,如果给组件添加 relative属性,则降低了其利用率
    <style type="text/css">
    * {
        padding: 0;
        margin: 0;
    }  

    ul {
        list-style: none;
    }

    input {
        border: none;
    }

    .box {
        width: 250px;
        height: 35px;
        margin: 50px;
        border: 1px solid #ccc;
    }

    .box > .con {
        overflow: hidden;
        margin-bottom: 10px;
    }

    .con > .input {
        width: 215px;
        height: 35px;
    }

    .con > .search {
        float: right;
        width: 35px;
        height: 35px;
        background: url('http://sandbox.runjs.cn/uploads/rs/26/ddzmgynp/search.png') -2px -40px;
    }

    .box > .list {
        display: none;
        /* 这里absolut的作用是什么? 设置绝对定位,完全脱离文本流,也就不会影响到其它元素的布局 */
        position: absolute;
        width: 212px;
        overflow: hidden;
        border: 1px solid #ccc; 
        background-color: #fff;
    }

    .list > .in {
        line-height: 40px;
        text-indent: 1em;
        cursor: pointer;
    }

    .list > .in + .in {
        border-top: 1px solid lightblue;
    }

    .list > .in:hover {
        background-color: #f9f9f9;
    }
    </style>
</head>
<body>
<div class="box">
    <div class="con">
        <input class="input" id="input">
        <a href="#" class="search"></a>
    </div>
    <ul class="list" id="list">
        <li class="in">选项一</li>
        <li class="in">选项二</li>
        <li class="in">选项三</li>
    </ul>
    <div>其它文本内容其它文本内容其它文本内容其它文本内容</div>        
</div>
<script type="text/javascript">
input.onfocus = function(){
    list.style.display = 'block';
}

input.onblur = function(){
    list.style.display = 'none';
}
</script>
</body>
边缘对齐
  • 很多网站都使用了边缘对齐,但好多都是用页面宽度计算出来的,当宽度变化时需要重新计算。而无依赖的绝对定位利用静态位置,无需计算就可将其位置确定,且拓展性好
    <style type="text/css">
    * {
        padding: 0;
        margin: 0;
    }

    ul {
        list-style: none;
    }

    .box {
        width: 300px;
        height: 200px;
        margin: 50px;
        border: 2px solid black;
        background-color: lightgreen;
    }

    .box > .out {
        text-align: right;
    }

    .out > .list {
        /* 未设置绝对定位前,元素右边界与其父级块级元素的右边界线对齐 */
        position: absolute;
        /* 定位元素左边界将与其父级块级元素的右边界线对齐 */
        /* 设置固定定位 osition: fixed; 也可以,但是可能会影响其它元素的布局 */

        display: inline-block;
        margin: 10px 0 0 2px;
    }

    .list > .in {
        text-align: center;
        width: 30px;
        line-height: 30px;
        margin-top: 10px;
        border-radius: 50%;
        background-color: pink;
    }
    </style>
</head>
<body>
<div class="box">
    <div class="out">
        <!-- 对于safari浏览器需要添加空格   来触发右对齐,其他浏览器则不需要-->
        <!--   -->
        <ul class="list">
            <li class="in">一</li>
            <li class="in">二</li>
            <li class="in">三</li>
        </ul>        
    </div>
</div>
</body>
星号
  • 在很多注册或登录页面中,存在用 * 表示的必填项。* 和 * 号对齐,文字和文字对齐。这种情况使用静态位置的绝对定位比较合适
    <style type="text/css">
    * {
        padding: 0;
        margin: 0;
    }

    ul {
        list-style: none;
    }

    .list {
        width: 100px;
        padding-left: 20px;
        margin: 50px;
        border: 2px solid black;
        line-height: 2em;
    }

    .in > i {
        /* 设置绝对定位,完全脱离文档流,<span> 中的文字自然也就左对齐了 */
        position: absolute;

        margin-left: -10px;
        color: red; 
        font-style: normal;
    }
    </style>
</head>
<body>
<ul class="list">
    <li class="in">
        <i>*</i><span>手机号</span>
    </li>
    <li class="in">
        <span>用户名</span>
    </li>
    <li class="in">
        <i>*</i><span>密码</span>
    </li>
</ul>
</body>
偏移属性
  • 当使用偏移属性时,绝对定位元素将相对于包含块进行定位。一般地,我们仅仅使用偏移属性中的两个,且这两个属性不对立。但实际上,对立的偏移属性如left和right可以同时使用,甚至4个偏移属性都可以同时使用,并且可以达到一些意想不到的效果。以下基于绝对定位偏移属性的应用
全屏自适应
  • 实现一个距离屏幕右侧200px的全屏自适应的容器层
    <style type="text/css">
    .box {
        position: absolute;
        top: 0;
        left: 0;
        right: 200px;
        bottom: 0;
        background-color: pink;
    }
    </style>
</head>
<body>
<div class="box"></div>
</body>
左右半区翻图
  • 一些选项卡中存在左右半区的翻图效果,点击左覆盖区切换到上一张图片,点击右覆盖区切换到下一张图片
    <style type="text/css">
    * {
        padding: 0;
        margin: 0;
    }

    ul {
        list-style: none;
    }

    .box {
        position: relative;
        width: 300px;
        height: 200px;
        overflow: hidden;
        margin: 50px;
        border: 2px solid lightgray;
        text-align: center;
        font: 40px/200px '宋体';
        color: white;
    }

    .box > .list{
        position: absolute;
        width: 400%;
        left: 0;
        top: 0;
        bottom: 0;
        transition: left 1s;
    }

    .list > .in{
        float: left;
        width: 25%;
        background-color: lightgreen;
    }

    .box > .l,
    .box > .r{
        position: absolute;
        opacity: 0;
        top: 0;
        bottom: 0;
        background-color: rgba(0, 0, 0, 0.1);
        cursor: pointer;
    }

    .box > .l {
        left: 0;
        right: 50%;
    }

    .box > .r {
        left: 50%;
        right: 0;
    }

    .box > .l:hover,
    .box > .r:hover{
        opacity: 1;
        transition: 1s;
    }
    </style>
</head>
<body>
<div class="box">
    <ul class="list" id="list">
        <li class="in">第1个</li>
        <li class="in">第2个</li>
        <li class="in">第3个</li>
        <li class="in">第4个</li>
    </ul>
    <div class="l" id="l"><</div>
    <div class="r" id="r">></div>
</div>
<script type="text/javascript">
var index = 0;
var children = list.children;
l.onclick = function(){
    if(index > 0){
        index--;
        move(index);
    }
}

r.onclick = function(){
    if(index < children.length - 1){
        index++;
        move(index);
    }
}

function move(index){
    list.style.left = '-' + index * 100 + '%';
}
</script>
</body>
九宫格
  • 利用绝对定位的偏移属性可以制作宽高自适应的九宫格效果
    <style type="text/css">
    * {
        padding: 0;
        margin: 0;
    }

    ul {
        list-style: none;
    }    

    .list {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
    }

    .list > .in {
        /* 这里设置:相对定位,因为下面使用了 伪元素,在 .in 的内容之前及之后插入了新内容 */
        position: relative;

        float: left;
        height: 33.3%;
        width: 33.3%;
        background-color: pink;
    }

    .list > .in:before {
        content: "";
        position: absolute;
        left: 10px;
        right: 10px;
        top: 10px;
        bottom: 10px;
        border-radius: 10px;
        background-color: lightblue;
    }

    .list > .in:after {
        content: attr(data-value);
        position: absolute;
        left: 0;
        right: 0;
        top: 0;
        bottom: 0;
        height: 30px;
        margin: auto;
        text-align: center;
        font:bold 24px/30px '宋体';
    }
    </style>
</head>
<body>
<ul class="list">
    <li class="in" data-value='1'></li>
    <li class="in" data-value='2'></li>
    <li class="in" data-value='3'></li>
    <li class="in" data-value='4'></li>
    <li class="in" data-value='5'></li>
    <li class="in" data-value='6'></li>
    <li class="in" data-value='7'></li>
    <li class="in" data-value='8'></li>
    <li class="in" data-value='9'></li>
</ul>
</body>

相对定位(relative)

定义
  • 当元素相对定位时,它会从其正常位置移走,不过,原来所占的空间并不会因此消失。相对定位元素,会为其所有子元素建立一个新的包含块。这个包含块对应于该元素原本所在的位置
  • 相对定位完成的过程首先是按static(float)方式生成一个元素(并且元素像层一样浮动了起来),然后相对于自身原有位置进行偏移,移动的方向和幅度由leftrighttopbottom属性确定,偏移前的位置保留不动
  • position: relative; 和 负margin 都可以使元素位置发生偏移,二者有什么区别?
    • position: relative; 相对自己原本的位置偏移,不影响其它普通流中元素的位置
    • margin:除了让元素自身发生偏移还影响其它普通流中的元素
    <style type="text/css">
    * {
        padding: 0;
        margin: 0;
    }

    .box {
        width: 600px;
        height: 300px;
        margin: 30px;
        background-color: pink;
    }

    .box > .box1 {
        position: relative;
        top: 50px;
        left: 100px;
        /* .box1 元素相对于以前的位置向右移动100px,向下移动50px */
        /* 虽然 .box1 元素相对于以前的位置产生了偏移,但是 .box1 元素以前的位置还是保留着,所以span元素实际显示的区域是在 .box1 元素以前位置的后面 */

        width: 100px;
        height: 100px;
        background-color: lightsalmon;
    }
    </style>
</head>
<body>
<div class="box">
    <div class="box1">相对定位</div>
    <span>你好世界你好世界你好世界你好世界你好世界你好世界</span>
</div>
</body>
  • 注意:
    • 元素仍然处于标准文档流中
    • 如果相对定位元素遇到过度受限的问题,一个值会重置为另一个值的相反数。bottom 总是等于 -top,right 总是等于 -left
百分比
  • 非常奇怪的是,虽然相对定位的数值型偏移属性是相对于自身的,但其百分比却是相对于包含块的。top 和 bottom 百分比相对于包含块的高度(只是高度height,不包括纵向 padding 和 border),left 和 right 百分比相对于包含块的宽度(只是宽度 width,不包括横向 padding 和 border)
  • 注意:对于IE7-和firefox浏览器来说,若包含块的高度 height 为 auto,则百分比的 top 和 bottom 设置有效果,而其他浏览器则都没有效果
    <style type="text/css">
    * {
        padding: 0;
        margin: 0;
    }
 
    .box {
        width: 400px;
        height: 400px;
        background-color: pink;
    }

    .box > .box1{
        position: relative;
        left: 40px;
        top: 40px;
        /* 数值型相对于自身 */

        width: 100px;
        height: 100px;
        background-color: lightsalmon;
    }

    .box > .box2{
        position: relative;
        left: 10%;  
        top: 10%;
        /* 百分比相对于包含块,这里移动 10% * 400 = 40px */

        width: 100px;
        height: 100px;
        background-color: lightblue;
    }
    </style>
</head>
<body>
<div class="box">
    <div class="box1"></div>
    <div class="box2"></div>
</div>
</body>
特性
  • 限制范围
    • 般地,给绝对定位元素限制范围时,为其父级元素设置相对定位relative,因为相对定位元素不脱离文档流
    • 注意:相对定位元素可以限制绝对定位,但不能限制固定定位,因为固定定位是相对于视窗定位的
  • 提升层级
    • 当想要提升元素层级,又不想脱离文档流时,使用相对定位是一个好主意
行内元素
  • 不同于绝对定位元素可以使元素具有块级元素属性,相对定位应用于 inline 元素后,由于无法改变其行内元素的属性,不具备块级元素属性,无法设置宽高,其上下 margin 也依然存在问题
    <style type="text/css">
    *{
        padding: 0;
        margin: 0;
    }

    .box {
        width: 600px;
        height: 300px;
        margin: 30px;
        background-color: pink;
    }

    .box > .inline1 {
        position: absolute;
        width: 100px;
        height: 100px;
        margin: 100px 0 0 100px;
        background-color: lightsalmon;
    }

    .box > .inline2 {
        position: relative;
        width: 100px;
        height: 100px;
        margin: 20px 0 0 20px;
        background-color: lightblue;
    }
    </style>
</head>
<body>
<div class="box">
    <span class="inline1">行内元素1</span>
    <span class="inline2">行内元素2</span>
</div>
</body>
IE兼容
  • 在IE6浏览器下,haslayout下的元素 负margin 超出父元素的部分会被隐藏掉。这个问题可以通过设置margin负值元素的 position 属性值为 relative 来解决

固定定位(fixed)

  • 固定定位是绝对定位的一种,元素会完全从文档流中去除,但固定元素的偏移是相对于视窗,或者说它的相对移动的坐标是视图(屏幕内的网页窗口)本身。由于视图本身是固定的,它不会随浏览器窗口的滚动条滚动而变化,除非我们在屏幕中移动浏览器窗口的屏幕位置,或改变浏览器窗口的显示大小,因此固定定位的元素会始终位于浏览器窗口内视图的某个位置,不会受文档流动影响,这与background-attachment: fixed;属性功能相同
  • 注意:IE7-浏览器不支持
特性
  • 固定定位与绝对定位的很多特性都类似,具有包裹性、破坏性及去浮动的特性,关于各浏览器中 display 属性的 bug、clip属性的隐藏功能、静态位置跳动以及overflow失效的表现都相同,在此就不再赘述
全屏遮罩
  • 当页面内容超出页面容器大小出现滚动条时,此时使用 absolute 全屏遮罩会出现滚动条以外部分没有遮住的情况。因为根元素html的父级是document,document的高度和可视区域一致,也就是与视窗一致,是不包括滚动条以外部分的
  • 这时,只能使用fixed固定定位来实现全屏遮罩效果
    <style type="text/css">
    *{
        padding: 0;
        margin: 0;
    }

    .page {
        position: absolute;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        background-color: pink;
        z-index: -1;
    }    

    .test {
        width: 2000px;
        height: 200px;
        margin: 20px;
        background-color: lightblue;
    }
    </style>
</head>
<body>
<div class="page" id="page"></div>
<div class="test"></div>  
<button type="button">absolute</button>
<button type="button">fixed</button>

<script type="text/javascript">
// 分别点击两个按钮,并拖动横向滚动条查看效果
var btns = document.getElementsByTagName('button');

for(var i = 0; i < btns.length; i++){
    btns[i].onclick = function(){
        page.style.position = this.innerHTML;
        console.log('.page 当前的定位方式为 ' + this.innerHTML)
    }
}  
</script>
</body>

CSS定位中的堆叠 z-index

  • 对于所有定位,最后都不免遇到两个元素试图放在同一位置上的情况。显然,其中一个必须盖住另一个。但,如何控制哪个元素放在上层,这就引入了属性 z-index
  • 参考: 深入理解CSS中的层叠上下文和层叠顺序
z-index 的作用
  • 利用z-index,可以改变元素相互覆盖的顺序。这个属性的名字由坐标系统得来,其中从左向右是x轴,从上到下是y轴。从屏幕到用户是z轴。在这个坐标系中,较高z-index值的元素 比 较低z-index值的元素 离用户更近,这会导致较高z-index值的元素覆盖其他元素,这也称为堆叠或叠放
  • z-index 仅在设置了position 非 static 属性的元素生效,且 z-index 的值只能在兄弟元素之间比较
  • 注意:z-index默认值为 auto,不会建立层叠上下文。但为 0 时则会建立层叠上下文
z-index: <integer> | auto(默认) | inherit
// 应用于:定位元素。无继承性
// z-index 应用于定位元素是CSS2的规范,到了CSS3标准,z-index 的应用范围扩大了不少
// 所有整数都可以作为 z-index 的值,包括负数。如果为元素指定一个负z-index值,会将其移到离读者更远的位置,会移到叠放栈的更低层
堆叠规则
  • 对于CSS2.1来说,页面元素的堆叠规则如下:
  • 定位元素的堆叠规则:
    • 对于定位元素(position不是static的元素)来说,不设置z-index或z-index相同时,后面元素覆盖前面元素
    • 对于处于同一堆叠上下文中的同一层次的元素来说,默认z-index较大值覆盖z-index较小值
    <style type="text/css">
    .clearfix:after {
        content: " ";
        display: table;
        clear: both;
    }

    .parent {
        border: 10px solid green;
        background-color: rgba(0, 255, 0, 0.5);
        /*overflow: hidden;*/
    }

    .parent > div{
        height: 80px;
    }

    .block {
        border: 1px solid green;
        color: white;
        background-color: pink
    }

    /*
    行内框与一个浮动元素重叠时,其边框、背景和内容都在该浮动元素之上显示
    块框与一个浮动元素重叠时,其边框和背景在该浮动元素之下显示,而内容在浮动元素之上显示
    */
    .float {
        float: left;
        font-weight: bolder;
        background-color: yellow
    }

    .inline {
        margin-left: -40px;
        background-color: lightcoral;
    }

    .position {
        position: relative;
        background-color: rgba(0, 0, 255, 0.8);
    }

    .positive-zindex {
        position: relative;
        z-index: 10;
        top: -10px;
        background-color: rgba(255, 0, 0, 0.8);
    }

    .negative-zindex {
        position: relative;
        z-index: -1;
        top: -20px;
        background-color: lightcoral;
    }
    </style>
</head>
<body>
<div class="parent">
    文字内容
    <div class="block">块状元素块状元素块状元素<br>块状元素块状元素块状元素<br>块状元素块状元素块状元素</div>
    <div class="float clearfix">浮动元素浮动元素浮动元素</div>
    <span class="inline">行内元素行内元素行内元素</span>
    <div class="position">定位元素定位元素定位元素</div>
    <div class="positive-zindex">正z-index正z-index正z-index</div>
    <div class="negative-zindex">负z-index负z-index负z-index</div>
</div>
</body>
堆叠上下文
  • 一旦为一个元素指定了z-index值(不是auto),该元素会建立自己的局部堆叠上下文。这意味着,元素的所有后代相对于该祖先元素都有其自己的叠放顺序
  • auto值指当前堆叠上下文中生成的栈层次与其父框的层次相同,这个框不会建立新的局部叠放上下文。z-index: auto;z-index: 0;的值相等,但z-index: 0;会建立新的局部堆叠上下文
  • 元素不会叠放在其堆叠上下文(即定位父级z-index为数字值)的背景之下,但可以叠放在其内容之下;当元素没有处于堆叠上下文中,元素不会叠放在<body>元素的背景之下,但可以叠放在其内容之下
    <style type="text/css">
    * {
        padding: 0;
        margin: 0;
    }

    .box1 {
        position: relative;
        /*z-index: 0;*/
        width: 150px;
        height: 150px;
        padding: 10px;
        margin: 50px; 
        background-color: lightsalmon;
    }

    .box1 > .box2 {
        position: relative;
        z-index: -1;
        width: 100px;
        height: 100px;
        margin-top: -10px;
        background-color: lightblue;
    }

    .box3 {
        width: 200px;
        height: 200px;
        padding: 10px;
        margin: -100px 50px 0;
        background-color: lightgreen;
    }
    </style>
</head>
<body>
<div class="box1">
    <p>box1</p>
    <div class="box2">box2</div>
</div>
<div class="box3">box3</div>
<script type="text/javascript">
var divs = document.getElementsByTagName('div'),
    box1 = divs[0],
    box2 = divs[1],
    box3 = divs[2];
console.log(getComputedStyle(box1, false)['z-index']);  // 0
console.log(getComputedStyle(box2, false)['z-index']);  // -1
console.log(getComputedStyle(box3, false)['z-index']);  // auto
</script>
</body>
兼容
  • IE7-浏览器 z-index 的默认值是 0
    • 一般地,定位元素的 z-index 的默认值是 auto,而IE7-浏览器定位元素的 z-index 的默认值是 0,二者的区别是IE7-浏览器的定位元素会自动生成堆叠上下文
  • IE6-浏览器关于z-index的一个怪异bug
    • 当元素本身浮动且不是定位元素(position是static),元素父级是relative,则在IE6-浏览器在无论该元素的父级的z-index如何设置都不起作用
    • 解决办法:
      • 元素去除浮动
      • 父级元素的相对定位改成绝对定位
      • 元素添加position属性(static除外)
      • 以上三个方法任一方法都可以,其实就是在破坏bug成立的条件
  • IE6-浏览器下select的z-index无效而遮挡div
    • IE6-浏览器下select元素(下拉列表)设置z-index无效,且默认会堆叠在div上
    • 解决办法:在IE6-浏览器中,虽然div无法覆盖select,但是iframe可以覆盖select。所以可以设置一个与div宽高相同的iframe。让div覆盖iframe,iframe覆盖select,最终达到select被div覆盖的效果

推荐阅读更多精彩内容

  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 10,101评论 1 88
  • CSS 是什么 css(Cascading Style Sheets),层叠样式表,选择器{属性:值;属性:值}h...
    崔敏嫣阅读 654评论 0 5
  • 1.CSS基本概念 1.1 CSS的定义 CSS(Cascading Style Sheets)层叠样式表,主要用...
    寥寥十一阅读 827评论 0 6
  • 一:在制作一个Web应用或Web站点的过程中,你是如何考虑他的UI、安全性、高性能、SEO、可维护性以及技术因素的...
    Arno_z阅读 394评论 0 1
  • relative:生成相对定位的元素,通过top,bottom,left,right的位置相对于其正常位置进行定位...
    zx9426阅读 411评论 0 2