CSS 相对|绝对(relative/absolute)定位系列(一)

一、有话要说

以前写内容基本上都是:眼睛一亮——哟呵,这个不错,写!然后去古人所说的茅房里蹲会儿,就有写作的思路了。但是,构思相对/绝对(relative/absolute)定位系列却有好些时日,考虑到:
1、 琐碎的俗称tip的东西不少,如何寻找主线串联;
2、 不少自己“非主流”的破常规的观点,如何一句话提炼,如何清晰表述,如何让人易于理解;
3、 relative/absolute/z-index本身关系暧昧非比寻常,如何有重点的叙述,同时又不扯断他们之间的牵连;
4、 又要拿一些大网站说事,如何避免可能的无意的言语上的冒犯;
5、 想一个够淡定同时又很噱头的题目;//zxx:此项以失败告终
6、 等等……

现在,终于决定开始敲键盘了,长时间的酝酿使得现在胸中有千言万语想倾吐啊,不急,像《火影》《海贼王》一样,是个长篇,娓娓道来。

二、必要的题外话

题外话说两点内容,一是关于观点与言论,二是关于情感化思维。

观点与言论
有句话貌似是这么说的:“我坚决不同意你的观点,但是我誓死捍卫你说话的权利!”;前段时间回家,在闲聊子女教育问题上(我纯听众),小舅就反复强调他的观点:“你可以义正言辞的当面孩子说:‘你的这种做法我认为是错误的!’,但是,你不能强制他按照你的想法来做。”

技术的道路上,似乎有这么个流程:经验 → 观点 → 世界观。 很多有经验的开发人员心中(可能无意识的)就形成了一套自己的准则,亦称技术方面的世界观。这种世界观本质上是带有宗教信仰的气息的,于是,当相悖的言论、相悖的世界观出现的时候,如果其不是海纳百川版包容与谦逊,所谓不屑,口水仗就会随之出现。

有着自己的世界观本身是好的,但是,如果像清朝政府一样,自我感觉良好,闭关锁国,对外在事物过分敌对,对自身也是一种限制,难有大成。所以,应该时时刻刻保持谦逊,虚怀若谷地思考接受别人的观点,方能在技术飞道路上不断前行,突破一个又一个的瓶颈。这也是我自己经常提醒自己的。

这里,我是非常欢迎各同行发表您的不同观点与看法的,尤其有理有据,争锋相对的观点,因为这让我看到了进步的可能点。为了帮助阐述自己的观点,本系列中会反复拿国内的一些大网站说事。我认为发表观点的权利应该是自由的,我可以很直接毫不掩饰地说:“我认为你这里的做法是欠妥的,可以改进的!”,这里我仅仅是从我个人的角度,以我的世界观来表达我的观点,仅仅是表达,完全没有什么嘲笑、不屑的意思,因为我知道,本身就没有什么对错之分,或许只是大家的出发点,侧重点不同而已。优秀的同行往往反而乐于见到真知灼见的观点,但是,林子大了,什么样的鸟都有,有些一直自以为是的人往往会自认为自己小小的自尊被侵犯而恶语相加,或是报以鄙视与嘲讽。要知道,在山顶上的人和山脚下的人眼中,对方都是渺小的;笑是会传染的,你在笑别人的时候也在被别人笑着;自以为在看画中人,其实自己也被当作画中人看着。

文章这东西就跟艺人一样,要有特色,好比苏打绿的娘娘声,春哥的爷们声。尤其是论述观点的文章,显然就要像辩论赛一样,观点鲜明,言辞激烈,否则,大家宁可去看凤姐说英语也不会鸟你写些什么东西的。

情感化思维
我在年初的“CSS float浮动的深入研究、详解及拓展(一)”一文中的引言部分曾阐述过“情感化思维”,认为“代码的情感化思维从无意识到前意识到意识”“代码的情感化认识渗透着部分人格”,您要是有兴趣可以去原文查看,这里再补充点我的新认识,情感化思维接近于感性思维,主要有感情倾向和形象化思维组成。这不难理解,举个2年之后的例子,假设那时我有女朋友了,并同时假设名叫婉儿,然后同事问婉儿,你对小张的情感是?婉儿的回答就会使“喜欢”,这就是“感情倾向”;然后同事又问,小张在你心中形象是?婉儿的回答是“冬日里的阳光,温暖的避风港”,这就是形象化思维。

例如浮动(一)中提到的我对浮动的感性化的认识:浮动就是一个变态,魔鬼,自私自利且影响他人的混球。我讨厌浮动。

其中,“变态,魔鬼,自私自利且影响他人的混球”属于形象化思维,“讨厌浮动”就属于感情倾向,合起来就是情感化思维。

我到现在还不清楚,是不是其他人跟我一样,会很感性的,夹杂着强烈的个人情感和性格特质去看到CSS的一些属性的。就自己而言,这种情感化的认识有助于理解与使用CSS。所以,本文也将借助情感化思维分析“position:relative/absolute”属性的脾气特性,利弊好坏。

三、absolute属性的情感化认识

我对position:absolute属性感性化的认识:absolute是一个善良的有个性的,我行我素、喜欢凌驾一切之上的魔鬼。这家伙,不喜欢也算不上讨厌,但是知道没事最好少招惹,免有后患。

四、position:absolute与float:left是近亲

先给大家讲个故事吧。曾经有两个魔鬼兄弟,一个叫浮动,一个叫绝对定位,它们总是一起在空中飞行戏耍的。但是,不幸的是,有一天,浮动被巨雷击中,双翼折损,陨落凡间,好在性命还在,但是,翅膀不在,它只能永远留在凡间,与芸芸众生呆在一起。偶然一天,众生发现浮动有一种能力,可以让布局整齐,有方向性的排列,于是,大肆使用其能力,建房子,造家园。但是,浮动本质上是魔鬼,其破坏性经常让房子高度塌陷,而饱受众生诟病。可怜的浮动啊,原本出身的意义就不是来建房子的,却被众人误解与指责。浮动的兄弟绝对定位本应在天空翱翔,但是为了看望其兄弟,也经常去凡间看望。后来,人们发现,绝对定位也有布局建房子的能力,也想拿来使用。但是,绝对定位不同于浮动,其翅膀尚在,其一个不乐意就可以飞回天空。聪明而狡黠的人们发现了一个可以限制绝对定位的物体,名叫相对定位。于是,什么时候,人们想利用绝对定位建房子,就使用这个名叫相对定位的东西把他限定住。后来,有一天,人们忍不住心中的疑问,就问绝对定位:“你在天上好好的,为什么没事要下来受罪呢?”绝对定位长吁一口气,道出了浮动就是他那可怜的弟弟的事情。“不会吧!”人们很惊讶,“你们样貌差异这么大,跟志玲姐和凤姐之间的差异有得一拼呢!”“唉”绝对定位又是一声叹气,“被雷击,翅膀没了,还毁了容,于是……”绝对定位忍不住抽泣起来。后来,人们逐渐明白,原来绝对定位下凡间帮着建房子都是自愿的。果然,后来,一部分人试着不再使用叫做相对定位的东西限制绝对定位,绝对定位也没有飞向天空……(未完,待续)

故事先说到这儿,正如故事里提到的,position:absolute与float:left论长相差别有志玲姐和凤姐那么大,但是,却是近亲,细想一下也合情合理,两者有两大共性:包裹性,破坏性。

包裹性
包裹性换种说法就是让元素inline-block化,例如一个div标签默认宽度是100%显示的,但是一旦被absolute属性缠上,则100%默认宽度就会变成自适应内部元素的宽度。哦,举个例子吧,如下测试代码:

CSS部分:

.div { padding:20px; margin-bottom:10px; background-color:#f0f3f9; }
.abs { position:absolute; }

HTML部分:

<div class="div">
    <img data-src="http://image.zhangxinxu.com/image/study/s/s256/mm1.jpg" />
    <p>无absolute</p>
</div>
<div class="div abs">
    <img data-src="http://image.zhangxinxu.com/image/study/s/s256/mm1.jpg" />
    <p>absolute后</p>
</div>

结果如下图所示:
absolute的inline-block化 张鑫旭-鑫空间-鑫生活

您可以狠狠地点击这里:absolute的inline-block化demo

float也是典型的inline-block化元素,这种元素的inline-block化适用于任何水平的标签。例如平时我们要让span标签支持width属性,可能要设置:

span { display:block; width:100px; }

但是,有float:left/position:absolute撑腰的情况下,display属性就是多余的,可以直接回家喝茶了。

span { float:left; width:100px; }
span { position:absolute; width:100px; }

破坏性
论破坏的功力,绝对定位显然比浮动更甚一筹,但是人们诟病的更多的却是浮动的破坏性。这不难理解,整天在耳边飞来飞去的苍蝇要比不常见的吸血牛虻讨厌。众人已经把浮动当作凡人中的一份子,而对于绝对定位,人们知道,毕竟人家原本隶属天上,能下凡间来帮忙造房子已经不错了,没有必要去苛求指责人家。

浮动与绝对定位与众生之间的关系 张鑫旭-鑫空间-鑫生活

浮动的破坏性在于切断line box链,致使高度塌陷,但由于浮动元素仍在凡间(DOM tree),实体是看得见摸得着的,所以其占据的实体位置还是在的。而absolute绝对定位不仅让高度塌陷,又由于从未深入凡间,在凡间没有他的实体位置,所以宽度也是塌陷的。

由于浮动身处凡间,所以其造成的破坏是可以通过其他手段弥补的;但是,绝对定位不属于凡间,其破坏无法修复,因为一是孤独,无人帮忙;二是只有空气,怎能修补。

例如下面的测试:
CSS代码:

.div { padding:20px; margin:10px 0 0 10px; background-color:#f0f3f9; float:left; }
.abs { position:absolute; }

HTML如下:

<div class="div">
    <img data-src="http://image.zhangxinxu.com/image/study/s/s256/mm1.jpg" />
    <p>图片无absolute</p>
</div>
<div class="div">
    <img class="abs" data-src="http://image.zhangxinxu.com/image/study/s/s256/mm1.jpg" />
    <p>图片absolute后</p>
</div>

结果如下截图:
absolute属性致使高宽塌陷 张鑫旭-鑫空间-鑫生活

可以看到,图片应该的position:absolute属性后,父标签的高宽都塌陷了,连它的兄弟float都救不了。

您可以狠狠地点击这里:absolute的破坏性demo

五、position:absolute滥用

在我看来,很多网站,position:absolute都有滥用的嫌疑,不仅仅是position:absolute滥用,其left,top属性值也滥用,relative属性值滥用,z-index也滥用。有的属性滥用就是单纯的多些代码而已;而有些其实可以不使用的地方也使用的话会给后来的扩展和维护造成很大的麻烦的。

relative/absolute/left/top/z-index这5个关系紧密,无论将哪一点都会牵扯到其他。为了避免讲述的混乱,我尽量只讲某一个。例如,这里只讲absolute属性。

absolute经常被一些新手拿来大肆建房子做布局也是可以理解的,貌似什么时候我看过一篇文章说,absolute属性的出现本来是想把页面搞得像photoshop那样,一个图层一个图层覆盖似的。但是,页面的发展显然与这个背道而驰,毕竟页面是活的。确实,像photoshop,把一个个层搞出来,使用absolute属性,以及一定坐标值就可以定位出来了。不需要考虑什么间距啊,margin啊,一些IE下乱七八糟的bug啊什么的,有一了百了的畅快感。尤其对于页面制作不熟悉的新手,这种绝对定位布局可谓屡试不爽。

还有时候,遇到有些复杂的布局,项目经理又催得紧,懒得再去折腾,干脆,直接,绝对定位,先把效果做出来再说。因为绝对定位毕竟有飞翔的能力,例如想在黄浦江中间建个灯塔,直接告知坐标,飞过去,灯塔一插,搞定了,很省事的。

看上去省事,其实是自掘坟墓。所谓“本属天上人,勿管凡间事”,对于普通的页面布局,不到万不得已不要使用absolute进行定位。

对普通的layout,如果动不动就使用absolute属性,我个人是比较深恶痛疾的。

首先自己是个流体布局控,绝对定位这种东西,显然没有流动的气质,尤其拿来定位后(虽然有时候在relative的庇护下也有一定的流动性)。流动性布局很强调不定宽,不定高,活用标签自身属性,顺其自然,最少干预。但是由于absolute属性(尤其是带有left/top值)的破坏性,会导致高宽塌陷,于是,不得已,需要设定一个高度值(或是足以撑开高度的值),例如新浪微博导航就是绝对定位,于是,导航外标签必须定高,否则,下面的元素会上来发生重叠:
新浪微博导航外标签定高 张鑫旭-鑫空间-鑫生活
高度禁用后导航重叠 张鑫旭-鑫空间-鑫生活

其次,自己是个代码控。自己是个有代码癖的人,眼中是容不得可以不使用的CSS属性的。对于absolute布局,为了修复其破坏造成的后遗症而花费的CSS代码开销在我看来已经超出的容忍的限制。

最后,也是更重要的,就是绝对定位大大降低了页面的扩展性和维护性。其在降低维护性方面的卓越表现不仅仅在于自身,还在于其领导能力(指引领relative与z-index制造更加混乱的页面,这个后面会依次讲到)。我想有经验的页面重构人员都深有体会,去改之前别人写的页面,出现问题的很多时候就是那些不知道为什么要绝对定位的元素,这些元素就像地雷一样,总以为安全,放心大胆地往前走,结果,“砰”一声嗝屁了。覆盖,重叠,精确调距离,修改之前的高宽参数等,想想都让人吐槽。最后,越改越混乱。

absolute属性本来是个好孩子,可做奇兵,颇有妙用。但是,太多人把天上的凤凰当野鸡养,把absolute过多的用于普通布局,而沉浸其中,不亦乐乎。

其实想想,要求也不能那么高。毕竟大部分的同行都是做中小站点的,一个页面寿命短短几个月说不定就要抄底重来。花功夫去折腾扩展性,代码量什么的,实在是对不起自己那点可怜的工资,有这点闲功夫还不如去撩撩美女姐姐,泡泡清纯小妹呢。所以,淡定,淡定!

不过,一些结论性的话还是要说的:想重构高质量的页面,少用绝对定位布局

六、鞋子是用来穿的

又是题外话。对于CSS属性,如何高效地使用它们,如何使页面流畅,灵动,又极具扩展性和可维护性呢?就是该生下来该干嘛的就让他干嘛。就拿绝对定位举例,absolute最大最能动的空间是在天空中,不受任何限制的天空,可以自由驰骋,又与世隔绝,不会对凡间造成任何侵扰,顶多遮住点阳光。所以,absolute尽量不要身陷林立的DOM中,尤其是用来做普通的布局,这可真是拿砍刀削指甲,做着危险的活儿啊。

举个更容易理解的例子吧。我们都知道鞋子是用来穿的。但是,它还有其他功能,比如说攻击武器,例如嫌小布什台上讲话语速太快跟不上,听不懂,你就可以掷出你的飞鞋提醒他降低语速。很显然,虽然鞋子有做武器这个特殊功能,你是不会去淘宝上买个百八十双鞋子,专门用来扔人的吧!absolute属性的使用一个道理。

下集看点
下集内容还是讲absolute定位,多实例与实践。内容大致有:
普通absolute布局的替代实现方案;
body标签是absolute自由的海洋;
解析absolute元素margin定位于left/top的恩怨情仇;
absolute与reflow回流及应用;
等……

原创文章,转载请注明来自张鑫旭-鑫空间-鑫生活[http://www.zhangxinxu.com]
本文地址:http://www.zhangxinxu.com/wordpress/?p=1287

(未完,待续…)

分享到:

标签: , , , , , , , ,

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

想学到点真东西? ×
如果你有1~3年前端开发经验,不妨 ×
想找个师兄入门前端?不妨 ×


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

  1. 夜的眼睛说道:

    没看懂的话,不如去看看官方文档,,真心的,基础很重要,要自己理解

  2. 啰嗦说道:

    能三句话说清楚吗?CSS能分行写吗

  3. 小雅么么哒说道:

    感觉说的真的很啰嗦,本意是好的,将枯燥的代码讲的生动,但是物极必反。

  4. 小何说道:

    绝对的大神,膜拜!

  5. 18y说道:

    详细的看了好几下…..6的飞起,写的很好,膜拜了(太有情感色彩的文章,我被css感动了!!
    )

  6. Stypstive说道:

    文中说:absolute使父容器高度和宽度都塌陷,我实验后发现,你的这个观点是错的。absolute只会使父容器的高度塌陷,并不会使宽度塌陷。
    张老师Demo中的例子之所有产生了宽度塌陷的效果,是因为在img的父容器.div上加了float:left;float:left这个使容器inline-block化了,宽度自适应成了普通流p的宽度,让人误以为是absolute使宽度也塌陷了!去掉float后就会发现,absolute并不能使父容器宽度塌陷。
    望修正!

  7. 说道:

    大神,读了你的文章,得出此结论,float可以用浮动闭合的方法让父元素完全包裹住子元素,而absolute是没有办法的,因为他是天上的天使.我理解的对吗?

  8. 柒小林说道:

    看了前半段,我知道写得很好,但是能不能不要这么多废话,我实在看不下去了!

  9. 林子说道:

    hi,你好,我也09华科的,计院的,现在搞后台开发。偶然看到你的文章,觉得写得不错,你开的有公众号吗?

  10. 情感多余说道:

    看篇文章还要了解你的情感,也是够累的了,没看

  11. python教程说道:

    婉儿的回答就会使“喜欢”
    不是‘使’是‘是’

  12. 天才相师233说道:

    写的不错,帮顶!

  13. 新手村新手1024号说道:

    那到底要怎么排列页面的元素呢?float 和position:absolute会造成麻烦(我就是那个爱用飞起来的absolute定位的新手,想定哪定哪,畅快,但是也感觉到了有的时候页面不知道怎么就乱了。要回复呀)

  14. 潇潇沐予说道:

    看了鑫哥很多文章,都很受用。今留言的目的其一是难表对鑫哥文章喜爱之情,解胞燃眉之急,撩人发奋之志。其二是想小小建议下鑫哥。是不是可以做个上下页的导航出来,鑫哥有不少系列类的博文,有时看完第一篇后,得找到文章日期后回到目录从上向下寻找后篇,些许苦恼。如果可以,当真是更加完美。

  15. 我服了说道:

    听你说的我想打你

  16. 国恒说道:

    错误一处:测试absolute会使宽度也塌陷的代码中HTML代码,第二个div是不是忘记了加abs的class?

  17. 江夏说道:

    我也觉得次要的文字有点过多,导致主体思想难以挖掘(个人感觉)

  18. hheedat说道:

    代码的情感那个,有同感

  19. mayte说道:

    太有情感色彩的文章,我被css感动了!!

  20. w724883说道:

    我觉得你的文章没必要的文字太多,啰嗦

  21. 华生_说道:

    第二例,给img给上position:absolute之后,img不在属于 他的父级div,父级div的内容就没有了,所以宽、高度塌陷。我是不是可以这样理解呢 ,鑫哥? 但是这样理解的话,我不知道为什么此时img的父级div还有一定的高度,用chrome developer tool ,除去margin、padding 看到高度为91*46,这宽、高度是怎么计算得来的呢?

    • wangqiaoqiao说道:

      因为div加了 float: left 所以此时div是 inline-block的,变成了自适应。所以这时候它的尺寸就和它所包含的 p元素息息相关。那么你可以看到此时p元素的宽就是 div的宽,div的高就是p元素的高 + p元素的margin值 + p元素的padding

  22. 紫电清霜说道:

    google一下前端知识,常常可以看到博主写的博文,看了好几篇了,帮助挺大的,写的很有感情啊,赞一个!!!!加油!!!!!

  23. 鞋垫说道:

    文章写得不错啊,很值得读!有一点关于页面的问题想对博主说下:

    看了一晚上文章,眼睛疼,就把页面放大,结果,左右两列同时放大,主要内容被挤掉了。。。这是不是流动布局的漏洞啊!希望博主能优化下。

  24. skot说道:

    楼主你可真有意思

  25. skot说道:

    我想知道为什么新浪的主导航relative和float要一起用呢?relative在这儿的作用是什么呢?博主是我要学习的人呢。一定得回答我这个问题啊

  26. 张涛说道:

    很喜欢你的文章,学到了很多知识。
    顺便请教一下可以吗?
    我在网上看到:float不能和absolute一起使用,但是可以和relative一起使用。不知道是什么原因。
    能麻烦指点一下吗,最好能帮忙举下例子哦。。。非常感谢。。。

  27. Leano说道:

    感情化认识在一些不写书,没有开博客写文章的人而言是潜意识的,没有总结的,也是没有必要的,像楼主这种出书,写博客服务大众的人来讲,感性化认识能使得读者更容易读懂作者的意思,有点深入浅出的味道。

  28. abeir说道:

    喜欢你的文章,看看,受益匪浅呐

  29. ng说道:

    强~~~~

  30. hairong说道:

    在网上搜圆角的解决办法搜到了你的博客,看了好几篇文章了,太厉害了…继续学习,继续关注~“

  31. veapon说道:

    我也喜欢蹲坑的时候想东西。

  32. 梧桐说道:

    对absolute的看法我和你如出一辙,继续看下一集去鸟..

  33. Bili说道:

    哥们,写得真好!顶!

  34. 一个好人哥说道:

    期待你的下一篇文章,加勒个油!比期待月子二还期待。

  35. ethanchen说道:

    广告没了?期待下集

  36. rage说道:

    神人!写的好!