前端基礎篇之CSS世界

我想你天天寫css代碼有時候也會以爲很痛苦:這個佈局的css怎麼這麼難實現!我也常常會有這種感受,一個看似簡單的佈局老是要琢磨半天才能實現,偶爾還會出現一些怪異的超出理解的現象。這是由於咱們對css只是大概知道個形,並無看透css的本質。在同事的推薦下我閱讀了張鑫旭老師的《css世界》,才發現css跟想象中的不太同樣。本文爲《css世界》我的總結筆記,爲縮減篇幅丟棄了張老師冗餘的小幽默,丟掉了些含金量較低的章節內容,由於ie已經被淘汰出局,因此有關css兼容性的地方也所有忽略不記,同時對我的以爲不易理解的地方加上了一些本身的理解和驗證,因此錯誤之處還望指正。順便推薦個好用的在線代碼編輯工具,國內鏡像站點,方便各位對本文實例進行測試。另外本文會隨着做者對css的更深刻理解而逐步更新,但願到最後可以文如標題展示出真正的css世界。css

小剛老師

基本概念

這些基本概念有些可能不易理解但卻都很重要,若是看完仍是很不理解的話須要本身谷歌或百度,網上關於這些概念的文章很多。html

「流」又叫文檔流,是css的一種基本定位和佈局機制。流是html的一種抽象概念,暗喻這種排列布局方式好像水流同樣天然自動。「流體佈局」是html默認的佈局機制,如你寫的html不用css,默認自上而下(塊級元素如div)從左到右(內聯元素如span)堆砌的佈局方式。前端

塊級元素和內聯元素

這個你們確定都知道。css3

塊級元素是指單獨撐滿一行的元素,如div、ul、li、table、p、h1等元素。這些元素的display值默認是block、table、list-item等。git

內聯元素又叫行內元素,指只佔據它對應標籤的邊框所包含的空間的元素,這些元素若是父元素寬度足夠則並排在一行顯示的,如span、a、em、i、img、td等。這些元素的display值默認是inline、inline-block、inline-table、table-cell等。github

實際開發中,咱們常常把display計算值爲inline inline-block inline-table table-cell的元素叫作內聯元素,而把display計算值爲block的元素叫作塊級元素。web

width: auto 和 height: auto

widthheight的默認值都是auto面試

對於塊級元素,流體佈局之下width: auto自適應撐滿父元素寬度。這裏的撐滿並不一樣於width: 100%的固定寬度,而是像水同樣可以根據margin不一樣而自適應父元素的寬度。segmentfault

對於內聯元素,width: auto則呈現出包裹性,即由子元素的寬度決定。瀏覽器

不管內聯元素仍是塊級元素,height: auto都是呈現包裹性,即高度由子級元素撐開。

注意父元素height: auto會致使子元素height: 100%百分比失效。

css的屬性很是有意思,正常流下,若是塊級元素的width是個固定值,marginauto,則margin會撐滿剩下的空間;若是margin是固定值,widthauto,則width會撐滿剩下的空間。這就是流體佈局的根本所在。

外在盒子和內在盒子

外在盒子是決定元素排列方式的盒子,即決定盒子具備塊級特性仍是內聯特性的盒子。外在盒子負責結構佈局。

內在盒子是決定元素內部一些屬性是否生效的盒子。內在盒子負責內容顯示。

display: inline-table; 外在盒子就是inline,內在盒子就是table。外在盒子決定了元素要像內聯元素同樣並排在一排顯示,內在盒子則決定了元素能夠設置寬高、垂直方向的margin等屬性。以下圖

右側的table和左側的文字在一行排列(外在盒子inline的表現特徵),同時有擁有自定義寬度111px(內在盒子table能夠設置寬高)。

css權重和超越!important

曾經有道面試題把我難住了:

// 假設下面樣式都做用於同一個節點元素`span`,判斷下面哪一個樣式會生效
body#god div.dad span.son {width: 200px;}
body#god span#test {width: 250px;}
複製代碼

可憐當時作了三年前端的我居然還不知道css有權重😓

css選擇器權重列表以下:

權重值 選擇器
1,0,0,0 內聯樣式:style=""
0,1,0,0 ID選擇器:#idName{...}
0,0,1,0 類、僞類、屬性選擇器:.className{...} / :hover{...} / [type="text"] ={...}
0,0,0,1 標籤、僞元素選擇器:div{...} / :after{...}
0,0,0,0 通用選擇器(*)、子選擇器(>)、相鄰選擇器(+)、同胞選擇器(~)

之前想固然的覺得權重是十進制的,即十個class選擇器等於一個id選擇器,這是錯誤的。CSS權重進制在IE6爲256,後來擴大到了65536,而現代瀏覽器則採用更大的數量。因此咱們能夠忽略進制的問題,從高往低比較權重值。

若是權重是十進制的比較方式,則十一個class選擇器的權重高於一個ID選擇器。但經測試並不是如此:地址

能夠看到十一個class選擇器的樣式並無覆蓋一個id選擇器的樣式,由於:

當兩個權值進行比較的時候,是從高到低逐級將等級位上的權重值來進行比較的,而不是 1000個數 + 100個數 + 10個數 + 1個數 的總和來進行比較的,換句話說,低等級的選擇器個數再多也不會超太高等級的選擇器的優先級的。

正確規則:

  1. 先從高等級進行比較,高等級相同時,再比較低等級的,以此類推;
  2. 徹底相同的話,就採用 後者優先 原則;

所以上面那道的面試題比較應該是在第二等級id選擇器的比較就結束了:(#god + #test = 0,2,0,0) > (#god = 0,1,0,0);而上圖種例子中兩個權重分別是:(#test = 0,1,0,0) > (.test....test10 = 0,0,11,0),也是在第二等級id選擇器的比較時就結束了。因此之後比較權重,就先比較id選擇器個數,若是id同樣多,再比較class選擇器個數。哇,感受這能夠是一道專坑中文社區的面試題啊。

在css中,!important的權重至關的高。若是出現了!important,則無論權重如何都取有!important的屬性值。可是寬高有例外狀況,因爲寬高會被max-width/min-width覆蓋,因此!important會失效。

width: 100px!important;
min-width: 200px;
複製代碼

上面代碼計算以後會被引擎解析成:

width: 200px;
複製代碼

盒模型(盒尺寸)

元素的內在盒子是由margin boxborder boxpadding boxcontent box組成的,這四個盒子由外到內構成了盒模型。

IE模型: box-sizing: border-box 此模式下,元素的寬度計算爲border+padding+content的寬度總和。

w3c標準模型): box-sizing: content-box 此模式下,元素的寬度計算爲content的寬度。

因爲content-box在計算寬度的時候不包含border pading很煩人,並且又是默認值,業內通常採用如下代碼重置樣式:

:root {
  box-sizing: border-box;    
}
* {
  box-sizing: inherit;
}
複製代碼

內聯盒模型

內聯元素是指外在盒子是內聯盒子的元素。從表現來講,內聯元素的典型特徵就是能夠和文字在一行顯示。文字也是內聯元素。圖片、按鈕、輸入框、下拉框等替換元素也是內聯元素。內聯盒模型是指內聯元素包含的幾個盒子,理解記憶下面的幾個概念對css的深刻學習極其重要。

  1. 內容區域:本質上是字符盒子。在瀏覽器中,文字選中狀態的背景色就是內容區域。
  2. 內聯盒子:內聯盒子就是指元素的外在盒子是內聯的,會和其餘內聯盒子排成一行。
  3. 行框盒子:由內聯元素組成的每一行都是一個行框盒子。若是一行裏面沒有內聯元素如一個空的div標籤,則不會造成行框盒子。行框盒子由一個個內聯盒子組成,若是換行,那就是兩個行框盒子。好比一個包含了不少字符的換行的的p標籤,每一行都存在一個行框盒子。值得注意的是,若是給元素設置display: inline-block,則建立了一個獨立的行框盒子。line-height是做用在行框盒子上的,並最終決定高度。
  4. 包含盒子:就是包含塊。多行文字組成一個包含塊,一個包含塊有若干個行框盒子。
  5. 幽靈空白節點:內聯元素的每一個行框盒子前面有一個「空白節點」,這個「空白節點」不佔據任何寬度,沒法選中獲取,可是又實實在在存在,表現就如同文本節點同樣(本文中大量例子會用字母x模擬幽靈空白節點)。

替換元素

替換元素是指內容能夠替換的元素,實際上就是content box能夠被替換的元素。如存在src=""屬性的<img> <audio> <video> <iframe>元素和能夠輸入文本的<input> <select> <textarea>元素等。

全部替換元素都是內聯元素,默認display屬性是inlineinline-block(除了input[type="hidden"]默認display: none;)。

替換元素有本身默認的樣式、尺寸(根據瀏覽器不一樣而不一樣),並且其vertical-align屬性默認是bottom(非替換元素默認值是baseline)。

盒模型四大金剛

content

對於非替換元素如div,其content就是div內部的元素。 而對於替換元素,其content就是可替換部分的內容。

CSS中的content屬性主要用於僞元素:before/:after中,除了作字體庫或少寫個div,對於通常開發來講並沒有卵用。

padding

padding是四大金剛中最穩定的了,少見有什麼異常。儘管如此仍是有些須要注意的地方:

  1. 大部分狀況下咱們會將元素重置爲box-sizing: border-box,寬高的計算是包含了padding的,給人一種padding也是content box一部分的感受,好像line-height屬性也做用於padding上。但實際上,元素真正的內容的寬高只是content box的寬高,而line-height屬性是不做用於padding的。

  1. padding不可爲負值,可是能夠爲百分比值。爲百分比時水平和垂直方向的padding都是相對於父級元素寬度計算的。將一個div設爲padding: 100%就能獲得一個正方形,padding: 10% 50%能夠獲得一個寬高比 5:1 的矩形。
body {
  width: 400px;
}
.box {
  padding: 10% 50%;
}
複製代碼

  1. padding配合background-clip屬性,能夠製做一些特殊形狀:
/*三道槓*/
.icon1 {
  box-sizing: border-box;
  display: inline-block;
  width: 12px;
  height: 10px;
  padding: 2px 0;
  border-top: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  background: currentColor; /*注意若是此處背景顏色屬性用縮寫的話,須要放到其餘背景屬性的前面,不然會覆蓋前面的屬性值(此處爲background-clip)爲默認值*/
  background-clip: content-box;
}
/*雙層圓點*/
.icon2 {
  display: inline-block;
  width: 12px;
  height: 12px;
  padding: 2px;
  border: 2px solid currentColor;
  border-radius: 50%;
  background-color: currentColor;
  background-clip: content-box;
}

複製代碼

預覽以下:(currentColor是css中爲數很少的變量,指當前文字的顏色值,很是好用)

margin

  1. 做爲外邊距,margin屬性並不會參與盒子寬度的計算,但經過設置margin爲負值,卻能改變元素水平方向的尺寸:
<div>asdf</div>
<style> div { margin: 0 -100px; } </style>
複製代碼

此時div元素的寬度是比父級元素的寬度大200px的。可是這種狀況只會發生在元素是流佈局的時候,即元素width是默認的auto而且能夠撐滿一行的時候。若是元素設定了寬度,或者元素設置了float: left / position: absolute這樣的屬性改變了流體佈局,那麼margin爲負也沒法改變元素的寬度了。

  1. 塊級元素的垂直方向會發生margin合併,存在如下三種場景:
  • 相鄰兄弟元素之間margin合併;
  • 父元素margin-top和子元素margin-top,父元素margin-bottom和子元素margin-bottom
  • 空塊級元素自身的margin-topmargin-botom合併,例子以下。

要阻止margin合併,能夠:1. 把元素放到bfc中;2. 設置borderpadding阻隔margin;3. 用內聯元素(如文字)阻隔;4. 給父元素設定高度。

  1. margin的百分比值跟padding同樣,垂直方向的margin和水平方向上的同樣都是相對於父元素寬度計算的。
<div class="box">
  <div></div>
</div>
<style> .box{ overflow: hidden; background-color: lightblue; } .box > div{ margin: 50%; } </style>
複製代碼

此時 .box 是一個寬高比 2:1 的矩形,由於空塊級元素自身的垂直方向的margin發生了合併。

這裏父元素設置overflow: hidden是利用 bfc 的特性阻止子元素的margin和父元素合併,換成其餘 bfc 特性或者設置 1pxborder / padding都是能夠達到效果的。

  1. margin: auto能在塊級元素設定寬高以後自動填充剩餘寬高。margin: auto自動填充觸發的前提條件是元素在對應的水平或垂直方向具備自動填充特性,顯然默認狀況下塊級元素的高度是不具有這個條件的。典型應用是塊級元素水平局中的實現:
display: block;
width: 200px;
margin: 0 auto;
複製代碼

auto的特性是,若是兩側都是auto,則兩側均分剩餘寬度;若是一側margin是固定的,另外一側是auto,則這一側auto爲剩餘寬度。栗子:

這個特性不爲人知,且很實用。

除了水平方向,垂直方向的margin也能實現垂直居中,可是須要元素在垂直方向具備自動填充特性,而這個特性能夠利用position實現:

position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
width: 200px;
height: 200px;
margin: auto;
複製代碼

border

border主要做用是作邊框。border-style屬性的值有none/solid/dashed/dotted/double等,基本看名字就能猜出什麼來了:

border-width屬性的默認值是3px,是爲了照顧小弟border-style: double,你懂的。值得注意的是,border-color默認是跟隨字體的顏色,至關於默認設置了border-color: currentColor同樣。

border另外一廣受歡迎的功能就是圖形構建,特別是作應用普遍的三角形,其原理可看下圖的1-3:

div{
  float: left;
  margin: 20px;
}
div:nth-child(1){
  width: 20px;
  height: 20px;
  border: 20px solid;
  border-color: blue red orange green;
}
div:nth-child(2){
  width: 20px;
  height: 20px;
  border: 20px solid;
  border-color: blue transparent transparent transparent;
}
div:nth-child(3){
  border: 20px solid;
  border-color: blue transparent transparent transparent;
}
div:nth-child(4){
  border-style: solid;
  border-width: 40px 20px;
  border-color: blue transparent transparent transparent;
}
div:nth-child(5){
  border-style: solid;
  border-width: 40px 20px;
  border-color: blue red transparent transparent;
}
複製代碼

其實就是將其餘三個邊框的顏色設置透明,並把寬高設爲 0 。圖中4-5兩個圖形,是經過調整邊框寬度和顏色調整三角形的形狀,把最後一個圖的紅色改成藍色,則是一個直角三角形了。

好基友line-heightvertical-align

line-heightvertical-align是控制元素垂直對齊的兩大屬性,也是最難理解搞懂的屬性。

字母 x 的角色

在內聯元素的垂直方向對齊中,基線是最爲重要的概念。line-height定義的就是兩基線之間的距離,vertical-align的默認值就是基線。基線的定義則是字母 x 的下邊緣。

css中有個概念叫x-height,指的是小寫字母 x 的高度。vertical-align: middle對齊的就是基線往上1/2x-height高度的地方,能夠理解爲近似字母 x 的交叉點。

css中除了px/em/rem等,還有個單位是ex。指的就是小寫字母x的高度,即x-height。用處不大,再也不介紹。

line-height

  • line-height各種屬性值

normal: 默認值normal實際上是類型爲數值的變量,根據瀏覽器和字體'font-family'不一樣而不一樣,通常約爲 1.2 。

數值和百分比:最終會被計算爲帶單位的值,具體計算方法就是乘以字體大小font-size

長度值:就是100px這樣帶單位的值。

這幾類值的繼承特性不一樣:line-height是數值的元素的子元素繼承的就是這個數值,百分比/長度值繼承的都是計算後得出的帶單位的值(px)。

  • line-height的做用:

line-height屬性用於設置多行元素的空間量,如多行文本的間距。

對塊級元素來講,line-height決定了行框盒子的最小高度。注意是行框盒子的最小高度,而不是塊級元素的實際高度。(圖中兩個div行高同樣,div.one 的背景色區域就是行框盒子的高度,而 div.two 的背景區域則是實際高度,其行框盒子高度和 div.one 是同樣的。)

對於非替代的 inline 元素,它用於計算行框盒子的高度。此時內聯元素的行框盒子的高度徹底由line-height決定,不受其餘任何屬性的影響。

  • line-height實現垂直居中的本質:行距

行距是指一行文本和相鄰文本之間的距離。行距 = line-heightfont-size。行距具備上下等分的機制:意思就是文字上下的行距是同樣的,各佔一半,這也是line-height能讓內聯元素垂直居中的緣由。下圖中字母x上下行距各佔一半,共同撐起了div

下圖中和上圖惟一不一樣之處就是多了個display: inline-blockspan元素,可是此處的span元素並無影響div元素的高度,而只是靠着vertical-align: middle屬性將自身中心點對齊了字母x的交叉點實現垂直居中而已。div元素的高度仍然和上圖如出一轍,由字母x和行距共同撐起。此時若是刪除字母x,div的高度不變,由於span元素的行框盒子前會產生幽靈空白節點,而幽靈空白節點+行高也能撐起div

  • 內聯元素的大值特性
<div class="box">
  <span>asdf</span>
</div>
複製代碼

樣式1:此時 .box 高度是多少?

.box {
  line-height: 100px;
  background: lightgreen;
}
.box span {
  line-height: 30px;
}
複製代碼

樣式2:此時 .box 高度是多少?

.box {
  line-height: 30px;
  background: lightgreen;
}
.box span {
  line-height: 100px;
}
複製代碼

先說結論:不管內聯元素的line-height如何設置,最終父元素的高度都是數值大的那個line-height決定的。

樣式1中,span元素的行框盒子前存在一個幽靈空白節點,而這個幽靈空白節點的行高是100px;樣式2中,幽靈空白節點的行高是30px,可是這時span元素的行高是100px。兩種狀況其實同樣,取大值而已。

vertical-align

  • vertical-align的屬性值

線類: 如baseline(默認值) top middle bottombaseline使元素的基線與父元素的基線對齊,middle使元素的中部與父元素的基線往上x-height的一半對齊。top bottom使元素及其後代元素的底部與整行或整塊的底部對齊。)

文本類: text-top text-bottom(使元素的頂部與父元素的字體頂部對齊。)

上標下標: sub super(使元素的基線與父元素的下標基線對齊。)

數值: 20px 2em (默認值baseline至關於數值的 0 。使元素的基線對齊到父元素的基線之上的給定長度,數值正值是基線往上偏移,負值是往下偏移,藉此能夠實現元素垂直方向精確對齊。)

百分比: 20% (使元素的基線對齊到父元素的基線之上的給定百分比,該百分比是line-height屬性的百分比。)

  • vertical-align 的做用前提

vertical-align屬性起做用的前提必須是做用在內聯元素上。display計算值爲inline inline-block inline-table table-cell的元素。因此若是元素設置了float: left或者position: absolute,則其vertical-align屬性不能生效,由於此時元素的display計算值爲block了。

  • 好基友line-heightvertical-align和第三者幽靈空白節點的愛恨情仇

有時候會碰見下面這樣高度和設置不一致的狀況:

div的實際高度比設定的行高大了,爲何呢?

內聯元素的默認對齊方式是baseline,因此此時此時span元素的基線是和父元素的基線相對齊的,而此時父元素的基線在哪呢?

父元素的基線其實就是行框盒子前的幽靈空白節點的基線。把幽靈空白節點具象化爲字母x可能容易理解些:

因爲div行高是30px,因此字母xspan元素的高度都是30px。可是字母x的font-size較小,span元素的font-size較大,而行高同樣的狀況下font-size越大基線的位置越偏下,因此二者的基線不在同一水平線上。以下圖左邊部分:

因爲內聯元素默認基線對齊,因此字母xspan元素髮生了位移以使基線對齊,致使div高度變大。而此時字母x的半行距比span元素的半行距大,大出的部分就是div的高度增長的部分。

  • display: inline-block基線的不一樣之處

先看例子,圖中span元素設置了display: inline-block和寬高,從而撐起了父元素div的高度,但span自己並沒有margin屬性,那爲何底部和div下邊緣之間會有空隙呢?地址

這就要說到inline-block的不一樣之處了。一個設置了display: inline-block的元素:

  1. 若是元素內部沒有內聯元素,則該元素基線就是該元素下邊緣;
  2. 若是元素設置了overflowhidden auto scroll,則其基線就是該元素下邊緣;
  3. 若是元素內部還有內聯元素,則其基線就是內部最後一行內聯元素的基線。

知道了這點,那麼再回到上面的例子:

原來是第三者幽靈空白節點搞的鬼。此時span的行框盒子前,還存在一個幽靈空白節點。因爲span元素默認基線對齊,因此span元素的基線也就是其下邊緣是和幽靈空白節點的基線對齊的。從而致使幽靈空白節點基線下面的半行距撐高了div元素,形成空隙。以下圖:

若是span元素中存在內聯元素呢?

能夠看到,此時span元素下邊緣的空隙沒了,由於此時span元素的基線是內部最後一行內聯元素的基線。

值得一提的是,因爲替換元素內部不可能再有別的元素,因此其基線位置永遠位於下邊緣。

  • 解決問題

間隙產生本質上是由基線對齊引起的錯位形成的,源頭上是vertical-alignline-height共同形成的,因此要想解決這個問題,只要直接或間接改造兩個屬性中的一個就好了:

  1. 給元素設置塊狀化display: block使vertical-align屬性失效;
  2. 嘗試不一樣的vertical-align值如bottom/middle/top
  3. 直接修改line-height值;
  4. 若是line-height爲相對值如1.4,設置font-size: 0間接改變line-height
  • 彈框dialog

下面是張鑫旭大佬推薦的利用vertical-align實現的水平垂直居中彈框,可以理解的話就說明你已經徹底掌握了好基友和第三者的關係了。

<div class="container">
  <div class="dialog">自適應彈出層</div>
</div>
<style> .container{ position: fixed; top: 0; right: 0; bottom: 0; left: 0; background-color: rgba(0, 0, 0, .15); text-align: center; font-size: 0; white-space: nowrap; overflow: auto; } .container:after{ content: ''; display: inline-block; height: 100%; vertical-align: middle; } .dialog{ display: inline-block; width: 400px; height: 400px; vertical-align: middle; text-align: left; font-size: 14px; white-space: normal; background: white; } </style>
複製代碼

流的破壞

如今UI框架橫行的年代,咱們的css寫的愈來愈少了。這對於不少老鳥來講是件好事,可是對於初入前端的小白卻未必。由於寫的少了,就少了不少練手和總結的機會,對於不少樣式理解就不透徹。本章介紹的floatpositionBFC對於前端頁面佈局很是重要,但願諸位看官們靜下心來仔細研讀。

float屬性的特性

float屬性應該是css世界最使人意外的屬性了,倒不是由於他的表現,而是他的設計初衷居然只是爲了實現「文字環繞圖片」的效果。只不過由於float屬性的一些特性,才致使其被處處使用以至於產生了諸多不利於維護的頁面。 下面看看float屬性的特性:

  1. 包裹性:即此時元素width會像height同樣由子元素決定,而不是默認撐滿父元素。
  2. 塊狀化並格式化上下文:這個就是後面會講的BFC特性。塊狀是指元素設置float: left以後,其display的計算值就成了block。格式化上下文是指會建立一個BFC,這個後面會講。
  3. 沒有任何margin合併;
  4. 脫離文檔流:float設計的初衷就是爲了「文字環繞」效果,爲了讓文字環繞圖片,就須要具有兩個條件。第一是元素高度坍塌,第二是行框盒子不可與浮動元素重疊。而元素高度坍塌就致使元素後面的非浮動塊狀元素會和其重疊,因而他就像脫離文檔流了。

前三個特性都是正能量滿滿,可是最後一個特性卻給咱們開發者帶來了不少麻煩,須要用到clear來清除浮動。

clear的做用和不足

你們都知道clear: both能夠清除前面浮動元素的浮動,但實際上,他並非真的清除了浮動。

clear的定義是:元素盒子的邊不能與前面的浮動元素相鄰。也就是雖然浮動元素高度坍塌,可是設置了clear: both的元素卻將其高度視爲仍然佔據位置。

clear只能做用於塊級元素,而且其並不能解決後面元素可能發生的文字環繞問題。

BFC:塊級格式化上下文

  • 概念

BFC是一個獨立的渲染區域,只有Block-level box參與, 它規定了內部的Block-level Box如何佈局,而且與這個區域外部絕不相干。 BFC 就好像一個結界,結界裏面的東西不能影響外面的佈局,也就是說,BFC的子元素再翻江倒海,都不會影響外面的元素。 因此:

  1. BFC自己不會發生margin重疊。
  2. BFC能夠完全解決子元素浮動帶來的的高度坍塌和文字環繞問題。
  • BFC的建立方法
  1. 根元素;
  2. 浮動元素 (float不爲none的元素);
  3. 絕對定位元素 (元素的positionabsolutefixed);
  4. inline-blocks(元素的 display: inline-block);
  5. 表格單元格(元素的display: table-cellHTML表格單元格默認屬性);
  6. overflow的值不爲visible的元素;
  7. 彈性盒 flex boxes (元素的display: flexinline-flex);

BFC包含建立該上下文元素的全部子元素,但不包括建立了新BFC的子元素的內部元素。

  • 特性
  1. 內部的盒會在垂直方向一個接一個排列(能夠看做BFC中有一個的常規流);
  2. Box垂直方向的距離由margin決定。屬於同一個BFC的兩個相鄰Box的margin會發生重疊;
  3. 每個盒子的左外邊距應該和包含塊的左邊緣相接觸。即便存在浮動也是如此,除非子盒子造成了一個新的BFC。
  4. BFC就是頁面上的一個隔離的獨立容器,容器裏面的子元素不會影響到外面的元素,反之亦然;
  5. 計算BFC的高度時,考慮BFC所包含的全部元素,連浮動元素也參與計算;
  6. BFC的區域不會與float box重疊;

乍一看還挺多的,但真正要注意並用心理解的只有 3 4 6 。

特性 1 中內部的盒是指塊級盒。由於<html>根元素也是BFC,因此咱們日常寫的div p都是獨自佔一行。

特性 2 <html>是BFC,因此裏面的元素垂直方向的margin會發生摺疊。可是,直接子孫元素與該BFC上下邊界margin不能摺疊,保證了BFC內部的元素不會影響外部的元素。兩個上下相鄰的BFC之間折不折疊要看具體狀況,如display: inline-block float: left不會摺疊,而overflow: hidden則會摺疊。

特性 3 徹底解讀:

In a block formatting context, each box's left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch). This is true even in the presence of floats (although a box's line boxes may shrink due to the floats), unless the box establishes a new block formatting context (in which case the box itself may become narrower due to the floats).

網上不少翻譯成「每一個元素的margin box的左邊, 與包含塊border box的左邊相接觸」的,這樣的翻譯是不許確甚至錯誤的,曾給我形成莫大的困惑和迷茫(這翻譯太坑爹了一度讓我懷疑人生)。正確的翻譯是「每個盒子的左外邊距應該和包含塊的左邊緣相接觸」。

第一,包含塊未必就是父級元素。對於position: absolute來講,包含塊是指第一個positoin不爲static的祖先元素。

第二,BFC中的盒子應該與其自身的包含塊相接觸,而非與BFC盒子自己相接觸。

第三,BFC中的盒子是與其包含塊的 left edge 相接觸,而不是包含塊的 left-border 相接觸。left edge 正確的翻譯爲左邊緣。左邊緣多是content box的左邊緣(非絕對定位如position: relative float: left),也多是padding box的左邊緣(如絕對定位position: absolute position: fixed)。

理解了上面三點,其實特性 3 就是普通的流佈局和定位佈局默認貼着「左側」思想的總結。

如圖,aside元素的margin box的左邊距和BFC元素的左邊緣相接觸。而且因爲float box高度坍塌,main佔據了body所有空間而且和包含塊BFC盒子左邊緣相接觸(特性3「即便存在浮動也是如此」)。

特性 4 正是BFC存在的意義。它規定了BFC子元素不管margin-top: -10000px float: left 等都不會影響到BFC外部的元素的佈局。因此BFC是最好的清除浮動的方式,連浮動的文字環繞問題都能解決。

特性 5 BFC計算高度時包含浮動元素的高度。能夠利用BFC此特性解決浮動元素高度坍塌的問題。

特性 6 實現自適應兩欄佈局。此時main寬度是自適應的。

除了 BFC ,還有 IFC GFC FFC 等佈局,瞭解便可,想看點 這裏

絕對定位position: absolute

  • 定義

和浮動元素同樣,絕對定位也具備塊狀化、BFC、包裹性、脫離文檔流、沒有margin合併的特性。

但和浮動不一樣的是,絕對定位是徹底的脫離文檔流。你們還記得浮動產生的目的就是爲了實現文字環繞效果,因此浮動元素雖然脫離了文檔流,可是後面的文字仍是會環繞在浮動元素周圍。而絕對定位一但產生,就不會再對周圍元素產生任何影響。

並且二者包含塊不一樣,浮動元素包含塊只能是父級元素,絕對定位的包含塊則是距離最近的position不爲static的祖先元素。

  • 無依賴絕對定位

大多數用到絕對定位的時候,都是存在包含塊和left/top等方向屬性的。但其實position: absolute是很是獨立的css屬性,其樣式和行爲表現不依賴任何css屬性就能夠完成。

能夠看出,無依賴的position: absolute元素定位的位置和其自己無定位屬性時候的位置和display的值有關。若是元素在沒有position的狀況下是內聯元素,則和內聯元素在同一行顯示;若是元素在沒有position屬性的狀況下是塊級元素,則換行顯示。

無依賴絕對定位的實用性雖然還行,可是其功能卻徹底能夠用left/top實現。因此瞭解便可,若是有興趣能夠自行嘗試。

  • 絕對定位和overflow: hidden

其實一句話就能夠表示二者之間的關係:當overflow: hidden元素在絕對定位元素和其包含塊之間的時候,絕對定位元素不會被剪裁。

如下兩種絕對定位元素不會被剪裁:

<div style="overflow: hidden;">
  <img src="big.jpg" style="position: absolute;">
</div>
<div style="position: relative;">
  <div style="overflow: hidden;">
    <img src="big.jpg" style="position: absolute;">
  </div>    
</div>
複製代碼

如下兩種絕對定位元素會被剪裁:

<div style="overflow: hidden; position: relative;">
  <img src="big.jpg" style="position: absolute;">
</div>
<div style="overflow: hidden;">
  <div style="position: relative;">
    <img src="big.jpg" style="position: absolute;">
  </div>    
</div>
複製代碼
  • position: absolute的流體特性

當絕對定位元素的水平方向(left/right)或垂直方向(top/bottom)的兩個定位屬性同時存在的時候,絕對元素在該方向上便具備了流體特性。此時的width/height屬性具備自動撐滿的特性,和一個正常流的div元素的width屬性別無二致。如圖,設置了固定margin值的元素,寬高auto可以自動適應剩餘空間:

一樣的,設置了固定寬高的元素,若是margin: auto,則margin平分剩餘空間致使垂直水平居中:

層疊規則

層疊規則是指當網頁中的元素髮生層疊時侯的遵循的規則。

層疊上下文

層疊上下文好像是一個結界,層疊上下文內的元素若是跟層疊上下文外的元素髮生層疊,則比較該層疊上下文和外部元素的層疊上下文的層疊水平高低。

建立一個層疊上下文的方法就是給position值爲relative/aboslute/fixed的元素設置z-index不爲auto的值。

層疊上下文內元素的層疊水平以下圖:

  1. 最底層的border/background是指當前層疊上下文元素的邊框和背景色。z-index爲負值的元素在其之上。

以下圖所示.dad元素默認設置z-index: auto,沒有建立層疊上下文,此時其就是一個普通的塊級盒子,因此設置了z-index: -1.son元素跑到了爸爸身後看不見了。

而因爲.mom設置了z-index: 0,建立出了一個層疊上下文,因此.son元素就算設置了z-index: -1也跑不出老媽的視線。地址

  1. 當塊級元素和內聯元素髮生層疊,內聯元素居於塊級元素之上。以下圖:地址

  1. 普通定位元素層疊水平在普通元素之上。普通定位元素是指z-indexauto的定位元素。下圖span就是普通定位元素:地址

CSS3新增層疊上下文

CSS3帶來了不少新屬性,其中很不惹人注意的一點就是增長了不少會自動建立層疊上下文的屬性:

  1. 元素的opacity值不爲1,也就是透明元素;
  2. 元素的transform值不爲none
  3. 元素的filter值不爲none
  4. 元素的設置-webkit-overflow-scrolling: touch
  5. z-index不爲auto的彈性盒子的子元素;
  6. 元素的isolation值爲isolate
  7. 元素的mix-blend-mode值不爲normal
  8. 元素的will-change值爲opacity/transform/filter/isolation/mix-blend-mode中的一個。

這些屬性大都不支持z-index,因此他們都默認z-index: auto,跟普通定位元素層疊水平同樣,因此若是發生層疊會後來居上:地址

可是彈性盒子display: flex不一樣,彈性盒子的子元素支持設置z-index,且設置了數值的z-index也會自動建立層疊上下文。以下圖,能夠看到設置了z-index: 0的元素層疊水平更高。地址

文本控制

如下css屬性爲文本相關。

::first-letter 應用實例

::first-letter選中首個字符:地址

text-transform 應用

假設有個輸入框只能輸入大寫字母,那麼以下設置,輸入小寫字母出現的倒是大寫字母,可用於身份證輸入框或驗證碼輸入框等:

input {
    text-transform: uppercase;
  }
複製代碼

word-spacing 空格間隙

不要被表面意思誤導,word-spacing指的是字符「空格」的間隙。若是一段文字中沒有空格,則該屬性無效。下面代碼設定空格間隙是20px,也就是說空格如今佔據的寬度是原有的空格寬度+20px的寬度:

<p>我有空 格,我該死......</p>
<style> p { word-spacing: 20px; } </style>
複製代碼

white-space 空白處理

咱們都知道若是在html中輸入多個空白符,默認會被當成一個空白符處理,實際上就是這個屬性控制的:地址

  1. normal:合併空白符和換行符;
  2. nowrap:合併空白符,但不準換行;
  3. pre:不合並空白符,而且只在有換行符的地方換行;
  4. pre-wrap:不合並空白符,容許換行符換行和文本自動換行;

text-align: justify(本文重點例子!)

text-align: justify爲兩端對齊。除了實現文字的兩端對齊,還能用來作一些兩端對齊的佈局。下面介紹個兩端對齊佈局的實例:地址

因爲text-align: justify最後一行是左對齊,因此利用了三個空的i標籤模擬最後一行。雖然實現了兩端對齊,可是最後一行卻出現間隙。根據以前的經驗應該是vertical-alignline-height搞的鬼,咱們給i標籤加上outline並用字母 x 模擬幽靈空白節點,現形:地址

上圖分析:首先第一個i標籤基線與第二行的span標籤中的數字的基線對其,因此其位置在中間。其次最後一行的i標籤基線對齊幽靈空白節點字母x的基線,沒有錯位,因此此時最後一行的間隙高度就是字母x的高度。因此很容易想到把幽靈空白節點的行高設爲 0 來解決問題:地址

然而間隙雖然縮小了,可是仍是存在。此時因爲行高爲 0 ,幽靈空白節點也就是字母x在頁面中佔用的真實位置實際上是紅線所示。也就是說雖然字母 x 還顯示在頁面上,可是其真實高度已經爲0,此時其中線、上邊緣線、下邊緣線合一,都在紅線位置,其真實位置天然也就在紅線位置。然而其基線卻不會改變,在字母 x 下邊緣。

此時i標籤的基線發生錯位,位移到下面與幽靈空白節點基線對齊,致使產生了間隙。

因此只須要再改變i標籤的對齊方式,就能完全清除間隙:地址

此時i標籤的基線對齊其幽靈空白節點的下邊緣線,沒有了錯位,也就沒有了間隙。

若是改成vertical-align: top是同樣的,由於合一了。可是vertical-align: middle卻不行,由於此middle的位置是基線往上 1/2 個e-height的地方。

好吧本例結束了,沒想到解釋起來這麼複雜。雖然當下兩端對齊佈局使用這種方法已通過時了(沒 flex 實現起來簡單,更沒 grid 實現好),可是好好學習這個方法能加深對vertical-alignline-height的理解。

元素的顯示與隱藏

元素的顯示隱藏方法不少,不一樣方法的在不一樣的場景下頁面效果不一,對頁面的性能也有不一樣的影響。

元素隱藏方法總結:

  1. 若是但願元素不可見、不佔據空間、資源會加載、DOM 可訪問: display: none
  2. 若是但願元素不可見、不能點擊、但佔據空間、資源會加載,可使用: visibility: hidden
  3. 若是但願元素不可見、不佔據空間、顯隱時能夠又transition淡入淡出效果:地址
div{
  position: absolute;
  visibility: hidden;
  opacity: 0;
  transition: opacity .5s linear;
  background: cyan;
}
div.active{
  visibility: visible;
  opacity: 1;
}
複製代碼

這裏使用visibility: hidden而不是display: none,是由於display: none會影響css3的transition過渡效果。 可是display: none並不會影響cssanimation動畫的效果。

  1. 若是但願元素不可見、能夠點擊、佔據空間,可使用: opacity: 0
  2. 若是但願元素不可見、能夠點擊、不佔據空間,可使用: opacity: 0; position: absolute;
  3. 若是但願元素不可見、不能點擊、佔據空間,可使用: position: relative; z-index: -1;
  4. 若是但願元素不可見、不能點擊、不佔據空間,可使用: position: absolute ; z-index: -1;

display: nonevisibility: hidden的區別

  1. display: none的元素不佔據任何空間,visibility: hidden的元素空間保留;
  2. display: none會影響css3的transition過渡效果,visibility: hidden不會;
  3. display: none隱藏產生重繪 ( repaint ) 和迴流 ( relfow ),visibility: hidden只會觸發重繪;(迴流重繪知識點參考:真正理解重繪和迴流
  4. 株連性:display: none的節點和子孫節點元素全都不可見,visibility: hidden的節點的子孫節點元素能夠設置 visibility: visible顯示。visibility: hidden屬性值具備繼承性,因此子孫元素默認繼承了hidden而隱藏,可是當子孫元素重置爲visibility: visible就不會被隱藏。

若是面試問到這個問題,回答出來這四點應該是極好的。

彈性佈局

彈性佈局是指display: flexdisplay: inline-flex的佈局。注意,設爲彈性佈局之後,子元素的float、clear、vertical-align屬性都會失效。參見阮一峯大佬的 Flex 佈局教程

主要屬性應用以下:

彈性佈局實現兩端對齊尾行左對齊:地址

能夠看到 .container 容器中加了不少 i 空元素,這是爲了模擬項目佔位,也是彈性佈局實現兩端對齊的惟一不足之處~

網格佈局

網格佈局是目前最強大的 CSS 佈局方案。這裏總結了用 Grid 實現的經常使用 css 佈局:Grid網格佈局實例

更新說明

  • 更新了css權重和超越!important章節中權重部分的錯誤知識;(2019.10.16)
  • 更新了彈性佈局實現兩端對齊尾行左對齊實例;(2019.10.16)
  • 更新了text-align: justify連接中實例的顯示,固定了容器寬度;(2019.10.16)
相關文章
相關標籤/搜索