《精通 CSS》筆記(上)

第 1 章 基礎知識

學習層疊樣式表(CSS,cascading style sheets)最好的方法,就是無論三七二十一,直接上手寫代碼。css

HTML 簡史

Tim Berners-Lee 在 1990 年發明了 HTML,當時是爲了規範科研文檔的格式。HTML 是一種簡單的標記語言,爲文本賦予了基本的結構和意義,好比標題、列表、定義等。這些文檔一般沒有什麼裝飾性的元素,能夠方便地經過計算機來檢索,而人類可使用文本終端、Web 瀏覽器,或者必要時使用屏幕閱讀器來閱讀它們。html

CSS 的版本

CSS1 是在 1996 年末成爲 W3C 推薦標準的,當時只包含字體、顏色和外邊距等基本的屬性。CSS2 在 1998 年成爲推薦標準,增長了浮動和定位等高級特性,此外還有子選擇符、相鄰選擇符和通用選擇符等新選擇符。git

相比之下,CSS3 則採用了徹底不一樣的模式。實際上不存在所謂的 CSS3 規範,由於 CSS3 指的是一系列級別獨立的模塊。若是規範模塊是對以前 CSS 概念的改進,那就從 3 級(level 3)開始命名。若是不是改進,而是一種全新的技術,那就從 1 級(level 1)開始命名。github

條件規則和檢測腳本

若是但願根據瀏覽器是否支持某個 CSS 特性來提供徹底不一樣的樣式,那麼能夠選擇 @supports 塊。這個特殊的代碼塊稱爲條件規則,它會檢測括號中的聲明,而且僅在瀏覽器支持該聲明的狀況下,纔會應用塊中的規則:算法

@supports (display: grid) {
  /* 在支持網格佈局的瀏覽器中要應用的規則 */
}
複製代碼

條件規則的問題是其自身也很新,只能將它應用於新的瀏覽器中,由於舊版本瀏覽器不支持。瀏覽器

建立結構化、語義化富 HTML

語義化標記意味着在正確的地方使用正確的元素,從而獲得有意義的文檔。語義明確的元素有:網絡

  • h1h2
  • puloldl
  • strongem
  • blockquotecite
  • precode
  • timefigcaptioncaption

HTML5 新增了一批結構化元素:app

  • section
  • header
  • footer
  • nav
  • article
  • aside
  • main

從新定義的表現性文本元素

<b><div> 能夠算是倖存的表現性標記了,它們在排版上會分別顯示爲粗體(bold)和斜體(italic)。這兩個元素與 <strong><em> 的區別在於,它們沒有任何強調本身所包含內容的意味。多數狀況下,應該選擇 <strong><em>,由於它們是用來強調及重點強調內容的語義正確的選擇。ide

微格式

微格式是一組標準的命名約定和和標記模式,可用於表示特定的數據類型。微格式的命名約定是基於 vCard 和 iCalendar 等已有的數據格式制定的。好比下面的聯繫人信息就是以 hCard 格式標記的:佈局

<section class="h-card">
  <p>
    <a class="u-url p-name" href="http://andybudd.com/">Andy Budd</a>
    <span class="p-org">Clearleft Ltd</span>
    <a class="u-email" href="mailto:info@andybudd.com">info@andybudd.com</a>
  </p>

  <p class="p-adr">
    <span class="p-locality">Brighton</span>
    <span class="p-country-name">England</span>
  </p>
</section>
複製代碼

微數據

微數據是跟 HTML5 一塊兒,做爲給 HTML 添加結構化數據的另外一種方式而推出的。它的目標與微格式很是接近,但在把微數據嵌入內容方面則有所不一樣。下面是微數據標記聯繫人信息:

<section itemscope itemtype="http://schema.org/Person">
  <p><a itemprop="name" href="http://thatemil.com/">Emil Bojoklund</a></p>
  <p itemprop="affiliation" itemscope itemtype="http://schema.org/Organization">
    <span itemprop="name">inUse Experience AB</span>
    <a itemprop="email" href="mailto:emil@thatemil.com">emil@thatemil.com</a>
  </p>
  <p itemprop="address" itemscope itemtype="http://schema.org/PostalAddress">
    <span class="addressLocality">Malm?</span>,
    <span class="addressCountry">Sweden</span>
  </p>
</section>
複製代碼

第 2 章 添加樣式

有效且結構良好的文檔是添加樣式的基礎。

CSS 選擇符

類型選擇符用於選擇特定類型的元素。類型選擇符有時候也被稱爲元素選擇符。

p {
  color: black;
}
複製代碼

後代選擇符用於選擇某個或某組元素的後代。

blockquate p {
  padding-left: 2em;
}
複製代碼

要想更精確地選擇目標元素,可使用 ID 選擇符(#)和類選擇符(.)。

#intro {
  font-weight: bold;
}

.date-posted {
  color: #ccc;
}
複製代碼

與後代選擇符會選擇一個元素的全部後代不一樣,子選擇符(>)只選擇一個元素的直接後代,也就是子元素。

#nav > li {
  background: url(folder.png) no-repeat left top;
  padding-left: 20px;
}
複製代碼
<ul id="nav">
  <li>Home</li>
  <li>
    Services
    <ul>
      <li>Design</li>
      <li>...</li>
    </ul>
  </li>
  <li>Contact Us</li>
</ul>
複製代碼

上面嵌套的 <ul> 下的 <li> 的樣式不會受到影響。

相鄰同輩選擇符(+)能夠選擇位於某個元素後面,並與該元素擁有共同父元素的元素。

h2 + p {
  font-size: 1.4em;
  font-weight: bold;
  color: #777;
}
複製代碼

通常同輩選擇符(~)能夠選擇位於某個元素後面的全部該元素擁有共同父元素的元素。

h2 ~ p {
  font-size: 1.4em;
  font-weight: bold;
  color: #777;
}
複製代碼

相鄰同輩選擇符和通常同輩選擇符都不會選擇前面的同輩元素。

通用選擇符(*)能夠匹配任何元素。

* {
  margin: 0;
  padding: 0;
}
複製代碼

事實上,這樣寫可能帶來不少意想不到的後果,特別是會影響 <button><select> 等表單元素。若是想重設樣式,最好仍是像下面這樣明確指定元素:

h1,
h2,
h3,
h4,
h5,
h6,
ul,
ol,
li,
dl,
p {
  margin: 0;
  padding: 0;
}
複製代碼

屬性選擇符基於元素是否有某個屬性或者屬性是否有某個值來選擇元素。

abbr[title] {
  border-bottom: 1px dotted #999;
}

input[type='submit'] {
  cursor: pointer;
}

/* 匹配以某些字符開頭的屬性值 */
a[href^='http:'] {
}

/* 匹配以某些字符結尾的屬性值 */
img[src$='.jpg'] {
}

/* 匹配包含某些字符的屬性值 */
a[href*='/about/'] {
}

/* 匹配以空格分隔的字符串中的屬性值 */
a[rel~='next'] {
}
複製代碼

有時候咱們想選擇的頁面區域不是經過元素來表示的,而咱們也不想爲此給頁面添加額外的標記。CSS 爲這種狀況提供了一些特殊選擇符,叫僞元素。

.chapter::before {
  content: '「';
  font-size: 10em;
}

.chapter p::first-letter {
  float: left;
  font-size: 3em;
}
複製代碼

有時候咱們想基於文檔結構之外的情形來爲頁面添加樣式,好比基於超鏈接或表單元素的狀態。這時候就可使用僞類選擇符。

a:visited {
  color: green;
}

.comment:target {
  background: #fffec4;
}

/* 結構化僞類 */
tr:nth-child(odd) {
  background: yellow;
}

/* 表單僞類 */
input:required {
  outline: 2px solid #000;
}
複製代碼

僞元素使用雙冒號(::)語法,僞類使用單冒號(:)語法。

層疊

層疊機制的原理是爲規則賦予不一樣的重要程度。最重要的是做者樣式表,其次是用戶樣式表,最後是瀏覽器的默認樣式表。在此基礎上,規則再按選擇符的特殊性排序。

爲了給用戶更高的優先權,CSS 容許用戶使用 !important 覆蓋任何規則。

p {
  font-size: 1.5em !important;
  color: #666 !important;
}
複製代碼

特殊性

爲了量化規則的特殊性,每種選擇符都對應着一個數值。一條規則的特殊性就表示爲其每一個選擇符的累加數值。但這裏的累加計算使用的並不是咱們熟悉的十進制加法,而是基於位置累加,以保證 10 個以上類選擇符累加的特殊性不會大於等於 1 個 ID 選擇符的特殊性。這是爲了不 ID 這種高特殊性選擇符被一堆低特殊性選擇符(如類型選擇符)的累加值所覆蓋。若是某條規則中用到的選擇符不足 10 個,爲簡單起見,也可使用十進制來計算其特殊性。

任何選擇符的特殊性都對應於以下 4 個級別,即 a、b、c、d:

  • 行內樣式,a 爲 1;
  • b 等於 ID 選擇符的數目;
  • c 等於類(class)選擇符、僞類選擇符及屬性選擇符的數目;
  • d 等於類型(type)選擇符和僞元素選擇符的數目。

下面是特殊性計算舉例:

選擇符 特殊性 十進制特殊性
style="" 1,0,0,0 1000
#wrapper #content {} 0,2,0,0 200
#content .datePosted {} 0,1,1,0 110
div#content {} 0,1,0,1 101
#content {} 0,1,0,0 100
p.comment .datePosted {} 0,0,2,1 21
p.comment {} 0,0,1,1 11
div p {} 0,0,0,2 2
p {} 0,0,0,1 1

通用選擇符(*)的特殊性爲 0。

若是兩條規則特殊性相等,則優先應用後定義的規則。

繼承

有些屬性,像顏色或字體大小,會被應用它們的元素的後代所繼承。繼承是頗有用的機制,有了它就能夠避免給一個元素的全部後代重複應用相同的樣式。

繼承的屬性值沒有任何特殊性,連 0 都說不上。通用選擇符的特殊性爲 0,但仍然優先於繼承的屬性。

第 3 章 可見格式化模型

浮動、定位和盒模型是學習 CSS 須要掌握的幾個最重要的概念。

盒模型

頁面中的全部元素都被看做一個矩形盒子,這個盒子包含元素的內容、內邊距、邊框和外邊距。內邊距(padding)是內容區周圍的空間。給元素應用的背景會做用於元素內容和內邊距。邊框(border)會在內邊距外側增長一條框線,這條框線能夠是實線、虛線或點劃線。邊框的外側是外邊距(margin),外邊距是圍繞在盒子可見部分以外的透明區域,用於在頁面中控制元素之間的距離。

對元素盒子而言,內邊距、邊框和外邊距不是必需的,所以它們的默認值都爲 0。

默認狀況下,元素盒子的 widthheight 屬性指的是內容盒子,也就是元素可渲染內容區的寬度和高度。這時候添加邊框和內邊距並不會影響內容盒子的大小,但會致使整個元素盒子變大。經過修改 box-sizing 屬性能夠改變計算盒子大小的方式。box-sizing 的默認值爲 content-box,若是吧 box-sizing 修改成 border-box,那麼 widthheight 屬性的值將會包含內邊距和邊框。

可見格式化模型

ph1article 等元素屬於塊級元素,會顯示爲塊級盒子strongspantime 等元素屬於行內元素,會顯示爲行內盒子

塊級盒子會沿垂直方向堆疊,盒子在垂直方向上的間距由它們的上、下外邊距決定。

行內盒子是沿文本流水平排列的,也會隨文本換行而換行。它們之間的水平間距能夠經過水平方向的內邊距、邊框和外邊距來調節。但行內盒子的高度不受其垂直方向上的內邊距、邊框和外邊距的影響。此外,給行內盒子明確設置高度和寬度也不會起做用。

由一行文本造成的水平盒子叫行盒子(line box),而行盒子的高度由所包含的行內盒子決定。修改行盒子大小的惟一途徑就是修改行高(line-height),或者給它內部的行內盒子設置水平方向的邊框、內邊距或外邊距。

垂直方向上的兩個外邊距相遇時,會摺疊成一個外邊距,摺疊後外邊距的高度等於二者中較大的那一個高度,這種機制叫作外邊距摺疊。

行內盒子、浮動盒子或絕對定位盒子的外邊距不會摺疊。

把一個元素的 display 屬性設置爲 relative,該元素仍然會待在原來的地方。不管是否位移,相對定位的元素仍然會在文檔流中佔用初始的空間。

絕對定位則會把元素拿出文檔流,所以也就不會在佔用原來的空間。

要阻止行盒子環繞在浮動盒子外面,須要給包含行盒子的元素應用 clear 屬性。clear 屬性的值有 leftrightbothnone,用於指定盒子的哪一側不該該緊挨着浮動盒子。不少人認爲 clear 屬性只是簡單地刪除幾個用於抵消前面浮動元素的標記,事實卻沒有這麼簡單。清除一個元素時,瀏覽器會在這個元素上方添加足夠大的外邊距,從而將元素的上邊沿垂直向下推移到浮動元素下方。所以,若是你給「已清除的」元素添加外邊距,那麼除非你的值超過瀏覽器自動添加的值,不然不會看到什麼效果。

格式化上下文

當元素在頁面上水平或垂直排布時,他們之間如何相互影響,CSS 有幾套不一樣的規則,其中有一套規則叫作格式化上下文(formatting content)。前面咱們已經介紹了行內格式化上下文(inline formatting context)的一些規則。好比,垂直外邊距對於行內盒子沒有影響。相似的,有的規則適用於塊級盒子的疊放,好比前面介紹的外邊距摺疊。

此外,有些規則規定了頁面必須自動包含突出的浮動元素(不然浮動元素中的內容可能會跑到可滾動區域以外),並且全部塊級盒子的左邊界默認與包含塊的左邊界對齊(若是文字順序是從右向左,那麼與包含塊的右邊界對齊)。這組規則就是塊級格式化上下文(block formatting context)。

還有些規則容許元素創建本身內部的塊級格式化上下文,包括:

  • display 屬性值設置爲 inline-blocktable-cell 之類的元素,能夠爲內容建立相似塊級的上下文;
  • float 屬性值不是 none 的元素;
  • 絕對定位的元素;
  • overflow 屬性值不是 visible 的元素。

當一個元素具有了觸發新塊級格式化上下文的條件,而且挨着一個浮動元素時,它就會忽略本身的邊界必須接觸本身的包含快邊界的規則。此時,這個元素會收縮到適當大小。不只行盒子如此,全部盒子都是如此。

下面看一個使用常規方法清除浮動的示例:

.media-block {
  background-color: gray;
  border: solid 1px black;
}
.media-fig {
  float: left;
  width: 30%;
}
.media-body {
  float: right;
  width: 65%;
}
.media-block::after {
  content: ' ';
  display: block;
  clear: both;
}
複製代碼
<div class="media-block">
  <img class="media-fig" src="/img/pic.jpg" alt="The pic" />
  <div class="media-body">
    <h3>Title of this</h3>
    <p>Brief description of this</p>
  </div>
</div>
複製代碼

經過觸發新的塊級格式化上下文的方式,咱們能夠換種方式清除浮動:

.media-block {
  background-color: gray;
  border: solid 1px black;
}
.media-fig {
  float: left;
  width: 30%;
  margin-right: 5%;
}
.media-block,
.media-body {
  overflow: auto;
}
複製代碼

這樣就能實現咱們的目標:

  • 不用設置清除規則,就可讓 .media-block 包住浮動的圖片,由於塊級格式化上下文自動包含浮動;
  • 順帶着,咱們能夠放棄給 .media-body 聲明寬度和浮動。這是由於它會自動調整以適應浮動元素旁邊的剩餘空間,並確保挨着圖片的一遍是直的。若是這裏沒有新的格式化上下文,並且文本比較多,那麼位於浮動 .media-fig 下方的行盒子都會伸長,最終填滿圖片下方的空間。

儘可能基於簡單且可預測的行爲來建立佈局,這樣能夠下降代碼複雜度,並提升佈局穩健性。

第 4 章 網頁排版

自印刷出版物誕生以來,排版就一直是平面設計的基礎。

CSS 的基本排版技術

em 用於計算盒模型的大小時,它不是基於繼承的 font-size,而是基於元素自身計算的 font-size

font-size 到底應該選多大,其實沒有硬性要求。咱們這裏介紹一個適用於標題的大小的叫作「純四度」(perfect fourth)的數學比例,即上一級標題會比下一級標題的字型大小大自身尺寸的 1/4,或者說是下一級標題字型大小的 1.3333... 倍。

h1 {
  font-size: 2.315em; /* 37px */
}
h2 {
  font-size: 1.75em; /* 28px */
}
h3 {
  font-size: 1.314em; /* 21px */
}
複製代碼

此類比例關係對於初始階段的網頁設計相當重要。推薦你們試試 Modular Scale 計算器,其中有不少預設比例關係可供參考。

inline box

行內盒子中的內容區顯示文本。內容區的高度由 font-size 的測量尺度,即上圖中 n 那個 1em 見方的塊,以及這個塊與字形自己的關係來決定。

小寫字母 x 的上邊界決定了所謂的「x 高度」。

字形會被擺放在內容區中,每一個字形都在垂直方向上不偏不倚,使得每一個行內盒子的底邊都默認對齊於靠近底部的共同水平線,這條線叫基線。內容區也不必定會限制住字形,好比某些字體中的小寫字母「g」就會向下伸出內容區。

行高指的是行盒子的總高度。更通俗的叫法是行間距,排版術語叫鉛空,就是排字員用來隔開字符行的鉛塊。

行盒子的總體行高減去 font-size,獲得的值再平分紅兩份,也就是半鉛空。

若是行盒子中包含多個行高不一的行內盒子,那麼這個行盒子的最終高度至少等於其中最高的行內盒子。

body {
  font-family: Georgia, Times, 'Times New Roman', serif;
  line-height: 1.5;
}
複製代碼

通常來講,行高取值在 1.2 ~ 1.5 範圍內。關鍵是行與行之間既不能太密,也不能太疏。

這裏給 line-height 設置類沒有單位的值 1.5,意思就是當前 font-size 的 1.5 倍。bodyfont-size 爲 16px,那麼默認的 line-height 就是 24px。

也能夠給 line-height 設置像素值、百分比值或 em 值,但要注意 body 元素的全部子元素都會繼承 line-height 的計算值。換句話說,就算 body 用的是百分比值或 em,其子元素繼承的都是計算後獲得的像素值,但無單位的值就不會致使這個結果。所以,若是給 lien-height 設置沒有單位的值,那麼子元素繼承的是一個係數,永遠與本身的 font-size 成比例。

除了 line-height,行內盒子也會受到 vertical-align 屬性的影響。它的默認值是 baseline,即子元素的基線與父元素的基線對齊。其餘值還有 suptopbottomtext-toptext-bottommiddle

若是行盒子中有一個元素使用 vertical-align 調整了位置,那麼它可能會擴展行盒子的高度。

與行內文本相比,行內塊和圖片的垂直對齊行爲稍有不一樣,由於它們不必定有本身的惟一基線。

咱們使用 font-weight 屬性來設置標題文本的粗細。關鍵字有如下幾個:normalboldbolderlighter,也能夠直接給出數字值:100,200,300,……,900。默認值 normal 對應 400,bold 對應 700,這兩個粗細值是最經常使用的。

版心寬度、律動和毛邊

對閱讀體驗有着重大影響的因素:行長。用排版的行話說,就是版心寬度。過長或太短的文本行會打斷人的眼球移動,致使讀者沒法連續閱讀。

一行文本到底多長才合適,並無什麼終極答案。Robert Bringhurst 的經典圖書 The Elements of Typographic Style 提到,主題內容的文本行長一般是 45 ~ 75 個字符,平均值爲 66 個字符。

Web 字體

在下載 Web 字體的時候,瀏覽器有兩種方式處理相應的文本內容。第一種方式是在字體下載完成前暫緩顯示文本,術語叫 FOIT(flash of invisible text)。Safari、Chrome 和 IE 默認採用這種方式,問題是用戶必須等待字體下載完成才能看到內容。若是用戶的網絡速度很慢,這個問題會很是明顯。

第二種方式是在字體下載完成前,瀏覽器先用一種後備字體顯示內容。這樣能夠避免因網速慢而引發的問題,但也會帶來字體切換時的閃動問題。這個閃動有時候也被稱爲 FOUT(flash of unstyled text)。

第 5 章 漂亮的盒子

背景附着

背景會附着在指定元素的後面,若是你滾動頁面,那麼背景也會隨着元素移動而移動。能夠經過 background-attachment 屬性改變這種行爲。

.profile-box {
  background-attachment: fixed;
}
複製代碼

隨着頁面滾動,該背景圖片不會動,好像藏到了頁面後面同樣。

多重背景

Level 3 Backgrounds and Borders 規範如今支持一個元素設置多個背景圖片。所以,每一個背景屬性也就有了相應的多值語法,多個值由逗號分隔。

.multi-bg {
  background-image: url(img/spades.png), url(img/hearts.png), url(img/diamonds.png), url(img/clubs.png);
  background-position: left top, right top, left bottom, right bottom;
  background-repeat: no-repeat, no-repeat, no-repeat, no-repeat;
  background-color: pink;
}
複製代碼

多重背景按聲明的前後次序自上而下堆疊,最早聲明的在最上面,最後聲明的在最下面。背景顏色層在全部背景圖片下面。

可保持寬高比的容器

對於具備固定寬高比的位圖,把高度設置爲 auto,只改變寬度,或者把寬度設置爲 auto,只改變高度,都是能夠的。

可是若是沒有固定寬高比的元素呢?如何是其在可伸縮的同時保持固定寬高比?

iframeobject 就屬於這種情形,某些狀況下的 SVG 內容也是。常見的例子是在頁面中經過 iframe 嵌入一段視頻:

<iframe width="420" height="315" src="https://www.youtube.com/embed/dQw4w9WgXcQ" frameborder="0" allowfullscreen ></iframe>
複製代碼

若是像這樣給它設置一個可伸縮的寬度:

iframe {
  width: 100%; /* 或者其餘任何比例 */
}
複製代碼

就會致使 iframe 寬度爲 100%,而高度始終是 315 像素。由於視頻自己也有寬高比,因此咱們但願這裏的高度也能夠自適應。

此時不管把 iframe 的高度設置爲 auto 仍是刪除 height 屬性都無論用,由於 iframe 自己沒有固定的寬高比。此外,這樣作極可能致使 iframe 的高度變成 150 像素。爲何是 150 像素呢?CSS 規範指出,對於沒有指定大小的可替代內容(如 iframeimgobject),最終的默認大小爲 300 像素寬或 150 像素高。

要解決這個問題,須要藉助一些巧妙的 CSS 技術。 首先,把 iframe 包在一個元素裏:

<div class="object-wrapper">
  <iframe width="420" height="315" src="https://www.youtube.com/embed/dQw4w9WgXcQ" frameborder="0" allowfullscreen ></iframe>
</div>
複製代碼

而後讓這個包裝元素的尺寸與要嵌入的對象具備相同的寬高比。簡單計算一下,用原始的高度 315 像素除以原始寬度 420 像素,結果是 0.75。換句話說,高度是寬度的 75%。

接下來,將包裝元素的高度設置爲 0,但把 padding-bottom 設置爲 75%:

.object-wrapper {
  width: 100%;
  height: 0;
  padding-bottom: 75%;
}
複製代碼

以前介紹過,內邊距和外邊距若是使用百分比值來設置,那它們的實際值是基於包含塊的寬度來計算的。這裏的寬度是 100%(與包含塊寬度相等),所以內邊距就是包含塊的 75%。因而咱們就建立了一個具備寬高比的元素。

最後,在這個包裝元素中絕對定位嵌入對象。儘管包裝元素的高度是 0,仍然能夠經過絕對定位把嵌入對象放到一個「可保持寬高比」的內邊距盒子裏:

.object-wrapper {
  width: 100%;
  height: 0;
  padding-bottom: 75%;
  position: relative;
}

.object-wrapper iframe {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}
複製代碼

成功!這樣就能夠在頁面中包含可伸縮的嵌入對象了。

第 6 章 內容佈局

定位

定位並不適合整體佈局,由於它會把元素拉出頁面的正常流。關於定位的總結以下:

  • 元素的初始定位方式爲靜態定位(static),意思是塊元素垂直堆疊
  • 能夠把元素設置爲相對定位(relative),而後能夠相對於其原始位置控制該元素的偏移量,同時又不影響其周圍的元素。與此同時,這也爲該元素的後代元素創造了定位上下文。這一點也是相對定位真正的用處。
  • 絕對定位(absolute)支持精肯定位元素,相對於其最近的定位上下文:或者是其非靜態定位的祖先元素,或者是 html 元素。絕對定位的元素會脫離頁面流,而後再相對於其定位上下文進行定位。默認狀況下,它們會被瀏覽器定位與以前靜態定位時所處的位置,但不會影響周圍的元素。而後,咱們能夠相對於定位上下文來改變它們的位置。
  • 固定定位(fixed)與絕對定位基本相似,只不過定位上下文被自動設置爲瀏覽器視口。

絕對定位很是適合建立彈出層、提示和對話框這類覆蓋於其餘內容之上的組件。

要用好定位,還有一個重點技術必須掌握,那就是 z-index,也就是堆疊元素的次序。靜態定位(static)之外的元素會根據它們在代碼樹中的深度依次疊放,就像打撲克發牌同樣,後發的牌會壓在先發的牌上面。它們的次序能夠經過 z-index 來調整。

除了 z-index,還有其餘影響元素堆疊次序的因素。這裏有一個概念,叫堆疊上下文。就像一盒撲克牌,每張牌自己也是一個上下文(牌盒),而牌只能相對當前的牌盒排定次序。有一個根堆疊上下文,全部 z-index 不是 auto 的定位元素都會在這個上下文中排序。隨着其餘上下文的創建,就會出現堆疊層級。

堆疊上下文是由特定屬性和值建立的。好比,任何設定了 position: absolute 及值不是 autoz-index 屬性的元素,都會建立一個本身後代元素的堆疊上下文。

在一個堆疊上下文內部,不管 z-index 值多大或多小,都不會影響其餘堆疊上下文,畢竟不能相對於別的堆疊上下文從新排序。

設置小於 1 的 opacity 值也能夠觸發新的堆疊上下文。

對於利用行內塊建立水平佈局而言,若是須要垂直對齊,有如下兩點:

  • 要讓行內塊沿上方對齊(很像浮動),設置:vertical-align: top
  • 要讓兩個元素的內容垂直對齊,先把它們都轉換成行內塊,再對它們應用 vertical-align: middle

對於每一個塊都佔據確切寬度的水平佈局而言,空白是一個突出的問題。HTML 源代碼中的換行符會被渲染成空白符,若是水平佈局的幾個行內塊的寬度之和剛好等於包含元素寬度,那麼這幾個行內塊必定會發生折行。解決這種問題的方法簡單粗暴,就是把包含元素的 font-size 設置爲 0(從而讓每一個空格的寬度爲 0)。

Flexbox

Flexbox,也就是 Flexible Box Layout 模塊,是 CSS 提供的用於佈局的一套新屬性。這套屬性包含針對容器(彈性容器,flex container)和針對其直接子元素(彈性項,flex item)的兩類屬性。Flexbox 能夠控制彈性項的以下方面:

  • 大小,基於內容及可用空間;
  • 流動方向,水平仍是垂直,正向仍是反向;
  • 兩個軸向上的對齊與分佈;
  • 順序,與源代碼中的順序無關。

Flexbox 能夠針對頁面中某一區域,控制其中元素的順序、大小、分佈及對齊。這個區域內的盒子能夠沿兩個方向排列:默認水平排列(成一行),也能夠垂直排列(成一列)。這個排列方向稱爲主軸(main axis)。

與主軸垂直的方向稱爲輔軸(cross axis),區域內的盒子能夠沿輔軸發生位移或伸縮。Flexbox 佈局中最重要的尺寸就是主軸方向的尺寸:水平佈局時的寬度或垂直佈局時的高度。咱們稱主軸方向的這個尺寸爲主尺寸(main size)。

若是不指定大小,Flex 容器內的項目就會自動收縮。也就是說,一行中的各項會收縮到各自的最小寬度,或者一列中的各項會收縮到各自的最小高度,以剛好能夠容納自身內容爲限。

Flexbox 對子項的排列有多種方式。沿主軸的排列叫排布(justification),沿輔軸的排列則叫對齊(alignment)。

用於指定排布方式的屬性就是 justify-content,其默認值是 flex-start,表示按照當前文本方向排布(也就是向左對齊)。justify-content 的其餘幾個關鍵字爲:flex-endcenterspace-betweenspace-around

Flexbox 不容許經過以上這些關鍵字指定個別項的排布方式。然而,對 Flexbox 的子項指定值爲 auto 的外邊距在這裏卻有不一樣的含義。具體來講,若是指定某項一側的外邊距值爲 auto,並且在容器裏那一側還有空間,那麼該外邊距就會擴展佔據可用空間。利用這一點,能夠創造讓一項位於一側,其餘項位於另外一側的佈局。

.navbar li:first-child {
  margin-right: auto;
}
複製代碼

像上面這樣,對第一項應用 margin-right: auto 能夠吃掉全部剩餘空間,把其餘項推到右側。

控制輔軸對齊的屬性 align-items,其默認值是 stretch。也就是說,子項默認拉伸,以填滿可用空間。其餘的關鍵字還有 flex-startcenterflex-endbaselinebaseline 關鍵字能夠將子項中文本的基線與容器基線對齊,效果與行內塊的默認行爲相似。若是子項大小不一,而你但願它們在輔軸上雖然位置不一樣,但自己對齊,那麼就能夠採用這種方法。

除了同時對齊全部項,還能夠在輔軸上使用 align-self 指定個別項的對齊方式。

Flexbox 可讓咱們輕鬆解決垂直對齊問題。在容器裏面只有一個元素時,只要將容器設置爲 flex,再將須要居中的元素的外邊距設置爲 auto 就好了。這是由於 Flexbox 中各項的自動外邊距會擴展「填充」相應方向的空間。

<div class="flex-container">
  <div class="flex-item">
    <h2>Not so lost in space</h2>
    <p>This item sits right in the middle of its container...</p>
  </div>
</div>
複製代碼

想要水平而且垂直居中 .flex-item,僅須要如下 CSS 代碼,不管容器或其中元素有多大。

html,
body {
  height: 100%;
}
.flex-container {
  height: 100%;
  display: flex;
}
.flex-item {
  margin: auto;
}
複製代碼

Flexbox 支持對元素大小的靈活控制。這一點既是實現精確內容佈局的關鍵,也是迄今爲止 Flexbox 中最複雜的環節。可伸縮的尺寸在實現以前,確實是很難預測的。

Flex 的意思是「可伸縮」,這體如今如下 3 個屬性中:flex-basisflex-growflex-shrink。這 3 個屬性應用給每一個可伸縮項,而不是容器。

  • flex-basis:控制項目在主軸方向上、通過修正以前的「首選」大小(widthheight)。能夠是長度值(如 18em)、百分比(相對於容器的主軸而言),也能夠是關鍵字 auto(默認值)。關鍵字 auto 的意思好像是把 widthheight 設置爲自動,但實際上並非那麼回事。這裏 auto 值的意思是這個項目能夠從對應的屬性(widthheight)那裏得到主尺寸 -- 若是設置了相應屬性的話。若是沒有設置主尺寸,那麼該項目就根據其內容肯定大小,有點相似浮動元素或行內塊。也能夠設置 content 值,意思也是根據項目內容肯定大小,可是會忽略經過 widthheight 設置的主軸尺寸(與 auto 不一樣了)。

  • flex-grow:一個彈性係數(flex factor)。在經過 flex-basis 爲每一項設置了首選大小以後,若是還有剩餘空間,該係數表示該如何處理。其值是一個數值,表示剩餘空間的一個比值。默認值是 0,表示從 flex-basis 取得尺寸後就再也不擴展。

  • flex-shrink:也是一個彈性係數,與 flex-grow 相似,但做用相反。換句話說,若是空間不夠了,該如何收縮?增長了 flex-shrink 這個因素以後,計算過程就更復雜了。默認值是 1,表示若是空間不夠,全部項都會以本身的首選尺寸爲基準等比例收縮。

要理解 flex-basisflex-grow 以及 flex-shrink 的關係可並不容易。Flexbox 使用了至關複雜的算法來計算各伸縮項的大小。可是,若是咱們將計算過程簡化成如下兩個步驟,那麼理解起來就容易多了。

(1)檢查 flex-basis,肯定假想的主尺寸。

(2)肯定實際的主尺寸。若是按照假想的主尺寸把各項排布好以後,容器內還有剩餘空間,那麼它們能夠伸展。伸展多少由 flex-grow 係數決定。相應地,若是容器裝不下那麼多項,則根據 flex-shrink 係數決定各項如何收縮。

使用 flex 簡寫屬性能夠一次性設置 flex-growflex-shrinkflex-basis 屬性:

.navbar li {
  flex: 1 0 0%;
}
複製代碼

在多行佈局中,咱們能夠相對於容器來對齊行或列。咱們可使用一個叫作 align-content 的屬性,默認值爲 stretch,意思是每一行都會拉伸本身以填充本身應占的容器高度。align-content 對容器中多行的做用,與 justify-content 對主軸內容排布的做用很是類似。align-content 的其餘取值爲:flex-startflex-endcenterspace-betweenspace-around

使用 Flexbox 的 order 屬性,能夠徹底擺脫項目在源代碼中的順序的約束。只要告訴瀏覽器這個項目排在第幾就好了。默認狀況下,每一個項目的 order 值都爲 0,意味着按照它們在源代碼中的順序出現。

經過 Flexbox 重拍次序隻影響呈現的效果。按 Tab 鍵切換鍵盤焦點和屏幕閱讀器並不會受 order 屬性的影響。所以 HTML 代碼仍是要按照邏輯來寫。

相關文章
相關標籤/搜索