传说中的定位元素

577 阅读8分钟

1.常用的定位属性

  (1) static : 常规框,默认值。
  (2) relative : 相对定位,在元素没有定位之前的位置上进行定位,并且它原本所占的空间仍为其保留。
  (3) absolute : 绝对定位,在没有设置left,top,bottom,right时,它将在没有定位之前的位置上脱离文档流,不占空间,后面的元素将会替代它的位置,并且有层级的概念。它总是在文档流的上面,除非手动设置z-index属性。如果设置了left,top,bottom,right时,它将按照设置进行定位,如果它不是在一个定位的父元素里面(除static外),那么它的起点将在窗口的左上角,反之,它的起点将在父元素的位置上进行定位。一个行内元素,一旦设置了此属性,则会转变成块元素。
  (4) fixed : 固定定位,参照物是按照浏览器窗口定位,设置了fixed的元素就像被固定住了一样,它不会随着滚动条的滚动而滚动。一个行内元素设置了此属性后,将被转变成块元素。

2.详谈static

  将一个元素的position属性设置为static,和不设置的效果是相同的。因为当不设置position属性时,默认position属性的值就是static。
示例代码:
<style type="text/css">
    body,div{
        margin:0;
        padding:0;
    }
    .static{
        position:static;
        top:100px;
        left:100px;
        width:100%;
        height:60px;
        background-color:red;
    }
    .common{
        width:100%;
        heigth:100px;
        background-color:blue;
    }
</style>
<body>
    <div class="static"></div>
    <div class="common"></div>
</body>
运行结果如下:

从运行结果可以看到,设置为position:static的元素,它的left和top,并不起作用。

3.详谈relative

  元素按照原来的位置定位,并且不脱离文档流。
<style type="text/css">
    body,div{
        margin:0;
        padding:0;
    }
    div{
        width:200px;
        height:200px;
        border:1px solid #dedede;
    }
    .relative{
        position:relative;
        background:red
    }
</style>
<body>
    <div>item1</div>
    <div class="relative">relative</div>
    <div>item3</div>
</body>
运行效果如下:

  如果在设置了position:relative;的元素中设置left,top,bottom,right值,它的层级就总是要比标准流元素高。

<style type="text/css">
    body,div{
        margin:0;
        padding:0;
    }
    div{
        width:200px;
        height:200px;
        border:1px solid #dedede;
    }
    .relative{
        position:relative;
        background:red;
        left:0;
        top:100px;
    }
</style>
<body>
    <div>item1</div>
    <div class="relative">relative</div>
    <div>item3</div>
</body>
运行结果如下:

  从运行结果可以看出,背景色为红色的div遮挡住了下面的div元素。如果红色的div元素不想遮挡住下面的蓝色div元素,可以设置z-index属性来调整层级。

<style type="text/css">
    body,div{
        margin:0;
        padding:0;
    }
    div{
        width:200px;
        height:200px;
        border:1px solid #dedede;
    }
    .relative{
        position:relative;
        background:red;
        left:0;
        top:100px;
        z-index:-1;
    }
</style>
<body>
    <div>item1</div>
    <div class="relative">relative</div>
    <div>item3</div>
</body>
运行结果如下:

  relative的left,right,bottom,top都可能会引起溢出。

<style type="text/css">
    body,div{
        margin:0;
        padding:0;
    }
    div{
        width:100px;
        height:100px;
        border:1px solid red;
        overflow:auto;
    }
    p{
        position:relative;
        right:-100px;
    }
</style>
<body>
    <div>
        <p>relative</p>
    </div>
</body>
运行结果如下:

导致溢出的原因,就是因为relative不脱离文档流。

4.详谈absolute

  设置为position:absolute;的元素,其定位的参照物是第一个非static定位的父级元素,并且设置了absolute的元素,在没有设置left,right,bottom,top的属性值的情况下,元素并不会改变位置,但是却脱离了文档流,并且有了z-index层级的概念,可以通过设置该属性来调整层级。如果两个元素同时设置了position:absolute;则后来者居上,按照元素的位置,越后面的层级越高。
<style type="text/css">
    body,div{
        margin:0;
        padding:0;
    }
    .wrap{
        position:relative;
        width:200px;
        border:1px solid #dedede;
    }
    .item1,.item2{
        width:100%;
        height:100px;
        background:red;
    }
    .absolute{
        position:absolute;
        width:100%;
        height:50px;
        background:pink;
    }
</style>
<body>
    <div class="wrap">
        <div class="item1">item1</div>
        <div class="absolute">absolute</div>
        <div class="item2">item2</div>
    </div>
</body>
运行结果如下:

当定位遇上了定位该怎么定位呐?

<style type="text/css">
    body,div{
        margin:0;
        padding:0;
    }
    .box{
        position:relative;
        left:100px;
        top:200px;
        width:200px;
        height:200px;
        background-color:red;
    }
    .item1{
        position:absolute;
        left:10px;
        top:10px;
        width:100px;
        height:100px;
        background-color:pink;
    }
    .item2{
        position:absolute;
        left:10px;
        top:10px;
        width:50px;
        height:50px;
        background-color:blue;
    }
</style>
<body>
    <div class="box">
        <div class="item1">
            <div class="item2"></div>
        </div>
    </div>
</body>
运行效果如下:

5.详谈fixed

  fixed和absolute的定位效果非常类似,但是它们有着很大的区别。
<style type="text/css">
    body,div{
        margin:0;
        padding:0;
    }
    .box1,.box2{
        position:relative;
        left:150px;
        top:150px;
        width:200px;
        height:200px;
        border:1px solid #dedede;
    }
    .box1 .absolute{
        position:absolute;
        top:0;
        left:0;
        width:100px;
        height:100px;
        background-color:pink;
    }
    .box2 .fixed{
        position:fixed;
        top:0;
        left:0;
        width:100px;
        height:100px;
        background-color:green;
    }
</style>
<body>
    <div class="box1">
        <div class="absolute">absolute</div>
    </div>
    <div class="box2">
        <div class="fixed">fixed</div>
    </div>
</body>
运行结果如下:

    从运行结果可以看出,设置为position:fixed;的元素并没有参照它的父元素进行定位,而是在浏览器的左上角显示,由此可见,fixed的元素是按照浏览器窗口定位的。

6.关于定位鲜为人知的那些事儿

  (1) 如果同时设置left,bottom,right,top时,那么只有left和top值起作用。
  (2) 如果同时设置left,bottom,right,top时,又想让right或者bottom起作用,那么可以将left设置为auto。
  (3) 如果将left,bottom,right,top都设置为auto时,如果它上面没有其他元素,相当于没有进行设置。
  (4) 如果元素设置为position:absolute,同时又设置margin-left和left时,则该元素距离左侧的距离是margin-left + left的结果。
  (5) 让一个元素垂直居中,如下所示:
<style type="text/css">
    body,div{
        margin:0;
        padding:0;
    }
    .box{
        position:absolute;
        left:0;
        top:0;
        bottom:0;
        right:0;
        margin:auto;
        width:200px;
        height:200px;
        background-color:green;
    }
</style>
<body>
    <div class="box"></div>
</body>
  (6) 通过fixed实现遮罩层,如下所示:
<style type="text/css">
    body,div{
        margin:0;
        padding:0;
    }
    .wrap{
        position:fixed;
        top:0;
        left:0;
        width:100%;
        height:100%;
        background-color:rgba(0,0,0,.5);
    }
    .wrap .item{
        position:absolute;
        top:0;
        left:0;
        right:0;
        bottom:0;
        margin:auto;
        width:200px;
        height:200px;
        background:pink;
    }
</style>
<body>
    <div class="wrap">
        <div class="item"></div>
    </div>
</body>
  (7) 父元素包不住fixed元素,如下所示:
<style type="text/css">
    body,div{
        margin:0;
        padding:0;
    }
    .box{
        position:absolute;
        left:200px;
        width:200px;
        height:200px;
        border:1px solid #dedede;
    }
    .box .item{
        position:fixed;
        left:0;
        width:100px;
        height:100px;
        background-color:red;
    }
</style>
<body>
    <div class="box">
        <div class="item"></div>
    </div>
</body>
运行效果如下:

  如果想fixed元素根据它的父元素定位,那么就不能设置left,bottom,top,right值。

<style type="text/css">
    body,div{
        margin:0;
        padding:0;
    }
    .box{
        position:absolute;
        left:200px;
        width:200px;
        height:200px;
        border:1px solid #dedede;
    }
    .box .item{
        position:fixed;
        width:100px;
        height:100px;
        background-color:red;
    }
</style>
<body>
    <div class="box">
        <div class="item"></div>
    </div>
</body>
运行效果如下:

如果没有设置left,right,bottom,top,那么它们的默认值是auto。   (8) 一旦定位值为absolute或fixed,那么高度将百分之百生效。fixed的百分比参照浏览器窗口计算,不管是否有父元素;absolute如果在一个定位的父元素里面,那么则按照父元素计算后的值进行计算,父元素无法自适应定位元素的高度,代码如下:

<style type="text/css">
    body,div{
        margin:0;
        padding:0;
    }
    .box{
        position:relative;
        width:300px;
        height:100px;
        border:1px solid #dedede;
        background:blue;
    }
    .box .item{
        position:absolute;
        left:0;
        top:0;
        width:100px;
        height:200px;
        background:pink;
    }
</style>
<body>
    <div class="box">
        <div class="item"></div>
    </div>
</body>
运行效果如下:

  (9) fixed的另外一个问题就是当在移动端使用position:fixed,制作遮罩层时会发现,在部分浏览器中,如果滚动内容,遮罩后面的的内容也会跟着滚动。那么,要解决这个问题,可以使用一个小技巧,

<style type="text/css">
    body{
        position:fixed;
        left:0;
        top:0;
    }
</style>
这样的话,它就不会滚动了,因为fixed的高度是参照浏览器的高度;其实,最简单的做法是,当显示遮罩层时,给body加overflow:hidden;然后,关闭遮罩层时,再去掉这个样式。