我真的了解css嗎? 我這樣問自己。
我的思考和這幾天的學習來自於看了寒冬winter大神的這篇blog:談談面試與面試題 。說實話, 我邊看,腦袋里面邊翻篇一樣的過着我的那點css知識,看完了,整個人都不好了。
我覺得不是題目有多難,而是我之前從沒覺得我應該去仔細的學習和思考這些問題。於是,最近就仔細的學習了下,分析總結歸納在這,也方便以后進一步的學習和更加深刻的理解。
---------------------------------------------------------
| 1.一些自適應或垂直水平居中問題匯總;
| 2.Normal Flow
| 3.Containing Block
| 4.Margin Collapse
| 5.BFC
| 6.Baseline
| 7.Writing Mode
| 8.unicode-bidi
---------------------------------------------------------
如果你覺得自己的css水平不太過關,這里有個簡潔明了的layout教程,很易學易懂,可以先學習一下:學習CSS Layout
其實我覺得上面有些關鍵詞其實是非常息息相關的,這里只是分別理解下。
一、一些自適應或垂直水平居中問題
1.必備技能:水平居中
大家都知道哈,margin:0 auto;搞定:
1 #block{ 2 margin: 0 auto; 3 width: 100px; 4 height: 100px; 5 background-color: yellow; 6 }
不過可要看好喔,我沒有float也沒有absolute。然后我加了下float:left;不居中了,然后我又加了position:absolute;也不居中了。那如果我有absolute要怎么辦呢:
1 #block{ 2 position: absolute; 3 width: 100px; 4 height: 100px; 5 left: 50%; 6 top: 50%; 7 margin-left: -50px; 8 margin-top: -50px; 9 background-color: yellow; 10 }
上面的代碼在垂直方向上也居中了。
2.必備技能:文本垂直居中
div中的文字垂直居中於容器中:
1 css: 2 #block{ 3 font-size: 12px; 4 height: 36px; 5 line-height: 36px; 6 border: 2px #000 solid; 7 } 8 9 html: 10 <div id="block"> 11 我是文本,我要垂直居中在容器中啦! 12 </div>
若是多行的文本,這樣就會有問題了。前兩天看到有一個多行文本垂直居中的實現,是用display:table和display:table-cell一起來實現的,先看實現方法:
1 CSS: 2 3 #wrap{ 4 height: 400px; 5 display: table; 6 } 7 #block{ 8 vertical-align: middle; 9 display: table-cell; 10 font-size: 12px; 11 border: 2px #000 solid; 12 width: 500px; 13 }
原理是:CSS中的vertical-align屬性只會對擁有valign特性的(X)HTML標簽起作用。所以通過display:table;模擬<table>然后就可以使用vertical-align屬性了。
display:table要用在父元素上,display:table-cell要用到子元素上,像table布局一樣。
1 HTML: 2 <div id="wrap"> 3 <div id="block"> 4 <pre>我是文本,我要垂直居中在容器中啦! 5 6 </pre>我也是文本喔,我也要居中~~ 7 </div> 8 </div>
這里用<pre></pre>是為了模擬多行文本。
不過要郁悶的注意瀏覽器的兼容性:
3. 一個div里面兩個子div,其中一個定高100px;要另一個隨父元素適應高:
1 CSS: 2 #wrapper{ 3 position: relative; 4 width: 300px; 5 min-height: 500px; 6 border:2px #00f solid; 7 } 8 #fixed{ 9 width: 300px; 10 height:100px; 11 background-color: yellow 12 } 13 #fit{ 14 position: absolute; 15 background-color: pink; 16 width: 300px; 17 top: 100px; 18 bottom: 0; 19 }
絕對定位,有了top再加上bottom:0;然后它就填充了剩下的高度。
4. css3有了很好玩的東西,我覺得有了它,再也不用為各種布局煩惱了:flexbox-快速布局神器
我就嘗試了一個下面這樣的簡單三列布局:
1 2 #wrap{ 3 display: flex; 4 flex-flow:row wrap; 5 align-items:stretch; 6 justify-content:space-around; 7 width: 100%; 8 height: 300px; 9 border: 2px #000 solid; 10 } 11 #left{ 12 flex:1 200px; 13 background-color: red; 14 } 15 #right{ 16 flex:2 360px; 17 background-color: yellow; 18 } 19 #center{ 20 flex:1 250px; 21 background-color: blue; 22 }
不過,還是老問題,瀏覽器的兼容性永遠不像我們想的那么美好:
小結:這里我也就列出了基本的幾個,在自己對布局有了些理解后,一般的類似布局應該都不會有問題,后面碰到有挑戰的有趣的我再收集過來,如果有有趣的相關的問題,希望你與我分享喔。
二、Normal Flow
這里的normal flow(普通流)實際上為CSS的定位機制之一,其他兩個分別是如雷貫耳的浮動和絕對定位。
那具體什么是普通流呢?普通流就是在多數情況下呈現在web頁面上的方式,所有的HTML元素都在塊框(block boxes,塊級元素)或者行框(inline boxes,行內元素)中。
普通流就是這樣的過程:
1.對於塊級元素:
在對應的 block formatting context 中,塊級元素按照其在HTML中的順序,在其容器框里從左上角開始,從上到下垂直地依次分配空間、堆砌( stack ),並獨占一行,邊界緊貼父容器。兩相鄰元素間的距離由 margin 屬性決定,在同一個 block formatting context 中的垂直邊界將被重疊( collapse )。並且,除非創建一個新的 block formatting context ,否則塊級元素的寬度不受浮動元素的影響(這就是浮動元素能蓋在塊級元素上面的原因)。
2.對於行內元素:
在對應的 inline formatting context 中,行內元素從容器的頂端開始,一個接一個地水平排布。水平填充、邊框和邊距對行內元素有效。但垂直的填充、邊框和空白邊不影響其高度。一個水平行中的所有 inline box 組成了名為 line box 的矩形區域。 line box 的高度始終容下所有的 inline box ,並只與行高有關。 line box 的寬度受到父容器和浮動元素存在的影響(這就是文本環繞浮動元素)。如果 line box 的寬度小於容器, line box 的水平排布就取決於 text-align 。如果 line box 的寬度大於容器,則截斷 line box 並換行在新的 line box 中重新排布元素(截斷處不應用 padding 和 margin 值)。如果 line box 無法截斷,如單詞過長或者指定不換行,則會溢出容器。
3.對這些 block box 和 inline box 進行相對定位,即相對於已排布的位置進行偏移。元素在其中保留原來所占用的空間。
這有一篇文章,作者總結的非常好:CSS定位之一:普通流
三、Containing Block
containing block(包含塊),我理解就是定位參考框,與上面說的css的定位機制息息相關。元素一旦定義了定位顯示(static absolute relative)便具有了包含塊的性質,它所包含的定位元素都將以該包含塊為坐標系進行定位和調整。
舉個簡單明了的小例子:如果一個div定義了position:absolute;那么他會相對於誰定位呢?他會向上尋找父元素-》父元素的父元素....直到找到一個position:relative/fixed/absolute的父元素,然后來相對於它進行對位。
包含塊的建立有它的規則:
1.根元素作為初始包含塊,原諒后面兩句我實在翻譯不來,請戳下面手冊,自行理解;
2.對於position:relative和static的元素,他們的包含塊是由最近的塊元素祖先建立的;
3.對於position:fixed的元素,他的包含塊是由視口(viewport)建立的;
4.就像上面的小例子,position:absolute的元素他的包含塊由最近的不是position:static的祖先建立:
4.1 如果祖先是塊級元素,containing block 由祖先的 padding edge 形成。
4.2 如果祖先是內聯元素,containing block 取決於祖先的 direction 屬性。
w3c包含塊的定義:the definition of containing block
我覺得吧,既然簡單了解了containing block的工作原理,那么我覺得css另一定位機制position相關,也必須再來一遍了,張鑫旭大神的這一系列寫的蠻好,自行移步腦補:
CSS 相對|絕對(relative/absolute)定位系列(一)
CSS 相對|絕對(relative/absolute)定位系列(二)
CSS 相對|絕對(relative/absolute)定位系列(三)
CSS 相對|絕對(relative/absolute)定位系列(四)
CSS 相對|絕對(relative/absolute)定位系列(五)
四、Margin Collapse
W3C是這樣定義collapsing margins 的:‘這里的折疊意味着,相鄰的邊距(沒有非空內容,padding或border areas或clearance來分開他們)兩個或兩個以上的盒子(可以是相鄰或嵌套)相結合,形成一個單一的邊緣’。簡單來說,就是:
1.垂直的兩個正margin重合,會得到兩者中較大的margin,margin較小的元素的margin值就會被collapsed為0;
2.如果有一個margin為負值,那么正負相加得到最后的值;
3.如果兩個margin都是負的,那么絕對值較大的負值會被應用。
但是下面這些情況就不會發生margin collapse:
n.1 浮動元素;
n.2 position:absolute的元素;
n.3 inline-block元素;
n.4 元素的overflow值設為其他不是可見的值的時候,他不與他的子元素發生margin collapse;
n.5 被cleared的元素,他的top margin不與他父元素的bottom margin重疊;
n.6 根元素不發生重疊;
定義理解起來總是有點別扭,看些實例就好了,可以移步這里:Collapsing margins
五、BFC
什么是bfc呢,上面理解normal flow的時候總在說那個block formatting context,其實這就是bfc。就是說: 浮動元素和絕對定位元素,非塊級盒子的塊級容器(例如 inline-blocks, table-cells, 和 table-captions),以及overflow值不為“visiable”的塊級盒子,都會為他們的內容創建新的BFC(塊級格式上下文)。
通俗點理解,我覺得他就是塊框和行框的渲染上下文。
我們可以理解為一個箱子(實際上是看不見摸不着的),箱子里面物品的擺放是不受外界的影響的。轉換為BFC的理解則是:BFC中的元素的布局是不受外界的影響(我們往往利用這個特性來消除浮動元素對其非浮動的兄弟元素和其子元素帶來的影響。)並且在一個BFC中,塊盒與行盒(行盒由一行中所有的內聯元素所組成)都會垂直的沿着其父元素的邊框排列。
仔細讀過這個 CSS定位之一:普通流 應該就會理解了bfc到底是什么。normal flow中塊框和行框的表現還有margin collapse都跟他息息相關。
這里有較為容易理解的相關描述:深入理解BFC
六、Baseline
說到baseline我所想到的就是小學時候用的英語本上的四線三格,想着這個應該就更好理解了。我覺得baseline某種意義上是為完美主義者准備的:
我覺得去實現這種效果,最重要的是理解line-height,大多時候我們只知道:line-height 屬性設置行間的距離(行高)。
但我覺得應該了解再稍微多一點:
1. 該屬性會影響行框的布局。在應用到一個塊級元素時,它定義了該元素中基線之間的最小距離而不是最大距離。
2. line-height 與 font-size 的計算值之差(在 CSS 中成為“行間距”)分為兩半,分別加到一個文本行內容的頂部和底部。可以包含這些內容的最小框就是行框。
然后我們再去探究上圖的baseline是如何實現的(你需要足夠的耐心來讀完它):CSS基線之道
七、Writing Mode
css中的writing mode(書寫模式)取決於writing-mode、direction和text-orientation這些屬性。它僅適用於<text>元素,並被< tspan >,< TREF >,<altglyph >,和< textpath >子元素忽略。
MDN上是這樣說的:MDN writing-mode 手冊屬性后面有例,可以自己嘗試,便於理解。
中文參考手冊:書寫模式(writing-mode)
八、unicode-bidi
說實話,在這之前我真的不知道unicode-bidi是什么。好滴吧,他其實是用來設置文本的方向來的。
用它的時候我覺得有必要弄清楚direction屬性,direction是用來檢索或設置文本流的方向。
---->當指定一個內聯元素的unicode-bidi屬性為normal時,direction屬性不影響bidi重排序,即direction設置不生效。
手冊上說的蠻全,但是我理解的有限,於是我便自己寫了寫試試:
unicode-bidi:bidi-override
unicode-bidi: embed;
總結:我覺得這里 有些大多是定義相關的,手冊多讀讀多想想,理解了他們的工作機制就好了。我也要放在這里,自己常來讀,反復思考。也要時常提醒自己不要眼高手低,遇到問題養成仔細學習的習慣,be patient...