绝对定位和相对定位的内幕

css有5种不同的position属性值

我们不会讨论inherit,因为顾名思义,它就是继承了父元素的值,而且在比较老的IE版本中,支持情况也不好。


任何元素的position属性的默认值都是static。所谓的static定位就是元素在文档流中。当然了,这完全取决于你的HTML结构。


另一个值你肯定见过,它就是fixed。说白了,它就是把一个对象钉在背景上,因此无论你把它放在哪,它就会一直在那。我们经常在sidebar的导航元素中看到它的身影,当页面向下滚动了很远的距离,这时候我们想回到顶部,如果没有一个fixed的导航,这种用户体验是很差的。


前面这三个值都很浅显易懂,接下来是绝对定位和相对定位。我们会单独的解释这些值,并且会讨论它们如何配合使用。


绝对定位

使用绝对定位,你可以让一个元素脱离文档流,并且把它放在页面上某个指定的位置。为了了解它如何工作,我们创建了一个简单的无序列表。


正如我们说过的,列表项(list item)默认的定位方式是static,这就意味着它们会跟随标准的文档流。下面我对其中一项使用绝对定位。

如你所见,第4项完全脱离了文档流,并且位于浏览器窗口的左上角。请注意,即使有其他内容占据了这个位置,这个元素也不在乎。当我们使用绝对定位时,它不会影响文档流中的其他元素,也不会被别的元素影响。


使用绝对定位的原因是我们想精确的定位,通过top、bottom、left和right属性,我们可以实现。举个例子,我们想让第4项距离顶部20px,距离左边20px。


为了证明绝对定位不会影响别的元素(或反之),我们让第4项靠近其他列表项。可以看到,它会叠加在其他元素上面而不是把它们挤开。


最后要注意的是,第5项占据了原来第4项的位置,而不是保持不动,就像第4项还在那一样。因为第4项脱离了文档流,其他所有元素都会进行调整。


相对定位

相对定位和绝对定位很类似,你也可以使用top、bottom、left和right进行精确定位。主要的区别在于元素的起始点不同。正如你前面看到的,绝对定位的起始点是浏览器窗口的左上角。同样的例子,来看看如果我们使用相对定位会怎样。


什么都没发生!事实证明,这个对象的确进行了相对定位,但是它的起始点就是元素在文档流的位置,而不是页面的左上角。现在,如果你使用相同的20px进行偏移,结果就会不同了。

这一次,这个元素相对于它的起始位置发生了位移。当你只是想对元素的位置进行微调的时候,这就非常有用了。请注意,和绝对定位一样,相对定位的元素同样不关心文档流中的其他元素。但是,相对定位的元素原来的位置不会被后面的元素占据,这和绝对定位不同,相对定位对文档流不会产生任何影响,就好像那个元素从未移动过。


它们如何配合使用

我们通过一个小例子来演示


HTML

创建一个div,class是“photo”,里面有一张200*200px的图片,这就是所有的HTML。

<div class="photo">
    <img src="http://lorempixum.com/200/200/people/9" />
</div>


基本的CSS

先简单的进行一些设置,比如把背景的颜色调暗些,给图片设置一个大小,设置好看的边框和阴影效果。

body {
    background: #222;
}

.photo {
    border: 5px solid white;
    height: 200px;
    width: 200px;
    margin: 50px auto;

    /* 有点复杂但是很酷的阴影效果 */
    -webkit-box-shadow: 0px 10px 7px rgba(0,0,0,0.4), 0px 20px 10px rgba(0,0,0,0.2);
    -moz-box-shadow: 0px 10px 7px rgba(0,0,0,0.4), 0px 20px 10px rgba(0,0,0,0.2);
    box-shadow: 0px 10px 7px rgba(0,0,0,0.4), 0px 20px 10px rgba(0,0,0,0.2);
}

效果如下:


贴上一个胶带

我们想要的效果是使用一块小胶带把图片贴在背景上。


首先我们使用 :before 伪类创建胶带。我们给它20px高度和100px宽度,然后背景设置为白色,不透明度为50%,这里我又加了一点点阴影效果。

.photo:before {
    content: "";
    height: 20px;
    width: 100px;
    background: rgba(255,255,255,0.5);

    -webkit-box-shadow: 0px 1px 3px rgba(0,0,0,0.4);
    -moz-box-shadow: 0px 1px 3px rgba(0,0,0,0.4);
    box-shadow: 0px 1px 3px rgba(0,0,0,0.4);
}


效果如下。胶带实际上影响了文档流。即使它不可见,它还是把图片挤出了边框的范围。


既然发现了伪类带来的问题,为了解决这些问题,我们先试着给胶带使用相对定位。

.photo:before {
    content: "";
    height: 20px;
    width: 100px;
    background: rgba(255,255,255,0.5);
    position: relative;
    top: 0px;
    left: 0px;

    -webkit-box-shadow: 0px 1px 3px rgba(0,0,0,0.4);
    -moz-box-shadow: 0px 1px 3px rgba(0,0,0,0.4);
    box-shadow: 0px 1px 3px rgba(0,0,0,0.4);
}


效果如下:


如你所见,问题没有得到解决,那接着尝试绝对定位。

.photo:before {
    content: "";
    height: 20px;
    width: 100px;
    background: rgba(255,255,255,0.5);
    position: absolute;
    top: 0px;
    left: 0px;

    -webkit-box-shadow: 0px 1px 3px rgba(0,0,0,0.4);
    -moz-box-shadow: 0px 1px 3px rgba(0,0,0,0.4);
    box-shadow: 0px 1px 3px rgba(0,0,0,0.4);
}

效果如下:


这回胶带移动了,却移到角落上去了。我们可以使用top和left进行推移,但这还是解决不了问题。为什么呢?

分析一下原因,我们知道绝对定位可以把胶带定位到某个精确的位置,但是这张图片会自动水平居中,所以当你改变窗口大小时,图片的位置会进行调整,这时胶带的位置就又有问题了。


现在,我们尝试完了相对定位和绝对定位,但是都不能解决问题。我们接下来该怎么办呢?

别急,到现在我们还没有解释绝对定位背后的故事,实际上,绝对定位并不总是以浏览器窗口的左上角为起始点。我们所说的 position: absolute; 表示的是相对于元素的第一个非static定位的父元素进行绝对定位,也就是说绝对定位不是完全的绝对,而是相对于某个父元素,如果不存在这个父元素,默认就是浏览器窗口(不是html或body节点!)


回到刚才的例子,我们还是对胶带使用绝对定位,但是首先需要确定绝对定位相对的父元素,也就是photo。我们不想对photo使用绝对定位,因为我们并不想移动它。因此,我们对它使用相对定位。

.photo {
    margin: 50px auto;
    border: 5px solid white;
    width: 200px;
    height: 200px;
    position: relative;

    /*overly complex but cool shadow*/
    -webkit-box-shadow: 0px 10px 7px rgba(0,0,0,0.4), 0px 20px 10px rgba(0,0,0,0.2);
    -moz-box-shadow: 0px 10px 7px rgba(0,0,0,0.4), 0px 20px 10px rgba(0,0,0,0.2);
    box-shadow: 0px 10px 7px rgba(0,0,0,0.4), 0px 20px 10px rgba(0,0,0,0.2);
}
 
 
.photo:before {
    content: "";
    height: 20px;
    width: 100px;
    background: rgba(255,255,255,0.5);
    position: absolute;
    top: 0px;
    left: 0px;

    -webkit-box-shadow: 0px 1px 3px rgba(0,0,0,0.4);
    -moz-box-shadow: 0px 1px 3px rgba(0,0,0,0.4);
    box-shadow: 0px 1px 3px rgba(0,0,0,0.4);
}


效果如下:


距离胜利还有一步之遥,最后我们还需要调整一下胶带的位置。注意一下,我为top属性设置了一个负值,因此胶带会偏离图片,产生一种浮在背景上的感觉。设置left属性使胶带位于图片的中间位置。

.photo:before {
    content: "";
    height: 20px;
    width: 100px;
    background: rgba(255,255,255,0.5);
    position: absolute;
    top: -15px;
    left: 50px;

    -webkit-box-shadow: 0px 1px 3px rgba(0,0,0,0.4);
    -moz-box-shadow: 0px 1px 3px rgba(0,0,0,0.4);
    box-shadow: 0px 1px 3px rgba(0,0,0,0.4);
}


效果如下:


小结

记住以下3点吧:

1. 相对定位就是相对于元素原来的位置让元素产生位移

2. 绝对定位就是相对于元素第一个非static定位的父元素进行定位

3. 相对定位或绝对定位的元素不会影响旁边的static定位或fixed定位的元素(绝对定位会脱离文档流,相对定位会占据原来的位置)

posted @ 2012-05-07 23:27  越己  阅读(2321)  评论(1编辑  收藏  举报