前言
雖然我CSS水平很水,但是水不是不學好的理由。
最近寒冬大哥針對面試發了一點“鬧騷”,我們來看看他的微博是怎麼說的呢?
normal flow、containing block、bfc、margin collapse,base line,writing mode,bidi,
這樣一路問下去的,奈何第一個問題(親我真的只問了position有哪些取值和行為啊)就悲劇了……
- position屬性常用的取值static、relative以及absolute和它們的基本行為是每個前端都應該掌握的。這包括relative和absolute的定位原點。
- fixed舊版本IE不支援,但是一個對技術有熱情的工程師也是應該瞭解的。
- 有過研究工程師可以知道absolute的containing block計算方式跟正常流不同,當然如果沒讀過標準的話,表述方式不一定是這樣。
- 對CSS布局有深入研究的工程師會知道position跟display、margin collapse、overflow、float這些特性相互疊加後的行為。
說句老實話,在狀態好的情況下,若是被問到這個題,我還能和他說道說道(很淺的那種),在狀態一般的情況下,我估計自己也直接悲劇了,那造成這個的是什麼原因呢?
答案毫無疑問的是我CSS水平是很水的,當項目經驗不夠的情況下,看書是不能記住一些東西的,所以還是需要項目實踐。
於是抱著我水我自豪的態度,我來試試他這道題水到底有多深,居然會刷掉一半的人。
思考過程
這個題若是單純提出position的幾個屬性,倒沒什麼問題,但我們來看看他的發散:
normal flow(一般流)
containing block(包含塊)
bfc(我深刻的意識到我一定見過他,但可恥的忘的一乾二淨了!)
margin collapse(搞不懂啊,應該是float引起的元素坍塌吧?)
base line (基準對齊)
......
後面的就完全沒有印象了,完了我想說,大哥我們能說中文嗎。。。至少給點解釋吧,對於css菜鳥來說看題目都很吃力的。。。。(掩面而泣)
驚歎
仔細閱讀題目並加以分析後,你會發現他這潭水是很深的,這道題快5分鐘可結束,慢可問上半個小時,而且問完了CSS都可以忽略不計了。。。
為什麼這麼說呢?
① position主要用於頁面配置,對css布局熟悉的朋友能很好的運用他布局,甚至拋棄float那個魔鬼(昨天我做了一道面試題就不用float布局,因為float本身是不用於布局的,這麼做的大哥,我不知道對不對,但我認為既然float不應該用於布局,我們便應該下意識的少用)。
② 在他發散過程中由將區塊層級元素與行內元素提到了,甚至細分到了行內元素的垂直對齊,更有可能發散到line-height上面,不可謂不深啊!
③ 在以上能做好的都已經不錯了,然後這道題更是可以細緻到各種應用細節,比如在IE7一下瀏覽器使用relative的z-index會有什麼問題,比如在布局上你會使用float嗎,float為什麼會引起元素坍塌,你如何解決元素坍塌......
......
然後的然後,他這道題真的發散開了就很大了,對於我這種水貨來說,看不懂啊,於是便只能在自己理解的方面做下說明,於是我們開始吧!
基本視覺格式化
凡是不能一蹴而就,我們一步步來,先瞭解點基礎的東西吧
我們在使用CSS過程中會發現很多“怪異”的現象,如果我們掌握了CSS中視覺表現模型是如何工作的了,那麼是不是會更加接近真理呢?
基本框
CSS假定每個元素都有一個基本框,這個矩形框便是我們所說的元素框(在CSS3出現後圓形、團原型也不是不可能哦)
各個元素框中心有一個內容區(content area),這個內容地區會有以下屬性:內邊距,外邊距,邊框。:
包含塊
因為每個元素都相對於其它包含塊擺放,所以包含塊就是一個元素的“布局上下文”,
刀狂劍癡葉小釵
在這個例子裡面,p的包含塊便是div(包含塊由最近的區塊層級元素擔當),所以p元素依賴於div布局,div依賴於body,行內元素擺放於包含塊沒什麼關係。
區塊層級元素
區塊層級元素很霸道,會獨佔一行作為自己的王國,一般一個元素的width被定義為從做內邊距到右內邊距的距離(IE6對盒模型解釋有誤)。margin、padding、width、height可以確定文檔布局。
多數情況下文檔高寬我們不太關心,寬度一般會鋪滿瀏覽器,高度會自己延生。
水平格式化
本來p元素寬度是200,但是由於padding問題寬度就變為220了,外邊距再延生40,所以整個寬度就是260了,這樣便隱式的增加了width的值!
但是,其右邊距卻不是20,因為CSS還有一個規則:。
所以我們要將一個元素置中會這樣設定
在寬度確定的情況下,做外邊距與右外邊距的值會被設定為相等的值(IE6忽視之,他會將之設定為0)。
負外邊距
由於margin可以被設定為負值,所以整個情況又會變得比較複雜,因為按照我們上面的規則,width便有可能超過其包含塊!!!
所以,我們平時操作負邊距時候,其實是增加了高寬,若是高寬確定的情況下,那邊是其他幾個屬性被增加了,帶來了元素移動的錯覺。
垂直格式化
區塊層級元素的高度預設由其內容決定,我們可以為元素顯示設定高度,但是這樣的話,元素框便不會自動增加了。
垂直置中
在水平情況下設定auto後,會取相同的值,當在垂直情況下,情況有所不同,,元素框失去了外邊距(定位元素有所不同)。
外邊距合并
外邊距合并的問題大家都知道,上下外邊距會發生合并現象,但是有種情況會讓事情變得比較複雜:
若是我們將代碼做一點改變:“將外層元素border”去掉;那麼。。
他這種合并方法就徹底讓我傻眼了。。。。。
行內元素
行內元素的布局比區塊層級元素要複雜,我們使用區塊層級元素布局,所以會比較重視,但是往往忽略行內元素的布局,這是會吃虧的。。。我們來看一個例子:
行內元素和區塊層級元素表現有很多不同,以上只是一個開始,我們來捋一捋,行內元素都有些什麼東東:
所以說行內元素坑坑爹呢,他的東西多著呢。。。
行內格式化
所有元素都有一個line-height屬性,這個值會顯著的影響行內元素顯示,行高由其組成元素和其他內容(如文本)高度確定。
注意:line-height實際隻影響行內元素和其他行內內容,不會影響到區塊層級元素(至少不直接影響)
建立框
首先,對於行內元素來說,font-size確定了內容區的高度,如果一個元素的font-size是15px,那麼內容區高度便是15px,因為所有元素的em框都是15px。
如果一個行內元素的font-size為15px,line-height為21px,相差的6px便是行間距,由此行內框形成:
但是有一個情境又會讓整個發展變得撲朔迷離:
刀狂劍癡葉小釵
對於匿名文本來說,內容高度沒有變化,半間距為0,但是對於span來說,line-height減去font-size後我們得到的半間距為-6,所以其行內框依舊是12px,內容區卻大了出來。
vertical-align
margin的方式不能垂直對齊,行內元素便提供了vertical-align屬性:
補充知識(http://www.zhangxinxu.com)
浮動和定位
參考:http://www.zhangxinxu.com/
經過以上的知識,我們知道了,所有文件項目都有一個框!被稱為,它描述了一個元素在文檔布局中所佔空間大小,所以框與框之間是會互相影響的。
接下來我們進入本文重點,浮動與定位,以現在的布局來說,說白了就是浮動和定位,所以掌握了他們就是掌握了布局。
浮動float
float是個奇怪的東東,他最開始的提出是用作讓圖片浮動,以便文字能圍繞著圖片書寫,!
所以我們來看看float這個讓人又愛又恨的傢伙都幹了些什嗎???
浮動元素會以莫種方式從文檔的正常流中刪除,他是他還是對文檔布局有一定影響
浮動真正的意義在哪裡呢?要知道這個問題的答案很簡單,假設現在CSS中沒有浮動(float)屬性,那麼會變成一個什麼樣子。
我們會發現,目前流行採用浮動方法實現的無論是分欄布局,還是列表排列我們都可以用其他一些CSS屬性(不考慮table)代替實現,
唯一一個實現不了的就是“文字環繞圖片”,我是想不出來能有什麼方法可以讓文字環繞圖片顯示。好,這個替代不了的作用才是float真正的意義所在——張鑫旭
看看以上說法,他這個是非常有意義的,我們回過頭來一看,好像確實是這麼回事的,float真的幹了很多不該乾的事情呢,所以我們的布局才有那麼多莫名其妙的BUG。
float的內幕
在詳細瞭解他之前,我們看一看包含塊(containing block),浮動元素的包含塊是最接近的塊級祖先元素:
img的包含塊就是最近的p標籤,然後浮動元素會產生一個塊級框(inline元素也會),其實我們可以認為float就是不帶方向性的inline-block()。
浮動元素的擺放有許多規則
後面還有幾個規則呢,我這裡都不想寫了,說實話我看著這麼多規則第一映像就不想用這個屬性了。。。
float我們都“比較”熟悉,所以對他的表現一般還是抓得準的,因為我們認為其實帶方向的inline-block,於是我們來看看浮動的破壞性。
inline boxes
行內元素會產生一個叫行內框的東西,前面我們已經知道了
在containing boxes中,一個個inline boxes組成了line boxs(行框),這是浮動影響布局的關鍵box類型
content area 內容區是一種圍繞文字看不見的box,大小就是font-size
在張鑫旭大哥的部落格中有兩張很有意思的圖,我這裡拿來主義搞來看看
按照此圖的研究,得出了以下結果:
當圖片失去inline boxes特性時就無法與inline boxes文字在一起了,他們已經不是一個家庭的人了。。
圖片於是靠邊站了(float帶給元素的是降級啊)
在CSS中所有高度都是由CSS模型產生的:box盒模型,line box 模型(line-height),inline boxes直接受控於line-height
真正的高度則是由每行的inline boxes組成的line boxes,而每行的line boxes高度垂直堆疊形成了containing box的高度
所以,沒了inline boxes的意思就是沒了高度,就跟男人沒有鳥是一個道理的。float就恰恰幹了這種事情。。。。直接把人家的inline boxes給搞了,讓別人沒了高度
所以,float可以讓文字圍繞著圖片,因為圖片沒有了高度,但是他是有寬度的喲,元素沒有了高度就會造成另一個事實:!我們想想區塊層級元素裡面都沒有高度了,他塌陷是非常合理的啊!所以我們又會搞很多事情來清除浮動帶來的高度塌陷。所以我們一夥布局可以盡量的少使用float,讓他幹他本質的事情吧,因為想做太監的人也不多。。。
Position登場
最後,標題的主角終於登場了,寫到這裡我其實都沒什麼想說了,也不太說得出來了。。。。這就是捨本逐末吧!
首先position有幾個屬性呢?這個問題我承認有一點白癡。
其實對於position來說,他的東西是很簡單的,用來用去就那麼幾個情境,操作的是區塊層級元素,很單一的。所以我們來看看本篇開始提出的問題
① relative與absolute的定位原點,無圖無真相,為瞭解決這個問題,我們寫個例子
刀狂劍癡葉小釵
可以看到,在不指定left與top的情況下,其預設是按照一般流的方式布局的。!
對於absolute定位的元素,在預設情況下,他之前的對他沒有任何影響,但是他之後的東西我們可以看到,事實上會覆蓋他的位置的,其實也不是覆蓋他的位置了,說明他的原點就在那裡只不過他就跟float元素似的沒有了高度,最後連寬也沒有了。。。
② IE6中的fixed屬性,對於這個東東我還確實沒有做過處理,但是應該是使用js控制的,他這個就有個效果上的問題,肯定會發生抖動的。
但是經過資料查詢發現IE6下用CSS也可以實現的
解決方案:
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); 這樣後面的數字就是你需要的設定的距離。
這個問題,我個人認為意義真不大,因為我最近的公司直接拋棄IE8了何況IE6呢,中國的這些大爺還真不能太嬌慣了。。。
PS:一件可恥的事情就是,這種情況下margin: auto;可以實現垂直置中的目的。。
③ BFC(可恥的我最後發現我沒有將他。。。)
相鄰盒子的間距是由margin決定且垂直方向的margin會重疊。而float和clear float也只對同一個BFC內的元素有效。
尼瑪可悲的就是就算讀者這個解釋我依舊不知道他是幹什麼的。。。。這裡我可恥的給跪了。。。留待以後解決吧。
結語
我發現自己是標題黨!前前後後扯了這麼遠,居然最後也沒有對題目做出正面回答,原因是什麼這裡我不說了,你懂的()!
不正面回答其實原因有幾個,第一是我還真沒完全理解題目要問什麼,第二就是對於發散的那些名詞我可恥的也不是全懂。。。
所以我若是去面試鐵定悲劇,所以CSS還是需要好好的大力的學習啊!!!!!