CSS Why,csswhy
前面的話
在CSS學習目錄中,已經詳細地介紹了CSS如何使用。知其然,還要知其所以然。本文將介紹CSS各部分出現的原因,僅限個人理解,如有不妥,歡迎交流
Why CSS
早期的大多數網站標記幾乎完全由表格和font元素組成,且對於所要表現的內容不能傳達任何實際含義,使文檔可用性降低,且不易於維護。於是1995年,W3C發布了CSS草案,試圖解決結構與樣式混雜的問題
1、如果考慮結構與樣式徹底分離,且樣式表可能用於多個HTML檔案,使用外部樣式表
2、如果樣式表僅用於當前頁面,且減少HTTP請求數量,使用內部樣式表
3、如果只是想為單個元素指定一些樣式,可以使用HTML的style屬性來設定一個行間樣式
Why 選取器
通過CSS選取器,向文檔中的一組元素類型應用某些規則
1、通配選取器選擇所有元素
2、元素選取器按照HTML標籤來選擇元素
3、類別選取器通過定義類名來選擇一類元素
4、ID選取器選擇特定ID的元素
5、屬性選取器根據元素的屬性及屬性值來選擇元素
6、後代選取器通過HTML層級關係來選擇元素
7、分組選取器將具有相同規則的元素合并設定
Why 層疊
CSS(cascading style sheets)中文翻譯過來是層疊樣式表,最基本的一個特性就是層疊。衝突的聲明通過層疊進行排序,由此確定最終的文檔表示
在下面的例子,元素選取器div和類別選取器.test都可以選擇出<div class="test"></div>,這就發生了衝突。由於類別選取器的特殊性大於元素選取器,所以通過層疊進行排序,最終該元素的樣式為{height: 200px;} ,如果去掉 .test{height: 200px;} 這條規則,則元素的樣式為{height: 100px;}
<style>div{height: 100px;}.test{height: 200px;} </style><div class="test"></div>
Why Hack
CSS Hack是實現瀏覽器樣式相容的兜底辦法,能不用就盡量不要使用。但是,針對一些瀏覽器的bug,比如老版本IE的bug,有時使用CSS Hack是不得已而為之的做法
比如,對於IE6-瀏覽器主要使用底線_和中劃線-這兩種字元實現hack。如下所示,在IE6瀏覽器中,div的文本顏色為藍色,其他瀏覽器則為紅色
div{
color:red;
_color:blue;
}
Why 偽類和虛擬元素
個人認為,偽類和虛擬元素是對HTML元素的一個擴充,通過它們可以豐富元素的樣式表現
偽類即假的類,類似於通過添加一個實際的類來達到效果,比如常見的hover滑鼠移至上方效果
a:hover{background-color:lightblue;}/*淺藍,滑鼠移至上方*/
虛擬元素即假的元素,類似於通過添加一個實際的元素才能達到。當然,添加的不是元素,而是產生內容,產生內容主要指由瀏覽器建立的內容,比如:before和:after
Why 單位
從廣義上講,單位是一個相對概念,其為事物座標系中的座標軸中能構成個體的抽象概念。長度單位是指丈量空間距離上的基本單元,是CSS為了規範長度而制定的基本單位。
為了更好的丈量和表示頁面的長度,CSS規定了絕對長度單位、字型相關的長度單位、視口相關的長度單位
【絕對長度單位】
絕對長度單位代表一個物理測量,包括像素px(pixels)、英寸in(inches)、英寸in(inches)、英寸in(inches)、英寸in(inches)、1/4毫米q(quarter-millimeters)、點pt(points)、派卡pc(picas)
在web上,像素px是典型的度量單位,很多其他長度單位直接映射成像素。最終,他們被按照像素處理
1in = 2.54cm = 96px 1cm = 10mm = 96px/2.54 = 37.8px1mm = 0.1cm = 3.78px1q = 1/4mm = 0.945px1pt = 1/72in = =0.0139in = 1/72*2.54cm = 1/72*96px = 1.33px1pc = 12pt = 1/6in = 1/6*96px = 16px
【字型相關的長度單位】
字型相關的相對長度單位包括em、ex、ch、rem
em表示元素的font-size屬性的計算值,如果用於font-size屬性本身,相對於父元素的font-size;若用於其他屬性,相對於本身元素的font-size
rem是相對於根項目html的font-size屬性的計算值
ex是指所用字型中小寫x的高度。但不同字型x的高度可能不同。實際上,很多瀏覽器取em值一半作為ex值
ch與ex類似,被定義為數字0的寬度。當無法確定數字0寬度時,取em值的一半作為ch值
【視口相關的長度單位】
視口相關的長度值相對於初始包含塊的大小。當初始包含塊的寬高變化時,他們都會相應地縮放。然而,當根項目的overflow值為auto時,任何捲軸會假定不存在
關於視口相關的單位有vh、vw、vmin、vmax4個單位
vh:布局視口高度的 1/100vw:布局視口寬度的 1/100vmin:布局視口高度和寬度之間的最小值的 1/100vmax:布局視口高度和寬度之間的最大值的 1/100
Why 盒模型
盒模型是CSS布局的基礎,它描述了一個元素在文檔布局中所佔的空間大小。而且,每個框影響著其他元素框的位置和大小
【box-sizing】
在CSS中盒模型被分為兩種,第一種是W3C的標準模型,第二種是IE怪異盒模型。不同之處在於後者的寬高定義的是可見元素框的尺寸,而不是元素框的內容區尺寸。目前對於瀏覽器大多數元素都是基於W3C標準的盒模型,但對於表單form中的部分元素還是基於IE的怪異盒模型,如input裡的radio、checkbox、button等元素,如果給其設定border和padding它們也只會往元素盒內延伸
在W3C的標準模型下,寬度和高度僅僅包含了內容寬度,除去了邊框和內邊距兩個地區,這樣為web設計師處理效果帶來了不少麻煩。為瞭解決這個問題,CSS3新增了一個盒模型屬性box-sizing,能夠事先定義盒模型的尺寸解析方式
Why margin重疊
在網頁布局中,因為margin重疊的原因,我們常常把margin作為一個“問題樣式”而盡量少地使用它。但實際上,它是在很大的作用的
HTML文檔建立的初衷只是用來展示資訊的。HTML文檔只使用預設樣式的前提下,如果上下margin不發生重疊,則會出現以下幾個問題:1、連續段落或列表之類,如果沒有margin重疊,首尾項間距會和其他兄弟元素呈現1:2的關係,排版不自然;2、web中任何地方嵌套或直接放入任何裸div,都會影響原生的布局,與web設計原則相違背;3、遺落的空的任意多個p標籤,會影響原來的閱讀排版
所以,我們要善用重疊,可以在清單項目中同時使用margin-top和margin-bottom。這樣,使頁面結構更具有健壯性,最後一個元素移除或位置調換,都不會破壞原生的布局
【-webkit-margin-collapse】
-webkit-margin-collapse: <collapse>(預設重疊) | <discard>(取消) | <separate>(分隔)
該屬性用於設定margin是否重疊,作用於發生margin重疊的兩個元素之一。如果,兩個都使用該屬性,一個設定為discard,一個設定為separate,則最終效果為重疊collase
Why auto
理解視覺格式化,可以確定得到的效果是應該顯示的正確效果,還是瀏覽器安全色性的bug。視覺格式化中比較重要的一個概念就是auto,auto值是用來彌補實際值與所需總和的差距
【為什麼區塊層級元素的寬度預設撐滿父級元素】
因為區塊層級元素width預設值為auto,而margin、border和padding預設值都為0,依據區塊層級元素框的水平總和等於父元素的width的計算公式,區塊層級元素的寬度width預設等於包含塊也就是父元素的寬度width
【為什麼區塊層級元素設定寬度後,預設居左顯示】
因為為區塊層級元素設定寬度後,而margin、border和padding預設值都為0,依據區塊層級元素框的水平總和等於父元素的width的計算公式。 這種情況,叫做格式化屬性過分受限(overconstrained),此時總會把margin-right強製為auto,從而使居左顯示,margin-right來補足剩餘的寬度
【為什麼固定寬度的區塊層級元素設定margin:auto可以實現水平置中顯示】
同樣依據區塊層級元素框的水平總和等於父元素的width的計算公式,border、padding為0,設定固定寬度後,margin-left和margin-right平分剩餘的寬度
【為什麼區塊層級元素的高度預設為元素自身高度】
個人認為,這與瀏覽器先從左至右,再從上到下的渲染機制有關。這種渲染機制決定了寬度值是確定的,高度值是元素自身高度。如果高度值也是確定的,即視口高度,則每渲染一個區塊層級元素,就要佔滿整個螢幕大小,無疑是一個災難;所以,瀏覽器在保證足夠寬的情況下,就需要盡量小的高度,這個盡量小的高度就是元素自身高度
【為什麼區塊層級元素設定margin:auto無法實現垂直置中顯示】
瀏覽器對於margin-top、margin-bottom為auto時,會自動將其重設為0。如果要實現垂直置中,可以利用calc()自己計算,如果height為100px,border為0,padding為10px,包含塊的高度為200px,則margin-top = calc((200px - 100px - 10px -10px) / 2)
[注意]要考慮垂直方向上的margin重疊問題
【為什麼圖片設定margin:auto不可以實現水平置中顯示】
圖片無法水平置中,類似於區塊層級元素無法垂直置中。因為圖片的寬度width預設是自身寬度,左右margin設定為auto,會被重設為0;如果要實現水平置中顯示,把圖片display設定為block即可
Why 行高和垂直對齊
普通流下,區塊層級元素的布局主要基礎是盒模型,而行內元素(包括inline-block元素)的布局則主要依靠line-height和vertical-align
line-height行高是指文本行基準之間的距離。vertical-align用來設定垂直對齊,所有垂直對齊的元素都會影響行高
【為什麼inline-block元素會存在底部空隙】
inline-block元素在區塊層級元素中留空隙是因為映像的預設垂直對齊是基準對齊(基準對齊在原理上相當於映像底邊與匿名文本大寫英文字母X的底邊對齊);而匿名文本是有行高的,繼承父級元素設定的行高,預設為normal(chrome下為font-size的1.334倍),所以X的底邊距離行框的底邊有一段距離,這段距離就是映像留出的空隙
於是,解決這個問題有以下3種解決辦法
1、設定display:block,因為垂直對齊只能作用於替換元素和行內元素,更改為區塊層級元素,會使垂直對齊失效
2、設定父級的line-height: 0,這樣使匿名文本與行框的距離為0
3、設定vertical-align為top/middle/bottom
【為什麼行內元素垂直margin無效】
因為行內元素垂直布局主要是通過行高line-height和垂直對齊vertical-align來影響的,垂直margin並不會影響它們,所以不會影響垂直布局。而在顯示方式,margin地區不會顯示元素背景,所以也不會影響自身元素的顯示,所以行內元素垂直margin無效
Why 浮動
浮動最早的使用是出自<img src="#" align="right">,用於文本環繞圖片的排版處理。如今浮動作為CSS中常用的布局方式
浮動元素脫離普通流,然後按照指定方向,向左或者向右移動,碰到父級邊界或者另外一個浮動元素停止。浮動具有以下4個特性:
1、浮動流:正常流中元素一個接一個排列;浮動元素也構成浮動流
2、塊級框:浮動元素自身會產生一個塊級框,不論這個元素本身是什麼,使浮動元素周圍的外邊距不會合并
3、包裹性:浮動元素的包含塊是指其最近的塊級祖先元素,後代浮動元素不應該超出包含塊的上、左、右邊界。若不設定包含塊的高度,包含塊若浮動,則包含塊會延伸,進而包含其所有後代浮動元素;若不設定包含塊的寬度,包含塊若浮動,則包含塊寬度由後代浮動元素撐開
4、破壞性:浮動動元素脫離正常流,並破壞了自身的行框屬性,使其包含塊元素的高度塌陷,使浮動框旁邊的行框被縮短,從而給浮動框留出空間,行框圍繞浮動框重新排列
【為什麼需要清除浮動】
清浮動,其實就是解決浮動元素的包含塊高度塌陷的問題
對於標準瀏覽器來說,清浮動其實就兩種方法,一種是在浮動元素下面添加新元素設定clear屬性;另一種是觸發包含塊的BFC,使其包含浮動元素
Why BFC
經常地,我們使用BFC來清除浮動,但實際上BFC還有很多其他的用途
在解釋BFC之前,先說一下文檔流。我們常說的文檔流其實分為定位流、浮動流和普通流三種。而普通流其實就是指BFC中的FC。FC是formatting context的首字母縮寫,直譯過來是格式化上下文,它是頁面中的一塊渲染地區,有一套渲染規則,決定了其子項目如何布局,以及和其他元素之間的關係和作用。常見的FC有BFC、IFC,還有GFC和FFC。BFC是block formatting context,也就是塊級格式化上下文,是用於布局塊級盒子的一塊渲染地區
滿足下列條件之一就可觸發BFC
1、根項目,即HTML元素
2、float的值不為none
3、overflow的值不為visible
4、display的值為inline-block、table-cell、table-caption
5、position的值為absolute或fixed
BFC是頁面上的一個隔離的獨立容器,容器裡面的子項目不會影響到外面元素,反之亦然。經常使用BFC實現以下3個用途
1、阻止元素被浮動元素覆蓋
<說明>通過改變內容為BFC背景為紅色的盒子的屬性值,使其成為BFC,以此阻止被綠色的浮動盒子覆蓋
2、包含浮動元素
<說明>通過改變高度塌陷的黑色邊框的盒子的屬性值,使其成為BFC,以此來包含綠色的浮動盒子
3、屬於同一個BFC的兩個相鄰塊級子項目的上下margin會發生重疊,(設定writing-mode:tb-rl時,水平margin會發生重疊)。所以當兩個相鄰塊級子項目分屬於不同的BFC時可以阻止margin重疊
<說明>淡紅色背景的塊級盒子二的外麵包一個div,通過改變此div的屬性使紅色盒子與綠色盒子分屬於兩個不同的BFC,以此來阻止margin重疊
Why 定位
CSS有三種基本的布局機制:普通流、浮動流和定位流。利用定位,可以準確地定義元素框相對於其正常位置應該出現的位置,或者相對於父元素、另一個元素甚至瀏覽器視窗本身的位置
當元素絕對位置時,會從文檔流中完全刪除。元素位置相對於最近的已定位祖先元素,如果元素沒有已定位的祖先元素,那麼它的位置相對於初始包含塊document,其邊界根據位移屬性放置。元素定位後產生一個塊級框,而不論原來它在正常流中產生何種類型的框。定位元素不會流入其他元素的內容,反之亦然
當元素相對定位時,它會從其正常位置移走,不過,原來所佔的空間並不會因此消失。相對定位元素,會為其所有子項目建立一個新的包含塊。這個包含塊對應於該元素原本所在的位置
固定定位與絕對位置很類似,元素會完全從文檔流中去除,但固定元素的位移是相對於視窗
【為什麼clip屬性無效】
絕對位置或固定定位元素才可以使用clip屬性。絕對位置元素常配合clip屬性達到元素隱藏的效果
.hide{ position:absolute; clip: rect(0,0,0,0);}
【為什麼靜態位置的元素會發生跳動】
對於置中對齊的行內元素來說,將元素設定為absolute或fixed會發生靜態位置跳動問題。而relative或static則不會有此問題。這是因為元素預設的置中對齊是元素的內容中線對應父級區塊層級元素中線,而當元素絕對位置或固定定位之後,定位元素左邊界將與其父級區塊層級元素的中線對齊
【為什麼overflow屬性會失效】
當overflow在絕對位置元素和其包含塊之間時,絕對位置元素不會被父級overflow屬性剪裁
解決辦法就是有兩種, 一種是讓overflow元素自身成為包含塊,給父級設定position:absolute或fixed或relative;另一種是設定overflow元素的子項目為包含塊,在絕對位置元素和overflow元素之間增加一個元素並設定position:absolute或fixed或relative
Why z-index
對於所有定位,最後都不免遇到兩個元素試圖放在同一位置上的情況。顯然,其中一個必須蓋住另一個。但,如何控制哪個元素放在上層,這就引入了屬性z-index
利用z-index,可以改變元素相互覆蓋的順序。這個屬性的名字由座標系統得來,其中從左向右是x軸,從上到下是y軸。從螢幕到使用者是z軸。在這個座標系中,較高z-index值的元素比較低z-index值的元素離使用者更近,這會導致較高z-index值的元素覆蓋其他元素,這也稱為堆疊或疊放
對於CSS2.1來說,頁面元素的堆疊規則如所示
對於定位元素(position不是static的元素)來說,不設定z-index或z-index相同時,後面元素覆蓋前面元素;對於處於同一堆疊上下文中的同一層次的元素來說,預設z-index較大值覆蓋z-index較小值
一旦為一個元素指定了z-index值(不是auto),該元素會建立自己的局部堆疊上下文。這意味著,元素的所有後代相對於該祖先元素都有其自己的疊放順序
[注意]auto值指當前堆疊上下文中產生的棧層次與其父框的層次相同,這個框不會建立新的局部疊放上下文。z-index:auto與z-index:0的值相等,但z-index:0會建立新的局部堆疊上下文
CSS3的出現對過去的很多規則發出了挑戰。對層疊上下文z-index的影響更加顯著,主要包括以下8個屬性
1、z-index值不為auto的flex項(父元素display:flex | inline-flex)
2、元素的透明度opacity值不等於1
3、元素的變形transform不是none
4、元素的mix-blend-mode值不是normal
5、元素的filter值不是none
6、元素的isolation值是isolate
7、will-change指定的屬性值為上面的任意一個
8、元素的-webkit-overflow-scrolling設定為touch
設定以上8個屬性的任意一個,都和設定absolute類似,層疊上下文z-index會生效
Why 溢出
當一個元素固定為某個特定大小,但內容在元素中放不下。此時可以利用溢出(overflow)來控制這種情況
overflow-x和overflow-y的屬性原本是IE瀏覽器獨自拓展的屬性,後來被CSS3採用,並標準化。overflow-x主要用來定義對水平方向內容溢出的剪下,而overflow-y主要用來定義對垂直方向內容溢出的剪下
當overflow設定為auto或scroll或hidden時可以觸發BFC,使得overflow可以實現一些相關應用
【為什麼會出現捲軸】
捲軸和overflow是緊密相關的。只有當父級的overflow的值是auto或scroll,並且元素的內容超出元素地區時,才有可能出現捲軸
無論什麼瀏覽器,預設捲軸均來自<html>,而不是<body>。因為<body>元素預設有8px的margin。若捲軸來自<body>元素,則捲軸與頁面則應該有8px的間距,實際上並沒有間距,所以捲軸來自<html>元素
chrome/firefox/IE瀏覽器的預設捲軸寬度是17px,safari瀏覽器則是21px
Why flex
CSS3引入了一種新的布局模型——flex布局。flex是flexible box的縮寫,一般稱之為彈性盒模型。flex布局提供一種更加有效方式來進行容器內的項目布局,以適應各種類型的顯示裝置和各種尺寸的螢幕
伸縮容器預設存在兩條軸: 水平的主軸(main axis) 和垂直的側軸(cross axis)
[注意]主軸方向不一定是水平的,它主要取決於justify-content屬性
主軸起點叫main start,主軸終點叫main end;側軸起點叫cross start,側軸終點叫cross end
伸縮項目預設沿主軸排列。單個伸縮項目佔據的主軸空間叫main size ,佔據的側軸空間叫cross size
[注意]伸縮項目的main size和cross size主要由寬度或高度決定
利用flex可以簡單的實現各種布局形式,詳細情況移步至此
Why 多欄版面配置
浮動作為常見排版方式只是不得已為之的行為,最初只是用來實現圖文混排,也最好只用於圖文混排,而不是更複雜的布局結構
定位用於對元素的精準定位布局
個人認為,flex布局提供的靈活布局方式可以用來替代被泛濫使用的浮動布局
而多欄版面配置則提供了類似於報紙、雜誌類的排版方式
CSS新增了多欄版面配置特性,可以讓瀏覽器確定何時結束一列和開始下一列,無需任何額外的標記。簡單來說,就是CSS3多欄版面配置可以自動將內容按指定的列數排列,這種特性實現的布局效果和報紙、雜誌類排版非常相似