關(guān)于CSS的position屬性的討論
面試的時候問個css的position屬性能刷掉一半的人這是啥情況……其實這問題我本來打算的是可以順著一路扯到
normal flow、containing block、bfc、margin collapse,base line,writing mode,bidi,
這樣一路問下去的,奈何***個問題(親我真的只問了position有哪些取值和行為?。┚捅瘎×?hellip;…
position屬性常用的取值static、relative以及absolute和它們的基本行為是每個前端都應該掌握的。這包括relative和absolute的定位原點。
fixed舊版本IE不支持,但是一個對技術(shù)有熱情的工程師也是應該了解的。
有過研究工程師可以知道absolute的containing block計算方式跟正常流不同,當然如果沒讀過標準的話,表述方式不一定是這樣。
對CSS布局有深入研究的工程師會知道position跟display、margin collapse、overflow、float這些特性相互疊加后的行為。
說句老實話,在狀態(tài)好的情況下,若是被問到這個題,我還能和他說道說道(很淺的那種),在狀態(tài)一般的情況下,我估計自己也直接悲劇了,那造成這個的是什么原因呢?
答案毫無疑問的是我CSS水平是很水的,當項目經(jīng)驗不夠的情況下,看書是不能記住一些東西的,所以還是需要項目實踐。
于是抱著我水我自豪的態(tài)度,我來試試他這道題水到底有多深,居然會刷掉一半的人。
思考過程
這個題若是單純提出position的幾個屬性,倒沒什么問題,但我們來看看他的發(fā)散:
normal flow(一般流)
containing block(包含塊)
bfc(我深刻的意識到我一定見過他,但可恥的忘的一干二凈了?。?/p>
margin collapse(搞不懂啊,應該是float引起的元素坍塌吧?)
base line (基線對齊)
......
后面的就完全沒有印象了,完了我想說,大哥我們能說中文嗎。。。至少給點解釋吧,對于css菜鳥來說看題目都很吃力的。。。。(掩面而泣)
驚嘆
仔細閱讀題目并加以分析后,你會發(fā)現(xiàn)他這潭水是很深的,這道題快5分鐘可結(jié)束,慢可問上半個小時,而且問完了CSS都可以忽略不計了。。。
為什么這么說呢?
① position主要用于頁面布局,對css布局熟悉的朋友能很好的運用他布局,甚至拋棄float那個魔鬼(昨天我做了一道面試題就不用float布局,因為float本身是不用于布局的,這么做的大哥,我不知道對不對,但我認為既然float不應該用于布局,我們便應該下意識的少用)。
② 在他發(fā)散過程中由將塊級元素與行內(nèi)元素提到了,甚至細分到了行內(nèi)元素的垂直對齊方式,更有可能發(fā)散到line-height上面,不可謂不深??!
③ 在以上能做好的都已經(jīng)不錯了,然后這道題更是可以細致到各種應用細節(jié),比如在IE7一下瀏覽器使用relative的z-index會有什么問題,比如在布局上你會使用float嗎,float為什么會引起元素坍塌,你如何解決元素坍塌......
......
然后的然后,他這道題真的發(fā)散開了就很大了,對于我這種水貨來說,看不懂啊,于是便只能在自己理解的方面做下說明,于是我們開始吧!
基本視覺格式化
凡是不能一蹴而就,我們一步步來,先了解點基礎的東西吧
我們在使用CSS過程中會發(fā)現(xiàn)很多“怪異”的現(xiàn)象,如果我們掌握了CSS中視覺表現(xiàn)模型是如何工作的了,那么是不是會更加接近真理呢?
基本框
CSS假定每個元素都有一個基本框,這個矩形框便是我們所說的元素框(在CSS3出現(xiàn)后圓形、團原型也不是不可能哦)
各個元素框中心有一個內(nèi)容區(qū)(content area),這個內(nèi)容區(qū)域會有以下屬性:內(nèi)邊距,外邊距,邊框。我這里又引用下其他大哥的圖吧:
包含塊
因為每個元素都相對于其它包含塊擺放,所以包含塊就是一個元素的“布局上下文”,
- <body>
- <div>
- <p>
- 刀狂劍癡葉小釵</p>
- </div>
- </body>
- </html>
在這個例子里面,p的包含塊便是div(包含塊由最近的塊級元素擔當),所以p元素依賴于div布局,div依賴于body,行內(nèi)元素擺放于包含塊沒什么關(guān)系。
塊級元素
塊級元素很霸道,會獨占一行作為自己的王國,一般一個元素的width被定義為從做內(nèi)邊距到右內(nèi)邊距的距離(IE6對盒模型解釋有誤)。margin、padding、width、height可以確定文檔布局。
多數(shù)情況下文檔高寬我們不太關(guān)心,寬度一般會鋪滿瀏覽器,高度會自己延生。
水平格式化
- <p style="width: 200px; padding: 10px; margin: 20px;">
- 刀狂劍癡葉小釵</p>
本來p元素寬度是200,但是由于padding問題寬度就變?yōu)?20了,外邊距再延生40,所以整個寬度就是260了,這樣便隱式的增加了width的值!
但是,其右邊距卻不是20,因為CSS還有一個規(guī)則:正常流塊級元素的margin,width,padding,border之和必須等于包含塊的內(nèi)容區(qū)域,所以右邊距會被重置為auto。
所以我們要將一個元素居中會這樣設置
- <div style="margin: 0 auto;"></div>
在寬度確定的情況下,做外邊距與右外邊距的值會被設置為相等的值(IE6忽視之,他會將之設置為0)。
負外邊距
由于margin可以被設置為負值,所以整個情況又會變得比較復雜,因為按照我們上面的規(guī)則,width便有可能超過其包含塊!??!
- <div style=" margin: 20px auto; width: 300px; background: gray; padding: 10px;">
- <p style=" background-color: Orange;">
- 刀狂劍癡葉小釵</p>
- </div>
- <div style=" margin: 20px auto; width: 300px; background: gray; padding: 10px;">
- <p style=" background-color: Orange; margin: 0 -20px;">
- 刀狂劍癡葉小釵</p>
- </div>
所以,我們平時操作負邊距時候,其實是增加了高寬,若是高寬確定的情況下,那邊是其他幾個屬性被增加了,帶來了元素移動的錯覺。
垂直格式化
塊級元素的高度默認由其內(nèi)容決定,我們可以為元素顯示設置高度,但是這樣的話,元素框便不會自動增加了。
垂直居中
在水平情況下設置auto后,會取相同的值,當在垂直情況下,情況有所不同,margin: auto 0;這種情況下,上下外邊距會被重置為0,元素框失去了外邊距(定位元素有所不同)。
- <div style=" margin: 20px auto; width: 300px; height: 200px; background: gray; padding: 10px; position: relative;">
- <p style=" background-color: Orange; width: 130px; height: 20px; margin: auto; position: absolute; ">
- 刀狂劍癡葉小釵</p>
- </div>
外邊距合并
外邊距合并的問題大家都知道,上下外邊距會發(fā)生合并現(xiàn)象,但是有種情況會讓事情變得比較復雜:
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title></title>
- <style type="text/css">
- body { background: #ECECEC; }
- .outer { background: white; border: 1px solid #CCCCCC; width: 300px; }
- .inner { margin: 10px; padding: 8px; background: none repeat scroll 0 0 #1C87D5; color: white;}
- </style>
- </head>
- <body>
- <div class="outer">
- <h1 class="inner">
- 來個測試走</h1>
- </div>
- </body>
- </html>
若是我們將代碼做一點改變:“將外層元素border”去掉;那么。。
他這種合并方法就徹底讓我傻眼了。。。。。
行內(nèi)元素
行內(nèi)元素的布局比塊級元素要復雜,我們使用塊級元素布局,所以會比較重視,但是往往忽略行內(nèi)元素的布局,這是會吃虧的。。。我們來看一個例子:
- <div style="margin: 20px auto; width: 300px; height: 200px; background: gray; padding: 10px; ">
- <span style=" border: 1px dashed orange;">
- 刀狂劍癡葉小釵刀狂劍癡葉小釵刀狂劍癡葉小釵刀狂劍癡葉小釵刀狂劍癡葉小釵刀狂劍癡葉小釵刀狂劍癡葉小釵刀狂劍癡葉小釵刀狂劍癡葉小釵
- </span>
- </div>
行內(nèi)元素和塊級元素表現(xiàn)有很多不同,以上只是一個開始,我們來捋一捋,行內(nèi)元素都有些什么東東:
- 匿名文本:
- 未被包含在行內(nèi)元素的字符串
- em框:
- em框在字體中定義,也被稱為字符狂
- 內(nèi)容區(qū):
- 內(nèi)容區(qū)可以是元素中各個字符的em框串在一起構(gòu)成的框,也可以由元素中字符字形描述的框。
- 行間距:
- font-size與line-height之差/2便是行間距
- 行內(nèi)框:
- 通過向內(nèi)容區(qū)增加行間距來描述,對于非替換元素行內(nèi)框剛好等于line-height
- 行框:
- 這是包含該行中出現(xiàn)的行內(nèi)框的***點和***點的最小框,意思是行框上邊界要高于***行內(nèi)框,***也要大于***的行內(nèi)框
所以說行內(nèi)元素坑坑爹呢,他的東西多著呢。。。
行內(nèi)格式化
所有元素都有一個line-height屬性,這個值會顯著的影響行內(nèi)元素顯示,行高由其組成元素和其他內(nèi)容(如文本)高度確定。
注意:line-height實際只影響行內(nèi)元素和其他行內(nèi)內(nèi)容,不會影響到塊級元素(至少不直接影響)
建立框
首先,對于行內(nèi)元素來說,font-size確定了內(nèi)容區(qū)的高度,如果一個元素的font-size是15px,那么內(nèi)容區(qū)高度便是15px,因為所有元素的em框都是15px。
如果一個行內(nèi)元素的font-size為15px,line-height為21px,相差的6px便是行間距,由此行內(nèi)框形成:
但是有一個場景又會讓整個發(fā)展變得撲朔迷離:
- <div style="line-height: 12px; font-size: 12px; margin: 20px auto; background: gray;">
- 刀狂劍癡葉小釵<span style=" font-size: 24px;">刀狂劍癡葉小釵</span>刀狂劍癡葉小釵
- </div>
對于匿名文本來說,內(nèi)容高度沒有變化,半間距為0,但是對于span來說,line-height減去font-size后我們得到的半間距為-6,所以其行內(nèi)框依舊是12px,內(nèi)容區(qū)卻大了出來。
vertical-align
margin的方式不能垂直對齊,行內(nèi)元素便提供了vertical-align屬性:
- top
- 將元素行內(nèi)框的頂端與包含該元素的行框的頂端對齊
- bottom
- 將元素行內(nèi)框的低端與包含該元素的行框的底端對齊
- text-top
- 將元素行內(nèi)框的頂端與父元素內(nèi)容區(qū)的頂端對齊
- text-bottom
- 將元素行內(nèi)框的底端與父元素內(nèi)容區(qū)的底端對齊
- middle
- 將元素行內(nèi)框的垂直中點與父元素基線上0.5ex處一點對齊
補充知識(http://www.zhangxinxu.com)
浮動和定位
經(jīng)過以上的知識,我們知道了,所有文檔元素都有一個框!被稱為元素框,它描述了一個元素在文檔布局中所占空間大小,所以框與框之間是會互相影響的。
接下來我們進入本文重點,浮動與定位,以現(xiàn)在的布局來說,說白了就是浮動和定位,所以掌握了他們就是掌握了布局。
浮動float
float是個奇怪的東東,他最開始的提出是用作讓圖片浮動,以便文字能圍繞著圖片書寫,僅此而已!
所以我們來看看float這個讓人又愛又恨的家伙都干了些什么???
浮動元素會以莫種方式從文檔的正常流中刪除,他是他還是對文檔布局有一定影響
我們使用float浮動做了很多其本職工作以外的事情,于是我們會混淆,我們會回看不清float真正的面目。
浮動真正的意義在哪里呢?要知道這個問題的答案很簡單,假設現(xiàn)在CSS中沒有浮動(float)屬性,那么會變成一個什么樣子。
我們會發(fā)現(xiàn),目前流行采用浮動方法實現(xiàn)的無論是分欄布局,還是列表排列我們都可以用其他一些CSS屬性(不考慮table)代替實現(xiàn),
唯一一個實現(xiàn)不了的就是“文字環(huán)繞圖片”,我是想不出來能有什么方法可以讓文字環(huán)繞圖片顯示。好,這個替代不了的作用才是float真正的意義所在 ——張鑫旭
看看以上說法,他這個是非常有意義的,我們回過頭來一看,好像確實是這么回事的,float真的干了很多不該干的事情呢,所以我們的布局才有那么多莫名其妙的BUG。
float的內(nèi)幕
在詳細了解他之前,我們看一看包含塊(containing block),浮動元素的包含塊是最接近的塊級祖先元素:
- <p>dssd
- <img style=" float: left;" />
- ssd</p>
img的包含塊就是最近的p標簽,然后浮動元素會生成一個塊級框(inline元素也會),其實我們可以認為float就是不帶方向性的inline-block(事實上這是非常錯誤的認識)。
浮動元素的擺放有許多規(guī)則
① 浮動元素不能超過包含塊的邊距 ② 浮動元素的左右外邊距必須是源文檔中之前出現(xiàn)的左浮動元素的右外邊距(這句話我不太理解,我們下來看看) ③ 左浮動元素不會出現(xiàn)在右浮動元素的右邊 ④ 浮動元素的頂端不能比其父元素的內(nèi)頂端還高 ⑤ 浮動元素的頂端不能比之前所有浮動元素或者塊級元素的頂端更高 ⑥ 源文檔中一個浮動元素之前出現(xiàn)另一個元素,浮動元素的頂端不能比包含塊元素所生成框的任何行高還高 ⑦ .......
float我們都“比較”熟悉,所以對他的表現(xiàn)一般還是抓得準的,因為我們認為其實帶方向的inline-block,于是我們來看看浮動的破壞性。
inline boxes
行內(nèi)元素會生成一個叫行內(nèi)框的東西,前面我們已經(jīng)知道了
在containing boxes中,一個個inline boxes組成了line boxs(行框),這是浮動影響布局的關(guān)鍵box類型
content area 內(nèi)容區(qū)是一種圍繞文字看不見的box,大小就是font-size
在張鑫旭大哥的博客中有兩張很有意思的圖,我這里拿來主義搞來看看
按照此圖的研究,得出了以下結(jié)果:
圖片為一個inline boxes,文字也是inline boxes,行高(line boxes)是由其內(nèi)部***的inline boxes高度決定的所以行高這里便是圖片的高度 此時圖片與文字是同一box類型的元素,在同一行上,所以這里他們是對齊的 但是,float圖片后會有意想不到的變化 我們看到第二張圖,float破壞了圖片的inline boxes,圖片的inline boxes米有了!
當圖片失去inline boxes特性時就無法與inline boxes文字在一起了,他們已經(jīng)不是一個家庭的人了。。
圖片于是靠邊站了(float帶給元素的是降級?。?br />在CSS中所有高度都是由CSS模型產(chǎn)生的:box盒模型,line box 模型(line-height),inline boxes直接受控于line-height
真正的高度則是由每行的inline boxes組成的line boxes,而每行的line boxes高度垂直堆疊形成了containing box的高度
所以,沒了inline boxes的意思就是沒了高度,就跟男人沒有鳥是一個道理的。float就恰恰干了這種事情。。。。直接把人家的inline boxes給搞了,讓別人沒了高度
所以,float可以讓文字圍繞著圖片,因為圖片沒有了高度,但是他是有寬度的喲,元素沒有了高度就會造成另一個事實:父級塊級元素高度塌陷!我們想想塊級元素里面都沒有高度了,他塌陷是非常合理的啊!所以我們又會搞很多事情來清除浮動帶來的高度塌陷。所以我們一伙布局可以盡量的少使用float,讓他干他本質(zhì)的事情吧,因為想做太監(jiān)的人也不多。。。
Position登場
***,標題的主角終于登場了,寫到這里我其實都沒什么想說了,也不太說得出來了。。。。這就是舍本逐末吧!
首先position有幾個屬性呢?這個問題我承認有一點白癡。
static relative absolute fixed
其實對于position來說,他的東西是很簡單的,用來用去就那么幾個場景,操作的是塊級元素,很單一的。所以我們來看看本篇開始提出的問題
① relative與absolute的定位原點,無圖無真相,為了解決這個問題,我們寫個例子
- <!DOCTYPE html>
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title></title>
- <style>
- * { margin: 0; padding: 0; }
- </style>
- </head>
- <body>
- <h1>
- 塊級元素</h1>
- <div style="margin: 20px auto; width: 300px; height: 200px; background: gray; padding: 10px;
- position: relative;">
- <p style="background-color: Orange; width: 130px; height: 20px; margin: auto; position: absolute;">
- 刀狂劍癡葉小釵
- </p>
- </div>
- <h1>
- 行內(nèi)元素</h1>
- <div style="line-height: 12px; font-size: 12px; margin: 20px auto; background: gray; position: relative;">
- 刀狂劍癡葉小釵<span style=" font-size: 24px;">刀狂劍癡葉小釵</span>刀狂劍癡葉小釵
- </div>
- <p style=" position: absolute;">dssd
- <img style=" float: left;" />
- ssd</p>
- </body>
- </html>
可以看到,在不指定left與top的情況下,其默認是按照一般流的方式布局的。事實上我剛剛那句話是錯的!
對于absolute定位的元素,在默認情況下,他之前的對他沒有任何影響,但是他之后的東西我們可以看到,事實上會覆蓋他的位置的,其實也不是覆蓋他的位置了,說明他的原點就在那里只不過他就跟float元素似的沒有了高度,***連寬也沒有了。。。
② IE6中的fixed屬性,對于這個東東我還確實沒有做過處理,但是應該是使用js控制的,他這個就有個效果上的問題,肯定會發(fā)生抖動的。
但是經(jīng)過資料查詢發(fā)現(xiàn)IE6下用CSS也可以實現(xiàn)的
解決方案:CSS表達式應該避免,因為會很大的托壞效率,所以還是建議使用js
1.將body元素中添加_background-attachment:fixed; _background-image:url(about:blank);這兩個屬性,由于這個問題只在可恥的IE6下,所以就針對IE6寫個hack。
2.將需要用固定定位的元素中加上_position:absolute; _top:expression(offsetParent.scrollTop); _left:expression(offsetParent.scrollLeft);這個3個屬性。
3._top:expression((offsetParent.scrollTop)+50); 這樣后面的數(shù)字就是你需要的設置的距離。
這個問題,我個人認為意義真不大,因為我最近的公司直接拋棄IE8了何況IE6呢,中國的這些大爺還真不能太嬌慣了。。。
PS:一件可恥的事情就是,這種情況下margin: auto;可以實現(xiàn)垂直居中的目的。。
- <div style="margin: 20px auto; width: 300px; height: 200px; background: gray; padding: 10px;
- position: relative;">
- <div style="background-color: Orange; top: 0; bottom: 0; height: 20px; margin: auto 0;
- position: absolute;">
- 垂直居中
- </div>
- </div>
③ BFC(可恥的我***發(fā)現(xiàn)我沒有將他。。。)
什么是BFC(Block Formatting Context),簡單講,它是提供了一個獨立布局的環(huán)境,每個BFC都遵守同一套布局規(guī)則。例如,在同一個BFC內(nèi),盒子會一個挨著一個的排,
相鄰盒子的間距是由margin決定且垂直方向的margin會重疊。而float和clear float也只對同一個BFC內(nèi)的元素有效。
可悲的就是就算讀者這個解釋我依舊不知道他是干什么的。。。。這里我可恥的給跪了。。。留待以后解決吧。
結(jié)語
我發(fā)現(xiàn)自己是標題黨!前前后后扯了這么遠,居然***也沒有對題目做出正面回答,原因是什么這里我不說了,你懂的(見***段話)!
不正面回答其實原因有幾個,***是我還真沒完全理解題目要問什么,第二就是對于發(fā)散的那些名詞我可恥的也不是全懂。。。
所以我若是去面試鐵定悲劇,所以CSS還是需要好好的大力的學習?。。。。?!
原文鏈接:http://www.cnblogs.com/yexiaochai/archive/2013/05/20/3086697.html