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

这篇文章发布于 2010年01月29日,星期五,06:27,归类于 CSS相关。 阅读 205171 次, 今日 2 次 43 条评论

 

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

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

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

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

well, 可能别人不是如此,但我对position:absolute的理解,可以说很长一段时间都是不到位的,或者或是一直没有机会好好的静下心来研究,知道个大概,于是就会有一些错误的认识。其中之一就是上面提到的,positionabsolute的元素如果没有设置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="zxx.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 src="zxx.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浮动元素就可以了,然后利用这个特性,发挥您的创造力,实现更多更精彩的效果吧。

四、最后的小结

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

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

(本篇完)

分享到:


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

  1. 2018.8说道:

    div 父级元素设置了relative,子元素都设置了absolute;其中一个(块元素)子元素没有设置Left和top,也会跑到父元素位置。另一个子元素(行内块)却不行,必须设置left和top 值 请问为什么??

  2. 小七说道:

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

    • 大锤说道:

      absolute , 相对于定位的元素是离它最近的非static元素 , 并不是只有relative

    • mfk说道:

      会从当前节点开始,向上找第一个非static(没有position的相当于static)元素做为定位起点。即向祖先节点找第一个postion是relative/absolute/fixed的。如果一直没找到,则用body做为定位起点。

  3. 努力的蜗牛说道:

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

  4. somnus说道:

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

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

    • 七仔说道:

      这个个人反角其实跟inline-block并不一样,你说的很对。不过大神这篇文章写于2010年,之后可能浏览器更新或是其他原因导致absolute的元素即使没有left/top值也和left:0;top:0;效果一样了。

  5. 冬日暖阳说道:

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

    • mfk说道:

      测试时,要去掉父节点的width、height。如果没有塌陷,则父节点高度=子节点撑开的高度。如果塌陷了,则父节点高度=0

  6. 王相尧说道:

    我觉得,嗯,不知道你是不是为了通俗易懂,,
    我个人理解,这个和块级格式化上下文(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的长辈元素)’中的同层,用的不太好吧,和括号里面不统一,改成包裹层好一点吧。

  7. zhisuper说道:

    为什么不支持pre标签呢 哎

  8. 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个月,你肯定也明白了。加油

  9. 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的包含块,浏览器一般默认设置为视窗大小的一个区域为“初始包含块”

    • mfk说道:

      首先,祖先元素没有设置position。则相对于body定位。
      其次,position:absolute;height:50px;left:0;right:0;bottom:0;相当于高度50宽度100%,然后bottom:0,所以将成浏览器最下方。
      再次,body中如果无其它内容,唯一的div绝对定位后,脱离文档流,所以body高度是0。

  10. izqcool说道:

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

    • mfk说道:

      margin:0 auto; 只对display:block元素起作用。absolute无top和left相当于display:inline-block,所以不起作用。

  11. Andy说道:

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

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

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

  12. 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覆盖。有什么不同的呢?

  13. ah说道:

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

  14. littlePumpkin说道:

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

  15. sam说道:

    旭哥俺来喽~~~

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

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

  16. 水液态中说道:

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

  17. 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的这种技巧,也许未来某天万一就修整了呢?

  18. cwshell说道:

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

  19. zky说道:

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

  20. 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基础刚学前端没几天。当时如果你不能直接否定我说的可以自己去试一下。