各位週末結束後都累了吧,那我們一起來看看【寒冬】的面試題吧(據說阿里的喲)

範大腳腳發表於2017-12-14
前言
雖然我CSS水平很水,但是水不是不學好的理由。
最近寒冬大哥針對面試發了一點“鬧騷”,我們來看看他的微博是怎麼說的呢?
複製程式碼
面試的時候問個css的position屬效能刷掉一半的人這是啥情況……其實這問題我本來打算的是可以順著一路扯到
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),這個內容區域會有以下屬性:內邊距,外邊距,邊框。我這裡又引用下其他大哥的圖吧:
 
包含塊
因為每個元素都相對於其它包含塊擺放,所以包含塊就是一個元素的“佈局上下文”,
複製程式碼
1 <body>
2     <div>
3         <p>
4             刀狂劍痴葉小釵</p>
5     </div>
6 </body>
7 </html>
複製程式碼
在這個例子裡面,p的包含塊便是div(包含塊由最近的塊級元素擔當),所以p元素依賴於div佈局,div依賴於body,行內元素擺放於包含塊沒什麼關係。
塊級元素
塊級元素很霸道,會獨佔一行作為自己的王國,一般一個元素的width被定義為從做內邊距到右內邊距的距離(IE6對盒模型解釋有誤)。margin、padding、width、height可以確定文件佈局。
多數情況下文件高寬我們不太關心,寬度一般會鋪滿瀏覽器,高度會自己延生。
水平格式化
<p style=”width: 200px; padding: 10px; margin: 20px;”>
    刀狂劍痴葉小釵</p>
本來p元素寬度是200,但是由於padding問題寬度就變為220了,外邊距再延生40,所以整個寬度就是260了,這樣便隱式的增加了width的值!
但是,其右邊距卻不是20,因為CSS還有一個規則:正常流塊級元素的margin,width,padding,border之和必須等於包含塊的內容區域,所以右邊距會被重置為auto。
所以我們要將一個元素居中會這樣設定
<div style=”margin: 0 auto;”></div>
在寬度確定的情況下,做外邊距與右外邊距的值會被設定為相等的值(IE6忽視之,他會將之設定為0)。
負外邊距
由於margin可以被設定為負值,所以整個情況又會變得比較複雜,因為按照我們上面的規則,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>
所以,我們平時操作負邊距時候,其實是增加了高寬,若是高寬確定的情況下,那邊是其他幾個屬性被增加了,帶來了元素移動的錯覺。
垂直格式化
塊級元素的高度預設由其內容決定,我們可以為元素顯示設定高度,但是這樣的話,元素框便不會自動增加了。
垂直居中
在水平情況下設定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>
外邊距合併
外邊距合併的問題大家都知道,上下外邊距會發生合併現象,但是有種情況會讓事情變得比較複雜:
複製程式碼
<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”去掉;那麼。。
他這種合併方法就徹底讓我傻眼了。。。。。
行內元素
行內元素的佈局比塊級元素要複雜,我們使用塊級元素佈局,所以會比較重視,但是往往忽略行內元素的佈局,這是會吃虧的。。。我們來看一個例子:
<div style=”margin: 20px auto; width: 300px; height: 200px; background: gray; padding: 10px; “>
    <span style=” border: 1px dashed orange;”>
        刀狂劍痴葉小釵刀狂劍痴葉小釵刀狂劍痴葉小釵刀狂劍痴葉小釵刀狂劍痴葉小釵刀狂劍痴葉小釵刀狂劍痴葉小釵刀狂劍痴葉小釵刀狂劍痴葉小釵
    </span>
</div>
行內元素和塊級元素表現有很多不同,以上只是一個開始,我們來捋一捋,行內元素都有些什麼東東:
複製程式碼
匿名文字:
未被包含在行內元素的字串
em框:
em框在字型中定義,也被稱為字元狂
內容區:
內容區可以是元素中各個字元的em框串在一起構成的框,也可以由元素中字元字形描述的框。
行間距:
font-size與line-height之差/2便是行間距
行內框:
通過向內容區增加行間距來描述,對於非替換元素行內框剛好等於line-height
行框:
這是包含該行中出現的行內框的最高點和最低點的最小框,意思是行框上邊界要高於最高行內框,最低也要大於最低的行內框
複製程式碼
所以說行內元素坑坑爹呢,他的東西多著呢。。。
行內格式化
所有元素都有一個line-height屬性,這個值會顯著的影響行內元素顯示,行高由其組成元素和其他內容(如文字)高度確定。
注意:line-height實際隻影響行內元素和其他行內內容,不會影響到塊級元素(至少不直接影響)
建立框
首先,對於行內元素來說,font-size確定了內容區的高度,如果一個元素的font-size是15px,那麼內容區高度便是15px,因為所有元素的em框都是15px。
如果一個行內元素的font-size為15px,line-height為21px,相差的6px便是行間距,由此行內框形成:
但是有一個場景又會讓整個發展變得撲朔迷離:
<div style=”line-height: 12px; font-size: 12px; margin: 20px auto;  background: gray;”>
    刀狂劍痴葉小釵<span style=” font-size: 24px;”>刀狂劍痴葉小釵</span>刀狂劍痴葉小釵
</div>
對於匿名文字來說,內容高度沒有變化,半間距為0,但是對於span來說,line-height減去font-size後我們得到的半間距為-6,所以其行內框依舊是12px,內容區卻大了出來。
vertical-align
margin的方式不能垂直對齊,行內元素便提供了vertical-align屬性:
複製程式碼
top
將元素行內框的頂端與包含該元素的行框的頂端對齊
bottom
將元素行內框的低端與包含該元素的行框的底端對齊
text-top
將元素行內框的頂端與父元素內容區的頂端對齊
text-bottom
將元素行內框的底端與父元素內容區的底端對齊
middle
將元素行內框的垂直中點與父元素基線上0.5ex處一點對齊
複製程式碼
補充知識(http://www.zhangxinxu.com)
英語本子的各條線
浮動和定位
參考:http://www.zhangxinxu.com/
經過以上的知識,我們知道了,所有文件元素都有一個框!被稱為元素框,它描述了一個元素在文件佈局中所佔空間大小,所以框與框之間是會互相影響的。
接下來我們進入本文重點,浮動與定位,以現在的佈局來說,說白了就是浮動和定位,所以掌握了他們就是掌握了佈局。
浮動float
float是個奇怪的東東,他最開始的提出是用作讓圖片浮動,以便文字能圍繞著圖片書寫,僅此而已!
所以我們來看看float這個讓人又愛又恨的傢伙都幹了些什麼???
浮動元素會以莫種方式從文件的正常流中刪除,他是他還是對文件佈局有一定影響
我們使用float浮動做了很多其本職工作以外的事情,於是我們會混淆,我們會回看不清float真正的面目。
浮動真正的意義在哪裡呢?要知道這個問題的答案很簡單,假設現在CSS中沒有浮動(float)屬性,那麼會變成一個什麼樣子。
我們會發現,目前流行採用浮動方法實現的無論是分欄佈局,還是列表排列我們都可以用其他一些CSS屬性(不考慮table)代替實現,
唯一一個實現不了的就是“文字環繞圖片”,我是想不出來能有什麼方法可以讓文字環繞圖片顯示。好,這個替代不了的作用才是float真正的意義所在
——張鑫旭
看看以上說法,他這個是非常有意義的,我們回過頭來一看,好像確實是這麼回事的,float真的幹了很多不該乾的事情呢,所以我們的佈局才有那麼多莫名其妙的BUG。
float的內幕
在詳細瞭解他之前,我們看一看包含塊(containing block),浮動元素的包含塊是最接近的塊級祖先元素:
<p>dssd
<img style=” float: left;” />
ssd</p>
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,行高(line boxes)是由其內部最高的inline boxes高度決定的所以行高這裡便是圖片的高度
此時圖片與文字是同一box型別的元素,在同一行上,所以這裡他們是對齊的
但是,float圖片後會有意想不到的變化
我們看到第二張圖,float破壞了圖片的inline boxes,圖片的inline boxes米有了!
當圖片失去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有幾個屬性呢?這個問題我承認有一點白痴。
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>
        行內元素</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控制的,他這個就有個效果上的問題,肯定會發生抖動的。
但是經過資料查詢發現IE6下用CSS也可以實現的
解決方案: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); 這樣後面的數字就是你需要的設定的距離。
這個問題,我個人認為意義真不大,因為我最近的公司直接拋棄IE8了何況IE6呢,中國的這些大爺還真不能太嬌慣了。。。
PS:一件可恥的事情就是,這種情況下margin: auto;可以實現垂直居中的目的。。
複製程式碼
<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(可恥的我最後發現我沒有將他。。。)
什麼是BFC(Block Formatting Context),簡單講,它是提供了一個獨立佈局的環境,每個BFC都遵守同一套佈局規則。例如,在同一個BFC內,盒子會一個挨著一個的排,
相鄰盒子的間距是由margin決定且垂直方向的margin會重疊。而float和clear float也只對同一個BFC內的元素有效。
尼瑪可悲的就是就算讀者這個解釋我依舊不知道他是幹什麼的。。。。這裡我可恥的給跪了。。。留待以後解決吧。
結語
我發現自己是標題黨!前前後後扯了這麼遠,居然最後也沒有對題目做出正面回答,原因是什麼這裡我不說了,你懂的(見第一段話)!
不正面回答其實原因有幾個,第一是我還真沒完全理解題目要問什麼,第二就是對於發散的那些名詞我可恥的也不是全懂。。。
所以我若是去面試鐵定悲劇,所以CSS還是需要好好的大力的學習啊!!!!!
您可以考慮給小釵發個小額微信紅包以資鼓勵 
本文轉自葉小釵部落格園部落格,原文連結:http://www.cnblogs.com/yexiaochai/archive/2013/05/18/3085536.html如需轉載請自行聯絡原作者


相關文章