CSS 各种定位(position)方式的区别


学习编程有很多种方式,比如在线教程、网络课程或是高强度的编程训练营。教程是不错,不过它能教给你的只有基本知识。不管是线上还是线下的课程(译注:这指国外),都非常昂贵,还会限制你的时间安排。虽然你也可以通过多种渠道去向你的同事求助,但是你如果想要理解他们给出的答案,你还需要具有足够的知识量。

这就是为什么大多数想学编程—或只是重拾一门技术的人—最终还是会求助于书籍的原因。如果你肯付出努力,书本确实可以帮助你学到任何你需要的东西,并且将来还可以用作非常好的参考资源。(译注:比如 Stack Overflow 上有个《哪本最具影响力的书,是每个程序员都应该读的?》,伯乐在线以前就整理翻译成《国外程序员推荐:每个程序员都应读的书》,十分推荐。)

1. 通读全书

不彻底地读完解释性的材料是一个常见的误区。跳过代码运行原理的解释而直接去看代码示例会将你领向失败。之所以你要买一本计算机书籍,就是为了获取代码示例,以及它附带的解释。

计算机书通常包含了你应该边读边标记的一些额外的信息,例如一些需要花大量时间去研究的参考资料。你可以使用这些参考资料帮助你去寻找不同的代码实现方式或不同的测试代码示例的输入方式。

当然了,单单一本书并不能教会你在当今复杂的编程环境下的所有东西。因此,许多计算机书籍还细心地引用了组织好的在线资源,里面也许包含了许多你所查找的内容的准确信息。

2. 集中精力

确保你在读书时能保持注意力。当你发现你突然在想一次钓鱼之行或是电视上的球赛,就是你该放下书的时候。随性地阅读是不够的,你需要专心致志或有一个练习的目标。如果你需要回顾之前在你神游到钓鱼之行时所阅读的内容确保你真正理解了,也别太在意。

3. 下载代码

编程书通常附带了可下载的源代码。下载源代码,载入编译器中编译它,然后看它实现了什么,这个过程非常重要。这些可以运行的代码对于我们理解编程技术至关重要。它们确保你可以看到一个没有任何问题(例如拼写错误等等)的可工作的示例。

在你开始理解代码的运行后,接下来你或许想要试着自己手写一下,以加强你对其原理的理解。拼写错误是新手程序员最主要的挫败感的来源之一,所以下载示例的源代码作为你的参考吧,这样你可以更快地找到自己的错误并纠正它们。除了手写代码,也要将其用键盘打出来。

4. 使用debugger进行单步调试

取决于你想学的语言以及你使用 Integrated Development Environment (IDE)的程度,你可能对于当你跑一个应用时确切发生了什么没有一个清晰的概念。很多现代编程语言的目标是任务自动化。当你了解程序是如何运行后,这一特性还是很好的,但它同样可能会成为你学习路上的一道坎。

在例程中单步调试帮助你理解细节。随着你一步一步向前运行,你可以观察变量的值,考察它们如何变化,以及确定它们为何以那种方式变化。使用debugger的功能去改变变量的值,你可以看到这些变化是怎样影响应用的。 再看看应用内存,去了解它是怎么保存信息的,然后查看调用栈去准确地了解一个调用是怎么完成的。总之,要在你单步调试时,探索应用中的所有可能的方面。

这种方法让你可以探索其他的应用开发和设计之路。比如,在适当的环境下,你有时可以进入文件库中观察它们是如何做关于应用的工作的。在一些案例中,你可以探索字节码或是反汇编应用代码去看底层如何运作。

注意:由于有些程序是时间敏感的,用debugger做单步调试可能导致应用不正常运行。此外,你有可能需要在某些节点重启应用,因为环境将会崩溃,你将得不到你所要的结果。单步调试最适合用于短的代码段。

5. 把玩并掌握代码

到了这一步,你可能会觉得你已经从这本书所给予的信息中提取出了全部。然而,你还是没有把玩示例代码并试着让它以别的方式运行。试验是学习的关键。将书本中的示例代码试验一下,是提升你技能的好方法。当你做了各种各样的延伸时,你应该开始理解代码的变化如何在整体上影响应用。这类知识无法通过其他方式学习——你需要通过试验去精准地理解一门语言所提供的特性。

一、有话要说

以前写内容基本上都是:眼睛一亮——哟呵,这个不错,写!然后去古人所说的茅房里蹲会儿,就有写作的思路了。但是,构思相对/绝对(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化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>

结果如下截图:

可以看到,图片应该的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属性的使用一个道理。

     static:静态定位是position的默认值,元素框正常生成,也就是没有定位时的正常显示。


  relative:相对定位


  用法一:元素相对自身的原位置偏移某个距离,但是原本的空间依旧保留,表现为空白。


  用法二:把一个元素设置为position: relative; 可以使该元素的子元素相对该元素绝对定位。


  absolute:绝对定位


  元素从文档流删除,并相对于包含块定位。元素在原本的空间关闭。元素定位后生成一个块级框,不论它原来是行内元素还是块级元素。


  包含块:最近的position值不是static的祖先元素(块级或行内),一般会指定一个元素作为绝对定位元素的包含块,将其position设置为relative而且没有偏移。


  fixed:固定定位


  元素从文档流删除,并相对于浏览器视窗定位,因此不随文档滚动而移动。元素在原本的空间关闭。元素定位后生成一个块级框,不论它原来是行内元素还是块级元素。与绝对定位的区别仅仅是包含块不同。


  包含块:浏览器视窗。


  absolute/fixed和float对比


  类似:元素都会从文档流删除,但是依旧会影响布局;都会生成一个块级框,无论原来是不是块级元素。


  区别:float的包含块是最近的块级祖先元素。


  偏移属性:top/right/bottom/left,初始值是auto。


  采用position定位之后必须采用偏移属性定义偏移量,也就是相对包含块的偏移。注意应用于position值不是static的元素。


  有时也需要定义width和heigth,但是可能会和偏移属性的定义冲突,因为四个偏移属性实际上已经定义了元素的大小。此时,根据width和left属性定义左右,根据top和height属性定义上下。


  内容溢出overflow: visible/ hidden/ scroll /auto/ inherit,初始值是visible。


  一个元素的大小固定,但是其内容放不下,就会导致溢出。overflow控制溢出部分的可见(visible)、不可见(hidden)、滚动可见(scroll)。


  元素可见性visibility: visible/ hidden/ collapse/ inherit,初始值是visible。


  visibility:hidden和display:none的区别:visibility:hidden设置元素不可见,但是元素依旧会影响布局,只是元素部分呈现为空白;display:none元素不显示并且从文档流中删除,对文档布局没有任何影响。

最后,你将开始创造出与书中代码不太一样的应用。这时,你走到了一个新的阶段。在这个阶段中,你开始自信地创建自己的应用,并且真正地理解了它们是如何运作的。

七个重要阶段

学会编程意味着你对语言的理解程度足够让你去实现所有的需求,创造出有用的应用。举个例子来说,在录用你做开发工作之前,雇主们需要你去达到这样的技能水平。

获取这些技能的唯一途径就是去练习,练习,接着练习直到你将程序融会贯通。当你学习使用某种语言编程时,程序员们应该努力去达成下面七个成就。

  1. 学习语言的基础,如数据存储、关键字、决策判定和循环指令。

  2. 看如何用该语言去完成特定任务。

  3. 探究该语言如何通过它的库获得提升。

  4. 钻研该语言的细节并且理解它底层的运行机制。

  5. 利用该语言进行试验,看看关联的改变如何互相影响。

  6. 使用学到的技术去开始创建简单的应用。

  7. 通过创造越来越复杂的应用和研究其他该语言的资源去不断地提升技能。

这看起来很多,但有很多程序员可以证明在一本技术书的帮助下你确实可以达成这些所有的成就…如果你通过正确的方式阅读的话。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如有疑问大家可以留言交流,谢谢大家对【微信公众号:web前端开发大全】的支持。关注公众号在对话框发送 0 即可免费领取响应式网址开发视频教程。