CSS進階指南

一 前言

要想掌握CSS部分的內容其實並不容易,儘管你已經閱讀過至關多的關於CSS的書籍,可是仍是免不了去網上搜索相關的知識擴大你對CSS內容的掌握。在網絡上查找最好的地方固然是CSS官網文檔,不過英文版的官方文檔將很大一部分人拒之門外,而中文版的博客上五花八門的只是零散又不權威,很容易將人帶入歧途,浪費時間。筆者寫這篇文章,摘錄博客上總結的CSS知識,同時參考CSS官方文檔,盡力保證其正確性。但願能節省開發者查閱的時間,提升效率。若有錯誤的地方,還請你們指出~一塊兒學習,共同進步。javascript

二 正文

DOM脫離文檔流

什麼是文檔流

指語言文本從左到右,從上到下顯示,這是傳統HTML文檔的文本佈局。
脫離文檔流便是元素打亂了這個排列,或是從排版中拿走。css

什麼狀況下會脫離文檔流

浮動(float)、絕對定位(absolute)、固定定位(fixed)三種方式定位會脫離文檔流。html

浮動

浮動元素會脫離文檔流並向左/向右浮動,直到碰到父元素或者另外一個浮動元素。float 屬性定義元素在哪一個方向浮動。以往這個屬性總應用於圖像,使文本圍繞在圖像周圍,不過在 CSS 中,任何元素均可以浮動。java

特色:jquery

  1. 浮動元素會生成一個塊級框,而不論它自己是何種元素
  2. 若是浮動非替換元素,則要指定一個明確的寬度;不然,它們會盡量地窄
  3. 沒有實際高度,浮動會致使父元素高度坍塌

須要注意:
向左浮動,方塊從右往左滑過來,若是某一行空間不夠(基於父容器的寬度),那麼這個塊會沿着最右邊的塊的下邊沿水平划過來,最後看卡到哪裏就中止。
圖片描述segmentfault

left4在第一行left3後面寬度不夠,換行成第二行。在left2後面寬度不夠,只能在left1後面。right1天然是從第二行開始查找位置,很幸運第二行如今惟一的元素#left4右面空間足夠,放置便可。right2在第二行中沒有足夠的位置,換行成第三行,找到空餘位置插入。瀏覽器

定位

圖片描述
absolute的基準元素是 static 定位之外的第一個父元素,而fix的基準元素是瀏覽器窗口。position的值爲absolute、fixed的元素脫離文檔流,static、relative沒有脫離文檔流。網絡

absolute定位結果

分兩種狀況來考慮:佈局

第一種:元素的某條邊沒有設置定位屬性(left/top/right/bottom)
這個時候,這一邊就會將absolute塊(包括外邊距)按流式佈局(正常佈局)來排列,固然這個流式佈局就會受到內邊距padding的影響了。學習

<!DOCTYPE html>
<html>
  <head>
      <meta charset="utf-8">
      <!--<script type="text/javascript" src='jquery-1.9.1.js'></script>-->
      <style>
    *{
      margin: 0;
      padding: 0;
      text-align: right;
      color: #FFF;
    }
    #container{
      position: absolute;
      left: 20px;
      margin-top: 10px;
      width: 600px;
      height: 600px;
      background-color: green;
    }
    #big{
      position: relative;
      left: 20px;
      margin-top: 40px;
      width: 300px;
      height: 300px;
      background-color: #000;
    }
    #normal{
      position: static;
      margin-left: 20px;
      margin-top: 50px;
      width: 200px;
      height: 200px;
      background-color: #aaa;
    }
    #middle{
      position: absolute;
      margin-left:0px;
      margin-top:20px;
      width: 100px;
      height: 100px;
      background-color: #333;
    }
    </style>
  </head>
  <body>
    <div id="container">
          <div id="big">
            <div id="normal">
              <div id="middle">
                middle</div>normal
              </div>big
            </div> container
      </div>
    </div>
</body>
</html>

圖片描述

第二種,元素的某條邊設置了定位屬性(left/top/right/bottom)
這時候,這一邊就會被做爲脫離文檔流的邊來處理,會相對於 static 定位之外的第一個父元素(的邊框)進行定位,若是這時候設置了外邊距,那麼這一邊相對於基準元素的偏移=定位值(left/top/right/bottom)+ 外邊距。

<!DOCTYPE html>
<html>
  <head>
      <meta charset="utf-8">
      <!--<script type="text/javascript" src='jquery-1.9.1.js'></script>-->
      <style>
    *{
      margin: 0;
      padding: 0;
      text-align: right;
      color: #FFF;
    }
    #container{
      position: absolute;
      left: 20px;
      margin-top: 10px;
      width: 600px;
      height: 600px;
      background-color: green;
    }
    #big{
      position: relative;
      left: 20px;
      margin-top: 40px;
      width: 300px;
      height: 300px;
      background-color: #000;
    }
    #normal{
      position: static;
      margin-left: 20px;
      margin-top: 50px;
      width: 200px;
      height: 200px;
      background-color: #aaa;
    }
    #middle{
      position: absolute;
      left:0px;
      margin-left:0px;
      margin-top:20px;
      width: 100px;
      height: 100px;
      background-color: #333;
    }
    </style>
  </head>
  <body>
    <div id="container">
          <div id="big">
            <div id="normal">
              <div id="middle">
                middle</div>normal
              </div>big
            </div> container
      </div>
    </div>
</body>
</html>

圖片描述

對於浮動與定位的位置優先級:
(fixed == absolute) > float > relative > static
理解爲同時設置了position:absolute和float:right忽略float:right
堆疊優先級:

1. 定位元素z-index>=0時爲(fixed == absolute == relative)  > static,z-index < 0時(fixed == absolute == relative)  < static。
理解爲兄弟元素一個設置了position:relative,另外一個設置了position:static,當relative元素z-index爲>=0時,不管static元素設置多少都在relative下面。若是relative設置z-index<0,則論static取什麼值relative都會在static下面。

2. 定位元素z-index>=0時(fixed == absolute == relative)  > float,z-index < 0時(fixed == absolute == relative)  < float。
理解爲兄弟元素一個設置了position:relative,另外一個設置了float:left,當relative元素z-index爲>=0時,不管float元素設置多少都在relative下面。若是relative設置z-index<0,則不管float的z-index設置多少relative都會在float下面。

3. float > static始終成立。由於z-index只有在定位元素上才起做用,定位元素包括fixed、absolute、relative。

4. fixed == absolute == relative,比較堆疊順序直接比較z-index大小便可。

參考資料:
【1】浮動:https://www.cnblogs.com/chuaW...
【2】定位:https://segmentfault.com/a/11...

垂直邊距合併

什麼是垂直邊距合併

當兩個垂直外邊距相遇時,它們將造成一個外邊距。合併後的外邊距的高度等於兩個發生合併的外邊距的高度中的較大者。

什麼狀況下會發垂直邊距合併

1. 只針對塊級元素
2. 正常文檔流

注意:合併行爲只適用於外邊距,若是元素有內邊距和邊框,它們絕對不會合並。

狀況1:同一層級垂直方向上盒子的相遇

<html>
<head>

<style type="text/css">
* {
  margin:0;
  padding:0;
  border:0;
}

#d1 {
  width:100px;
  height:100px;
  margin-top:20px;
  margin-bottom:20px;
  background-color:red;
}

#d2 {
  width:100px;
  height:100px;
  margin-top:10px;
  background-color:blue;
}

</style>
</head>

<body>

<div id="d1">
</div>

<div id="d2">
</div>

<p>請注意,兩個 div 之間的外邊距是 20px,而不是 30px(20px + 10px)。</p>
</body>
</html>

圖片描述

(注意:圖片中的「內容區域」應該是包括content和padding)
demo1

狀況2:存在嵌套關係

 父子節點都是沒有脫離文檔的兩種定位(static、relative)的外邊距(margin)會合並,顯示效果以最大的那個外邊距爲準:父元素的第一個子元素的上邊距margin-top若是碰不到有效的border或者padding.就會不斷一層一層的找本身「領導」(父元素,祖先元素)的麻煩。

沒有給父元素設置內邊距或者有效的邊框的狀況下:

<html>
<head>
<style type="text/css">
* {
  margin:0;
  padding:0;
  border:0;
} 
#outer {
  width:300px;
  height:300px;
  background-color:red;
  margin-top:20px;
} 
#inner {
  width:50px;
  height:50px;
  background-color:blue;
  margin-top:10px;
}
</style>
</head>
<body>
<div id="outer">
  <div id="inner">
  </div>
</div>
<p>註釋:請注意,若是不設置 div 的內邊距和邊框,那麼內部 div 的上外邊距將與外部 div 的上外邊距合併(疊加)。</p>
<p>爲父元素例子中的middle元素增長一個border-top或者padding-top便可</p>
</body>
</html>

圖片描述

邊距合併實際例子:

<!DOCTYPE html>
<html>
  <head>
      <meta charset="utf-8">
      <!--<script type="text/javascript" src='jquery-1.9.1.js'></script>-->
      <style>
    *{
      margin: 0;
      padding: 0;
      text-align: right;
      color: #FFF;
    }
    #container{
      position: absolute;
      left: 20px;
      margin-top: 10px;
      width: 600px;
      height: 600px;
      background-color: green;
    }
    #big{
      position: relative;
      left: 20px;
      margin-top: 40px;
      width: 300px;
      height: 300px;
      background-color: #000;
    }
    #normal{
      position: static;
      margin-left: 20px;
      margin-top: 50px;
      width: 200px;
      height: 200px;
      background-color: #aaa;
    }
    #middle{
      position: absolute;
      margin-left:0px;
      margin-top:20px;
      width: 100px;
      height: 100px;
      background-color: #333;
    }
    </style>
  </head>
  <body>
    <div id="container">
          <div id="big">
            <div id="normal">
              <div id="middle">
                middle</div>normal
              </div>big
            </div> container
      </div>
    </div>
</body>
</html>

圖片描述

結果:normal和big都沒有脫離文檔流,發生嵌套時,最終確認上邊距爲50px.

解決方案:在包含塊上設置邊框或者內邊距,會使其子元素的外邊距包含在包含塊內。

解決這種狀況下邊距合併:

<!DOCTYPE html>
<html>
  <head>
      <meta charset="utf-8">
      <!--<script type="text/javascript" src='jquery-1.9.1.js'></script>-->
      <style>
    *{
      margin: 0;
      padding: 0;
      text-align: right;
      color: #FFF;
    }
    #container{
      position: absolute;
      left: 20px;
      margin-top: 10px;
      width: 600px;
      height: 600px;
      background-color: green;
    }
    #big{
      padding-top:5px;
      position: relative;
      left: 20px;
      margin-top: 40px;
      width: 300px;
      height: 300px;
      background-color: #000;
    }
    #normal{
      position: static;
      margin-left: 20px;
      margin-top: 50px;
      width: 200px;
      height: 200px;
      background-color: #aaa;
    }
    #middle{
      position: absolute;
      margin-left:0px;
      margin-top:20px;
      width: 100px;
      height: 100px;
      background-color: #333;
    }
    </style>
  </head>
  <body>
    <div id="container">
          <div id="big">
            <div id="normal">
              <div id="middle">
                middle</div>normal
              </div>big
            </div> container
      </div>
    </div>
</body>
</html>

圖片描述

注意:#big{ padding-top:5px;} 這裏normal上邊框距離big上邊框的值應該是:margin-top(normal) + padding-top(big)

狀況3.外邊距與自身發生合併

假設有一個空元素,它有外邊距,可是沒有邊框或填充。在這種狀況下,上外邊距與下外邊距就碰到了一塊兒,它們會發生合併:
圖片描述

若是這個外邊距遇到另外一個元素的外邊距,它還會發生合併:

圖片描述
這就是一系列的段落元素佔用空間很是小的緣由,由於它們的全部外邊距都合併到一塊兒,造成了一個小的外邊距。

參考資料:
【1】http://www.w3school.com.cn/cs...

BFC

BFC(Block Formatting Contexts)直譯爲"塊級格式化上下文"。Block Formatting Contexts就是頁面上的一個隔離的渲染區域,容器裏面的子元素不會在佈局上影響到外面的元素,反之也是如此。

BFC造成

  1. float 的值不爲 none
  2. position 的值不爲 static 或 relative
  3. display屬性爲inline-boxs、table-cells、table-captions的不是塊盒的塊容器(除非這個值已經被傳播到視口),
  4. overflow不爲visible的塊盒纔會爲它的內容建立新的BFC。
  5. body元素

BFC渲染規則

  1. 內部的Box會在垂直方向,一個接一個地放置。
  2. Box垂直方向的距離由margin決定。屬於同一個BFC的兩個相鄰Box的margin會發生重疊
  3. 每一個元素的margin box的左邊, 與包含塊border box的左邊相接觸(對於從左往右的格式化,不然相反)。即便存在浮動也是如此。
  4. BFC的區域不會與float box重疊,經常使用來清除浮動和佈局。
  5. BFC就是頁面上的一個隔離的獨立容器,容器裏面的子元素不會影響到外面的元素。反之也如此。
  6. 計算BFC的高度時,浮動元素也參與計算

【待補充】

IFC

IFC(Inline Formatting Contexts)直譯爲」內聯格式化上下文」,IFC的line box(線框)高度由其包含行內元素中最高的實際高度計算而來(不受到豎直方向的padding/margin影響)

IFC渲染規則

  1. 框會從包含塊的頂部開始,一個接一個地水平擺放。
  2. 擺放這些框的時候,它們在水平方向上的外邊距、邊框、內邊距所佔用的空間都會被考慮在內。
  3. 在垂直方向上,這些框可能會以不一樣形式來對齊:它們可能會把底部或頂部對齊,也可能把其內部的文本基線對齊。能把在一行上的框都徹底包含進去的一個矩形區域,被稱爲該行的行框。
  4. 水平的margin、padding、border有效,垂直無效。
  5. 不能指定寬高。
  6. 行框的寬度是由包含塊和存在的浮動來決定。

IFC ‘line-height’ 與 ‘vertical-align’ 屬性

計算行框裏的各行內級框的高度:

  1. 行框的高是最頂端框的頂邊到最底端框的底邊的距離。
  2. 對於置換元素、行內塊元素、行內表格元素來講,這是邊界框的高度
  3. 對於行內框來講,這是其 ‘line-height’。

行內級元素根據其 ‘vertical-align’ 屬性垂直對齊。
在這些框使用 ‘top’ 或 ‘bottom’ 對齊的狀況下,user-agent必須以最小化行框的高爲目標對齊這些框。若這些框夠高,則存在多個解而不定義行框基線的位置。

清除浮動

  1. 在當前元素應用 clear:both;
  2. 浮動元素後添加新的元素,應用 clear:both;
  3. 父級div定義 overflow: auto
  4. 清除浮動的最佳實踐方案:
.clearfix:after {
          visibility: hidden;
          display: block;
          font-size: 0;
          content: " ";
          clear: both;
          height: 0;
       }

margin:auto與width的計算

主要講了margin與width結合處理大小爲auto的問題,並詳細介紹width的計算原則。
將這個問題以前先放一張盒模型示意圖:

圖片描述

如今有一個寬度爲400px的包含塊,針對如圖所示:

圖片描述

狀況一:margin-left margin-right width的值都是auto
表 現:width儘量的大,width的值爲100%;margin-left margin-right均爲0

狀況二:margin-left margin-right width的值都是100
表 現:margin-right 被強制設置成200

狀況三:margin-left margin-right 的值是auto;width已知爲200px
表 現:居中顯示

狀況四:margin-left:-100, margin-right:100 width的值是auto
表 現:width被計算爲400px

狀況五:margin-left:100,width:100,margin-right的值都是auto
表 現:margin-right被計算爲200px

三 後記

CSS相關連接:
CSS基礎

相關文章
相關標籤/搜索