absolute绝对定位的非绝对定位用法

一、absolute绝对定位的流行用法

一般而言,我们会用absolute绝对定位做什么呢?就是绝对定位,顾名思意,定死在某个位置上。例如,lightbox效果就是使用的绝对定位,例如新浪微博的弹出提示信息,我要转发李冰冰姐姐的微博,结果就会弹出:
新浪微博绝对定位使用 张鑫旭-鑫空间-鑫生活

还有就是与父relative相对定位标签结合使用,实现相对于父标签的绝对定位效果,例如人人网的搜索下拉菜单效果:
人人网下拉效果 张鑫旭-鑫空间-鑫生活

这里用法少不了的是left(right)绝对定位值或是top(bottom)值,否则绝对定位的位置会跟设置了left为0,top为0值一样。好,我这里特意斜体加粗,为什么呢?因为这句话是不正确的,如果您没有意识到,说明您有必要好好看看这篇文章了。

well, 可能别人不是如此,但我对position:absolute的理解,可以说很长一段时间都是不到位的,或者或是一直没有机会好好的静下心来研究,知道个大概,于是就会有一些错误的认识。其中之一就是上面提到的,position为absolute的元素如果没有设置left, top等值与left:0;top:0;的的效果一样,一样吗?其实不一样。

二、absolute元素的margin定位

absolute定位于margin定位似乎是冤家,某种定义上讲,两者作用一致,都可以定位,似乎两者水火不容,竞争对手,确实,大部分情况下是,但是没有设置定位数值的absolute元素可以通过margin来进行定位。举个小例子吧,见下面的代码,一张绝对定位的图片,含margin属性,无left,top等定值数值:
absolute定位与margin定位其实是没有什么冲突的,无论absolute元素时候设置了left/top值,其margin属性值都是可以起作用的。下面展示的是没有left/top值的absolute元素的margin定位。

<img src="http://image.zhangxinxu.com/image/blog/zxx_90_0824.jpg" width="90" height="111" style="position:absolute; margin:50px 0 0 50px;" />

结果如下图:
absolute元素的margin定位 张鑫旭-鑫空间-鑫生活

您可以狠狠地点击这里:该小例子demo

可见absolute元素可以通过margin进行定位。前提就是没有设置left或是top之类的定位数值。我是这么理解的,对于没有设置绝对定位值的absolute绝对定位元素并没有脱离文档流,依旧在demo中(可能不正确)(现纠正:此理解是错误的,已脱离文档流),证据如下:我们再一个普通的div中(无任何样式)放置一个无绝对定位值的absolute元素,这个元素依旧子啊这个div中,而没有跑到div之外,例如如下的示例代码:

<div style="width:200px; height:120px; background:#f0f3f9; margin:40px;"><img data-src="http://image.zhangxinxu.com/image/blog/zxx_90_0824.jpg" style="position:absolute;" /></div>

结果如下图:
absolute元素与文档流 张鑫旭-鑫空间-鑫生活

您可以狠狠地点击这里:该示例demo

可以说,没有设置定位值的absolute元素是个普通又不普通的元素,普通之处在于其依旧在DOM tree中,对margin等属性敏感;不普通在于其实际的高宽都丢失了。这非常类似于浮动(float),浮动的本质就是“包裹与破坏”,破坏高度,浮动元素的实际占据高度为0(具体点这里);而absolute元素(无定位值)也是“包裹与破坏”,只是其“破坏”比float更加凶猛,不仅实际的高度没有,连实际的宽度也没有。说句不严谨的结论:绝对定位元素就是个比浮动元素更加变态的近亲。

三、绝对定位元素的非绝对定位

从上面一部分我们可以得到两个结论:其一,无定位值的absolute元素可以使用margin定位;其二,无定位值的absolute元素是个没有实际宽度的浮动元素。

这两点很重要,我们可以使用这两个特性实现一些特别的定位效果。两个例子,一是文字投影效果,二是自适应布局。

文字的阴影效果
CSS3中有text-shadow属性可以实现文字阴影效果,但是IE对CSS3的支持不佳,所以我们需要想替他的方法实现,absolute+margin是个很好很简单的方法,见下面的效果图,截自Firefox3.5:
文字阴影效果 张鑫旭-鑫空间-鑫生活

相关代码如下:

css代码:
.zxx_show{padding:20px; background:#f0f3f9; color:#aaaaaa; font-size:14px;}
.zxx_text{position:absolute; margin:-1px 0 0 -1px; color:#333333;}

HTML代码:
<div class="zxx_show">
    <span class="zxx_text">这是一段用来测试的文字,看看是否有投影效果~~</span>
    这是一段用来测试的文字,看看是否有投影效果~~
</div>

您可以狠狠地点击这里:文字投影效果demo

绝对定位元素需要写在投影文字之前,因为absolute元素实际占据的高度宽度都是0,所以文字可以自然而然的在其下方显示,由于下方的文字颜色较浅,于是便形成投影效果。此方法很精妙,可惜有小小兼容性差异,IE6下投影方向是水平朝右,IE7是右上方向,需要hack修复。

自适应布局
没有定位值的absolute元素是个更加变态的float元素,所以浮动元素干的某些事情absolute元素也能做,例如自适应布局。例如facebook动态头像与内容描述就是使用的这个方法。
facebook头像与描述自适应 张鑫旭-鑫空间-鑫生活

由于头像的宽度固定,所以对于描述标签,我们可以使用margin或是padding撑开一段距离,头像使用无定位值的absolute定位,这样就实现了头像与描述的自适应布局效果了。

例如,我的博客个人信息简介处,现在就是使用的float自适应布局,其实将float属性替换成absolute,效果一样的,见下图:
absolute与float在自适应布局中的替换 张鑫旭-鑫空间-鑫生活

关于absolute的自适应应用,我也做了个demo,您可以狠狠地点击这里:absolute自适应布局demo

下图为demo效果截图:
absolute自适应demo截图 张鑫旭-鑫空间-鑫生活

absolute绝对定位的非绝对定位应用肯定还有其他,只要记住无定位值的absolute元素就是个连实际宽度也没有的float浮动元素就可以了,然后利用这个特性,发挥您的创造力,实现更多更精彩的效果吧。

四、最后的小结

最后,先回答下开始悬而位答的问题:position为absolute的元素如果没有设置left, top等值与left:0;top:0;的的效果为何不一样?相信您应该知道答案了,例如一个div中有个absolute属性元素,其没有left或是top值,其会像个普通的inline-block属性元素一样静静地呆在这个div里面,但是一旦设置了left:0;top:0;对不起,这个absolute元素立马变身,直接从DOM tree里面脱离,独立于文档流,结果相对于最近的relative属性的祖先标签定位(如果没有,就body定位)。由于我们平时使用absolute都离不开left,top之类的值,所以才会概念不清。

每个CSS属性都有一段故事,需要我们静下心来发现,体会。

如果您发现文章中有表述不准确或是有相关问题需要交流可以通过评论或是去这里进行提问交流。
原创文章,转载请注明来自张鑫旭-鑫空间-鑫生活[http://www.zhangxinxu.com]
本文地址:http://www.zhangxinxu.com/wordpress/?p=608

(本篇完)

分享到:

标签: , , , , , , ,

赞助商推荐(我也要赞助)

想学到点真东西? ×
如果你有1~3年前端开发经验,不妨 ×
想要工资30K? ×


发表评论(目前35 条评论)

  1. 小七说道:

    有个问题很有趣:一般我们用absolute是要父元素或者祖先元素设置relative的,如果我设置了有个元素a是absolute,它的子元素b也设置absolute,这时候父元素a是绝对定位的,a的子元素b它把a当做relative去对待,我可以理解为:absolute不一定要父元素是relative,父元素是absolute也行。

  2. 努力的蜗牛说道:

    大神,这篇文章中说的使用了绝对定位的元素自身是没有宽高的,然后我在你写的“鑫三无准则”这篇文章中有关于徐若瑄微博的博客头像,这个元素最外层的使用了绝对定位方式,但是这个盒子没有设置宽高,却也能显示?这是为什么呢?求大神解惑,邮箱号前面的数字是我的qq号。

  3. somnus说道:

    最后说道,一个div中有个absolute属性元素,其没有left或是top值,其会像个普通的inline-block属性元素一样静静地呆在这个div里面,

    在这种情况下,它也是脱离文档流的,准确地说他不是呆在div里面的

  4. 冬日暖阳说道:

    为什么我在谷歌测试absolute的margin定位,定位元素的高度、宽度没有塌陷,在查看元素时还是显示了其高度和宽度。 难道我是对塌陷的意思理解错误?

  5. 王相尧说道:

    我觉得,嗯,不知道你是不是为了通俗易懂,,
    我个人理解,这个和块级格式化上下文(BFC)的建立有很大关系。
    说的简单点,因为float元素和position元素都会建立BFC,是一个机制,所以我觉得这是两个分离的过程,第一,为内容建立BFC。第二,寻找同层BFC。
    所以对于absolute,它为内容建立了BFC但是我们并没有触发寻找BFC的动作,所以此时,absolute元素,依然处于其父元素box类型的约束下。也因此absolute元素的margin属性才与其父元素互动。当我们设置如margin:auto、left、right、等属性时候,会触发元素寻找其所在的同层BFC(即嵌套结构中触发BFC的长辈元素),此时,absolute元素作为长辈元素的子元素,自然依据父元素的box类型约束自己。

    对于float元素,我们在设置之处就设定了left,right等,那么按照上边说的,我们可以理解,此时,float元素默认就完成了第二部。
    再多说一点,根据BFC机制,同层BFC(其实body元素就是个BFC所以,平时怎么排。建立的新BFC就怎么排。)父子之间是完全包裹的。依据这,我们可以理解overflow:hidden为什么可以清除浮动,,,float元素建立新的BFC,而父级元素依然处于底层BFC中,此时为父亲元素设置overflow:hidden为其内容建立BFC,那么此时嵌套结构同层BFC,即孩子又回到了父亲的怀抱,所以,实现了清除浮动的效果。

    。。。。。。再说一点,其实,依据上边的原理,我们可以实现一个横纵居中技术(特别是纵向居中)

    我直接代码不多说
    .align{
    overflow:hidden;
    }
    .align>.align-center{
    position:absolute;
    left:0;
    right:0;
    top:0;
    bottom:0;
    margin:auto; //margin:0 auto(auto 0);我多此一举,,,好吧,打我脸。
    }

    • 小东毛哥说道:

      赞同你的理解,另外‘同层BFC(即嵌套结构中触发BFC的长辈元素)’中的同层,用的不太好吧,和括号里面不统一,改成包裹层好一点吧。

  6. zhisuper说道:

    为什么不支持pre标签呢 哎

  7. zhisuper说道:

    大神你好。我是小白,刚看完慕课网的HTML、CSS基础。
    我不知道能不能得到您的回答,在一个群里面我也去提问过,当时他们明显就是解决不了我的问题,设置跟我说一些奇怪的话,比如,绝对定位只有TOP,LEFT属性,我就没有再去说什么。
    绝对定位参照具有定位属性的父级,否则就是参照BODY
    当创建一个定位属性的父级的时候,需要在里面添加position:relative; 然后需要定位的元素添加absolute. 这是很基础的问题。但是,当我给父级相对定位添加了一个left:20px这样一个定位的值的时候(具体px无影响),然后需要定位的块absolute设置left right的时候就会出现无效的情况。
    一句话概括,相对和绝对组合使用的时候,父级相对定位不可以添加left,top,否则是有影响的。
    我很难理解这是为什么,或者我这个结论就是胡扯?但是我确实遇到这个问题了。
    我是菜鸟,很多欠缺。
    如下代码:

    无标题文档

    div{
    border:solid 2px red;
    width:400px;
    height:200px;
    position:relative;
    top:10px;
    left:20px;/*当这里设置right的时候,下面注释的地方就不可以再设置right,只可以设置LEFT,反之……*/

    }
    div.box1{
    border-color:blue; width:35%; height:35%;

    position:absolute;
    top:20px;
    right:50px;/*这里也是*/
    }
    div#box2{
    border-color:green; width:35%; height:35%;
    position:absolute;
    top:20px;
    right:20px; /*为什么这里 可以设置左,当设置右的时候就没有效果,比如此时单单改动RIGHT的值的情况下,试试看?…………以上改动左右,并且改动px数值看看是否有效果?*/

    }

    box1
    box2

    大神,如果看到,真心请求您花费点时间帮我这个菜鸟看一下吧。多谢了

    • 我怎么都设置不出你说的场景啊说道:

      不管left、right还是宽高的设置,感觉都没有问题

    • 王相尧说道:

      朋友,,这个是因为你的选择器使用导致的问题

      首先你使用标签选择器,div 也就是说,所有的div都具有left:10px属性,,,那么,后边的box也是div,所以,他也具有left属性。然后,你再使用div.box选择到box给他设置了right:10px。。。

      是不是矛盾了?一个元素,,又有left,又有right,怎么办,肯定是砍掉一个。所以,后设置的就不起作用了。因为,臣妾办不到啊!

      • 发现一个错误,元素设置了固定宽高后,在垂直方向同时有top,bottom只有top的值会生效,水平方向同时有left,right只有left值会生效,并不是因为后设置的就不起作用了。如果有问题请指正,谢谢

    • 阿磊说道:

      。。div.box1与div.box2都有你最开始设置的div的属性啊。正如上面同学所说的,后面设置的属性替代掉了 前面设置的属性。。我想过了6个月,你肯定也明白了。加油

  8. Soy说道:

    鑫哥好!
    关于最后一段
    “结果相对于最近的relative属性的祖先标签定位(如果没有,就body定位)。”
    我有个疑问,当我把一个div的css设置为position:absolute;height:50px;left:0;right:0;bottom:0;,此div的祖先元素都没设置position。此div的位置将在浏览器的最下方,而body的高度依旧是0,在浏览器最上方,这个怎么解释。。

    • hunter说道:

      翻了一下css权威指南上说的,如果一个absolute的元素的祖先元素中没有非static定位的元素,就按其“初始包含块定位”即根元素html或者body的包含块,浏览器一般默认设置为视窗大小的一个区域为“初始包含块”

  9. izqcool说道:

    鑫哥,既然absolute不设置top和left的时候会想普通元素一样,为什么设置margin:0 auto;不起作用,而设置其他的 值可以呢?

  10. Andy说道:

    鑫哥好!
    尝试探讨一下。。。

    我认为造成上述种种现象的原因是因为:
    left和top的默认值并不是0!!所以设置和不设置的后果完全不一样。
    没有设置left、top值,则left、top的默认值将使该元素保持在原来的位置。

    不知道我这样理解是否有误?恳请指正。
    谢谢鑫哥~

  11. smallfish说道:

    觉得这篇文章说得太含糊,哪里有些问题..

    <div style=”width:200px; height: 40px; background:#f0f3f9; margin:40px;”>abcdefghijk lmnopqrstu vwxyzabcde fghijklmno pqrstuvwxyzabcdefghijklmnopqrstuvwxyz<img src=”http://image.zhangxinxu.com/image/blog/zxx_90_0824.jpg” style=”position:absolute;”></div>

    按我的理解,没有设置定位值的absolute元素应该是没有脱离文档流的,否则我上面示例中父元素的文字应该被覆盖。

    • CoolHector说道:

      img使用绝对定位之后在不添加top,right,bottom,left的情况下仍然貌似还是个那个安静的美男子,安静的呆在原位置,但其实他在z-index轴上已经发生的变化,你可以尝试在绝对定位的img后添加文字查看效果。

      • danny说道:

        很奇怪的是如果在img后面添加的不是文字或行内元素,而是块级元素就又不一样了。

        • Todd_hua说道:

          块级和行内表现都是一样啊,都被绝对定位的img覆盖。有什么不同的呢?

  12. ah说道:

    相对于最近的relative属性的祖先标签定位,如果没有,其实不是body,应该是document对象

  13. littlePumpkin说道:

    我试了一下,absolute定位的元素,不只是相对于最近的relative祖先来设置位置。相对于除了static之外的定位祖先都可以设置位置。

  14. sam说道:

    旭哥俺来喽~~~

    话说元素的absolute不设置left top 默认的起始点都是在它absolute变身之前所处正常文档流的位置(但失去了占位)~

    嗯..这是俺以前用absolute发现的特性..刚刚也实验了一次,的确如此~

  15. 水液态中说道:

    对于没有设置绝对定位值的absolute绝对定位元素并没有脱离文档流,依旧在demo中。
    会覆盖内容文字,不可能在文档中吧

  16. jill说道:

    1、只要记住无定位值的absolute元素就是个连实际宽度也没有的float浮动元素就可以了
    如果是float,那么去掉padding-left,内容中无图片时,文字部分可以自动占据图片位置。

    2、例如一个div中有个absolute属性元素,其没有left或是top值,其会像个普通的inline-block属性元素一样静静地呆在这个div 里面,但是一旦设置了left:0;top:0;对不起,这个absolute元素立马变身,直接从DOM tree里面脱离,独立于文档流

    如果是inline-block,那么图文混排模块中,就不需要设置padding-left值了。
    一旦设置absolute,就是脱离文档流了,不过不设置left、top时位置没变。

    你的思路还有文章有很多值得学习的地方,但我觉得,很多东西我们必须要首先参考下W3C标准规定。像absolute的这种技巧,也许未来某天万一就修整了呢?

  17. cwshell说道:

    我个人研究的不深,没具体做测试,不过从理解的角度上来讲,个人应该觉得有两点可能有点儿问题:一个是关于margin不起作用这点,另一个是关于如果没有参考值的情况下,是否会类似于inline-block的样式“静静的呆在这个div里”。
    应该说文中所给出的案例有点儿特殊性,因为外部父层设置了高度,如果没有高度呢?关于文中在阐述的这两点的严谨性是不是应该再考究一下。个人没做严格测试,感兴趣的朋友可以测试一下试试。另外,关于DOM TREE里那一点,应该也有待考究一下,在很多项目中,为保证js的高性能运行,比如显示隐藏或类似tab切换的效果中,为减少reflow节点,各位经常采用的方式可能就是使操作对象脱离文档流或动画流,那时候很多情况大家应该并没有设置相应参考值,因为是不必要的对于我们的目的来讲,因此,文中总结处的这一点观点,是否也应该再做一次考虑。
    一点儿个人见解,不知对否,有兴趣的可以继续探讨,呵呵不好请拍砖。

  18. zky说道:

    我试了下 我设置了position:absulute 也设置了 top 和left 的值 但是 margin 依然有效

  19. john说道:

    有三个div:content、page、sidebar,content包裹page和sidebar,page设置margin-right:300px,Sidebar宽度为300px,然后绝对定位在右侧。我采用这种方式定位,结果content不计算sidebar的宽度,导致footer和Sidebar重叠,该怎么解决?谢谢

    • 张 鑫旭说道:

      方法有:1. 给page设定最小高度(min-height + height),使其至少高度大于sidebar。
      2. 使用浮动定位代替绝对定位,详情参见这里,http://www.zhangxinxu.com/wordpress/?p=370

      • HTML布局说道:

        如果在一个图片上定位了文字,怎么样能做到文字随着图片的自适应也自适应呢?

        • zhisuper说道:

          文字相对于图片定位和雨图片一样都是相对同一个父级去设置,试一下。哈哈,其实我也不懂,0基础刚学前端没几天。当时如果你不能直接否定我说的可以自己去试一下。