"

計算機非人性的一部分表現是,一旦完成編譯並且順利運行,它將忠實地完成工作。

——艾薩克·阿西莫夫

Bootstrap是一個CSS和JavaScript庫,它致力於簡化現代網頁的構建,原本是Twitter開發給內部使用的。但是,“現代網頁”到底是什麼呢?

非常簡單,現代網頁是按照現在大多數用戶想要的樣子構建的網頁。HTML語言仍然是網頁的基礎和核心語言。但是,HTML標記語言的構造越來越不能快速直接地表達構成現代網頁的複雜和成熟。比如,下拉菜單、分段選項按鈕、標籤欄、可摺疊標籤和模態對話框都是大多數頁面的常見元素,卻沒有現成的HTML元素。

Bootstrap提供直接的方式,把HTML塊變成現代網站所需的更加成熟的可視化元素。

9.1 Bootstrap概覽

Bootstrap是一個模塊化的Web庫,由CSS和JavaScript文件組成。CSS文件包含了重新設計常見HTML元素的類,使它們看上去不一樣,或許更好看。JavaScript文件是一組jQuery插件,支持更加複雜的特性,這些特性無法單純通過CSS實現。

Bootstrap最初開發成一組LESS文件,你仍然能夠以LESS文件的方式獲取CSS部分。一般來說,有組成Bootstrap庫的每個模塊的LESS或CSS文件:表單、按鈕、導航欄、對話框等。在深入Bootstrap庫之前,下面先來看看LESS。

9.1.1 LESS和Bootstrap基礎

LESS文件是構建在普通CSS語法之上的一個抽象層,讓開發者可以聲明一個CSS文件最終將會如何使用。你可以把LESS看作一門編程語言,一旦編譯就會產生CSS。在LESS文件裡,可以使用變量、函數和運算符,因此極大地提高了創建和維護大型複雜CSS樣式表的流程效率。

1.變量

開發者使用LESS解決的一大問題是信息的重複。軟件開發者可能深諳“自己不要重複”(Don’t Repeat Yourself, DRY)原則並且每天踐行。DRY的最大好處是減少相同信息保存位置的個數,因而減少應該更新的位置的個數。在普通CSS裡,無法做到DRY。比如,如果特定顏色在多個CSS類裡使用(某些時候要更新),除了在每個出現的地方更新,你可能沒有更好的辦法了。

CSS類的問題在於它們在語義HTML元素的級別工作。在構建各種CSS類時,你通常需要重複小塊信息,比如顏色或寬度。你無法輕易為每個可重複的小塊信息創建一個類。即使每個可重複樣式都有一個CSS類,如顏色和寬度,當把樣式應用到語義元素(如容器)時,需要聯合多個CSS類才能實現預期效果。

考慮以下CSS例子。

.container {
color: #111;
}
.header {
background-color: #111;
}

container和header兩個CSS類都使用相同的顏色。如果那個顏色需要改變,那麼必須找出所有使用它的地方然後編輯。下面使用LESS重寫相同的特性。

@black: #111;
.container {
color: @black;
}
.header {
background-color: @black;
}

現在,這個顏色定義在一個地方,作為全局變量。從這裡來看,LESS把程序員喜歡的概念添加到CSS編碼了,如變量。但它能做的不止這些。

2.導入

可以把LESS代碼分割到多個文件,在需要的時候引用它們。假設創建一個container.less文件,它包含如下內容。

@black: #111;
.container {
background-color: @black;
}

在另一個LESS文件裡,比如main.less,可以通過導入這個文件來引用整個CSS。

@import "container";
.body { .container; }

如果container.less文件(擴展名不是必需的)放在另一個文件夾裡,你應該在調用@import時給出路徑信息。

3.混入(Mixins)

讓CSS樣式適配不同分辨率的能力是很重要的,尤其在網頁必須適配不同屏幕大小時。比如,當按鈕在平板上顯示且針對粗粒度指針(如手指)時,開發者通常會增加按鈕周圍的邊距(padding)。一般來說,如何使相同的CSS類根據某些運行時條件改變並且產生不同的顯示效果,這就是LESS混入派上用場的地方了。

以下是幾個混入示例。

.shadow(@color) {
box-shadow: 3px 3px 2px @color;
}
.text-box(@width) {
.shadow(#555);
border: solid 1px #000;
background-color: #dddd00;
padding: 2px;
width: @width;
}

可以從這裡派生出更加具體的CSS類,如下所示。

.text-box-mini {
.text-box(50px);
}
.text-box-normal {
.text-box(100px);
}
.text-box-large {
.text-box(200px);
}

這正是Bootstrap為了支持常見元素(如按鈕和輸入框)的不同風格在內部做的。

4.把LESS變成CSS

雖然LESS可以用作CSS的元語言,但LESS不是CSS。它必須進行某種處理來生成普通CSS。LESS代碼可以原樣下載並在客戶端通過JavaScript代碼處理,或者也可以在服務器上預處理,然後把普通CSS下載到客戶端。前者像在使用普通CSS文件:服務器端的更改會在下個頁面刷新時應用到客戶端。

但是,如果你有性能顧慮,而且要處理很大很複雜的CSS文件,服務器端預處理可能是個更好的選擇。服務器端預處理會在你每次修改服務器上的CSS時發生。通常,你會在構建流程的最後通過命令行使用LESS編譯器執行額外的步驟。Gulp等工具可以使用JavaScript相關的步驟來擴展構建流程。另一個流行的工具是Microsoft Web Essentials(一個Visual Studio插件),可以用來添加專門的菜單命令、處理CSS和腳本文件等Web資源。

但是,在ASP.NET MVC裡,還有另一種做法。你可以通過捆綁和壓縮機制整合整個LESS框架。在第10章裡,你將會詳細瞭解到,捆綁流程會把多個不同資源打包成單個可下載資源。比如,一個捆綁可能包含多個JavaScript和CSS文件,你可以通過向專門的終結點發送單個HTTP請求把它下載到本地機器。壓縮是應用到資源的特殊轉換。具體來說,壓縮會從文本資源移除所有不必要的字符,但不會改變預期功能。這意味著移除註釋、空白字符、換行符以及所有用於改善可讀性但只佔用空間的非功能性字符。

9.1.2 設置Bootstrap

可以從NuGet獲取Bootstrap。這種情況下,可以只取框架中所需要的部分。Bootstrap通常會用於整個網站,這樣可以從主視圖連接它,如下所示。

<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" src="@Url.Content("~/content/styles/bootstrap.min.css")">

viewport meta標籤把瀏覽器視口(Viewport)的寬度設為實際設備寬度並把放大級別設為標準。link元素只是引入Bootstrap樣式表的壓縮版本。如果打算使用更高級的Bootstrap特性,鑑於這些特性需要JavaScript,可以鏈接腳本文件以及它依賴的jQuery文件。

<script type="text/javascript"
src="@Url.Content("~/content/scripts/jquery-2.1.4.min.js")"></script>
<script type="text/javascript"
src="@Url.Content("~/content/scripts/bootstrap.min.js")"></script>

如果使用完整的Bootstrap庫,一旦鏈接了CSS和腳本文件,就已經準備好了。如果只用Bootstrap庫的部分,則必須確保需要的所有部分都正確鏈接。值得注意的是,Bootstrap庫的某些特性(比如工具提示和彈出界面)需要一些啟動JavaScript代碼,這些代碼必須添加代碼到每個頁面。

■ 注意:

Bootstrap不受老的Internet Explorer兼容模式支持。要確保頁面在Internet Explorer下能以最佳渲染方式查看,最好的辦法是在你的頁面裡添加以下meta標籤。

<meta http-equiv="X-UA-Compatible" content="IE=edge">

Bootstrap的CSS類使用了最新的CSS特性(如圓角效果),這可能不適用於老的瀏覽器。Internet Explorer 8就是部分支持Bootstrap的老瀏覽器的好樣板。

9.1.3 透析Bootstrap

Twitter Bootstrap在今天幾乎是必備的,原因是它使得向現代網站添加高級特性變得快速容易。Bootstrap的學習曲線比較短,很多基於它的模板都是免費的。但對於任何Web設計師而言,自定義基本Bootstrap模板實現獨特的效果也不是什麼難事。

Bootstrap是否適合你的項目取決於外觀的重要性。如果你的客戶需要自己的外觀,Bootstrap可能不是理想的。在這種情況下,開發團隊只收到圖形模板並使用它。此外,Bootstrap非常適合外觀重要但不是根本的快速項目。

換句話說,Bootstrap是一個很好的產品,但無法取代很好的設計。同時,它無法取代為每個設備定義得很好的用戶體驗。很容易找到一些網站提供基於Bootstrap的免費或付費模板。如果你限制自己使用Bootstrap庫的默認樣式(不改變CSS或LESS源代碼),那麼面臨的風險就是所有網站最終看起來都一樣。

要不要使用Bootstrap是一個架構決定,必須在項目早期做,後期很難更改。把Bootstrap添加到正在進行的項目或者從中刪除雖然不是不可能,但也通常有問題。最後,考慮到完整的Bootstrap庫包含100KB的CSS和30KB的腳本,這不是很大的資源,但也不是輕量級資源,尤其是使用較慢連接的較小設備。

Bootstrap的快速普及的其中一個關鍵原因是創建從不同類型設備看起來不錯的頁面成本很低。

■ 注意:

正如你將在第15章中看到的,有兩種截然不同的方式為多個設備設計網站。反應式Web設計是一種讓一套HTML頁面自動適配實際屏幕大小的方案。這是Bootstrap推廣的方案。其他方案為一些關鍵設備創建一套單獨的頁面,最突出的是智能手機。我將會在第16章講述這個話題。

9.2 反應式佈局

今天,所有網站至少都應該反應託管屏幕的寬度變化。作為開發團隊的一員,你有兩種主要方式實現這個功能。你可以從供應商那裡購買一個HTML反應式模板,堅持使用,讓實現細節透明,或者自行開發這個模板。

在後一種情況中,你會使用哪個框架呢?Bootstrap可能是人們應該考慮的第一個框架,但不是唯一的。其他同樣熱門和有效的響應式框架有Foundation、Skeleton和Gumby。任何學習Bootstrap的方案都從它提供的賦予HTML視圖響應式佈局的服務開始。

9.2.1 網格系統

Bootstrap有一個靈活的網格系統,它把水平可用空間分成12等份物理列。Bootstrap提供預定義CSS類,讓你可以通過創建邏輯列隨意佈局模板。換句話說,Bootstrap讓你可以通過一個範圍從1~12個單位的測量系統來安排模板空間。Bootstrap單位的實際大小取決於設備的實際屏幕大小。

屏幕大小實際上是視口——內容的可視化區域。在移動設備上,設備屏幕和視口一致,因為設備通常不支持可調整大小的窗口。而在臺式機上,你可以把窗口的大小調整到比最大可用空間小。在這種情況下,Bootstrap認為視口是可用渲染空間。

1.整體模板

任何Bootstrap內容要響應屏幕大小的改變都會基於行列矩陣。整體容器(這個矩陣)是一個樣式設為container的DIV元素(見圖9-1)。

"

計算機非人性的一部分表現是,一旦完成編譯並且順利運行,它將忠實地完成工作。

——艾薩克·阿西莫夫

Bootstrap是一個CSS和JavaScript庫,它致力於簡化現代網頁的構建,原本是Twitter開發給內部使用的。但是,“現代網頁”到底是什麼呢?

非常簡單,現代網頁是按照現在大多數用戶想要的樣子構建的網頁。HTML語言仍然是網頁的基礎和核心語言。但是,HTML標記語言的構造越來越不能快速直接地表達構成現代網頁的複雜和成熟。比如,下拉菜單、分段選項按鈕、標籤欄、可摺疊標籤和模態對話框都是大多數頁面的常見元素,卻沒有現成的HTML元素。

Bootstrap提供直接的方式,把HTML塊變成現代網站所需的更加成熟的可視化元素。

9.1 Bootstrap概覽

Bootstrap是一個模塊化的Web庫,由CSS和JavaScript文件組成。CSS文件包含了重新設計常見HTML元素的類,使它們看上去不一樣,或許更好看。JavaScript文件是一組jQuery插件,支持更加複雜的特性,這些特性無法單純通過CSS實現。

Bootstrap最初開發成一組LESS文件,你仍然能夠以LESS文件的方式獲取CSS部分。一般來說,有組成Bootstrap庫的每個模塊的LESS或CSS文件:表單、按鈕、導航欄、對話框等。在深入Bootstrap庫之前,下面先來看看LESS。

9.1.1 LESS和Bootstrap基礎

LESS文件是構建在普通CSS語法之上的一個抽象層,讓開發者可以聲明一個CSS文件最終將會如何使用。你可以把LESS看作一門編程語言,一旦編譯就會產生CSS。在LESS文件裡,可以使用變量、函數和運算符,因此極大地提高了創建和維護大型複雜CSS樣式表的流程效率。

1.變量

開發者使用LESS解決的一大問題是信息的重複。軟件開發者可能深諳“自己不要重複”(Don’t Repeat Yourself, DRY)原則並且每天踐行。DRY的最大好處是減少相同信息保存位置的個數,因而減少應該更新的位置的個數。在普通CSS裡,無法做到DRY。比如,如果特定顏色在多個CSS類裡使用(某些時候要更新),除了在每個出現的地方更新,你可能沒有更好的辦法了。

CSS類的問題在於它們在語義HTML元素的級別工作。在構建各種CSS類時,你通常需要重複小塊信息,比如顏色或寬度。你無法輕易為每個可重複的小塊信息創建一個類。即使每個可重複樣式都有一個CSS類,如顏色和寬度,當把樣式應用到語義元素(如容器)時,需要聯合多個CSS類才能實現預期效果。

考慮以下CSS例子。

.container {
color: #111;
}
.header {
background-color: #111;
}

container和header兩個CSS類都使用相同的顏色。如果那個顏色需要改變,那麼必須找出所有使用它的地方然後編輯。下面使用LESS重寫相同的特性。

@black: #111;
.container {
color: @black;
}
.header {
background-color: @black;
}

現在,這個顏色定義在一個地方,作為全局變量。從這裡來看,LESS把程序員喜歡的概念添加到CSS編碼了,如變量。但它能做的不止這些。

2.導入

可以把LESS代碼分割到多個文件,在需要的時候引用它們。假設創建一個container.less文件,它包含如下內容。

@black: #111;
.container {
background-color: @black;
}

在另一個LESS文件裡,比如main.less,可以通過導入這個文件來引用整個CSS。

@import "container";
.body { .container; }

如果container.less文件(擴展名不是必需的)放在另一個文件夾裡,你應該在調用@import時給出路徑信息。

3.混入(Mixins)

讓CSS樣式適配不同分辨率的能力是很重要的,尤其在網頁必須適配不同屏幕大小時。比如,當按鈕在平板上顯示且針對粗粒度指針(如手指)時,開發者通常會增加按鈕周圍的邊距(padding)。一般來說,如何使相同的CSS類根據某些運行時條件改變並且產生不同的顯示效果,這就是LESS混入派上用場的地方了。

以下是幾個混入示例。

.shadow(@color) {
box-shadow: 3px 3px 2px @color;
}
.text-box(@width) {
.shadow(#555);
border: solid 1px #000;
background-color: #dddd00;
padding: 2px;
width: @width;
}

可以從這裡派生出更加具體的CSS類,如下所示。

.text-box-mini {
.text-box(50px);
}
.text-box-normal {
.text-box(100px);
}
.text-box-large {
.text-box(200px);
}

這正是Bootstrap為了支持常見元素(如按鈕和輸入框)的不同風格在內部做的。

4.把LESS變成CSS

雖然LESS可以用作CSS的元語言,但LESS不是CSS。它必須進行某種處理來生成普通CSS。LESS代碼可以原樣下載並在客戶端通過JavaScript代碼處理,或者也可以在服務器上預處理,然後把普通CSS下載到客戶端。前者像在使用普通CSS文件:服務器端的更改會在下個頁面刷新時應用到客戶端。

但是,如果你有性能顧慮,而且要處理很大很複雜的CSS文件,服務器端預處理可能是個更好的選擇。服務器端預處理會在你每次修改服務器上的CSS時發生。通常,你會在構建流程的最後通過命令行使用LESS編譯器執行額外的步驟。Gulp等工具可以使用JavaScript相關的步驟來擴展構建流程。另一個流行的工具是Microsoft Web Essentials(一個Visual Studio插件),可以用來添加專門的菜單命令、處理CSS和腳本文件等Web資源。

但是,在ASP.NET MVC裡,還有另一種做法。你可以通過捆綁和壓縮機制整合整個LESS框架。在第10章裡,你將會詳細瞭解到,捆綁流程會把多個不同資源打包成單個可下載資源。比如,一個捆綁可能包含多個JavaScript和CSS文件,你可以通過向專門的終結點發送單個HTTP請求把它下載到本地機器。壓縮是應用到資源的特殊轉換。具體來說,壓縮會從文本資源移除所有不必要的字符,但不會改變預期功能。這意味著移除註釋、空白字符、換行符以及所有用於改善可讀性但只佔用空間的非功能性字符。

9.1.2 設置Bootstrap

可以從NuGet獲取Bootstrap。這種情況下,可以只取框架中所需要的部分。Bootstrap通常會用於整個網站,這樣可以從主視圖連接它,如下所示。

<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" src="@Url.Content("~/content/styles/bootstrap.min.css")">

viewport meta標籤把瀏覽器視口(Viewport)的寬度設為實際設備寬度並把放大級別設為標準。link元素只是引入Bootstrap樣式表的壓縮版本。如果打算使用更高級的Bootstrap特性,鑑於這些特性需要JavaScript,可以鏈接腳本文件以及它依賴的jQuery文件。

<script type="text/javascript"
src="@Url.Content("~/content/scripts/jquery-2.1.4.min.js")"></script>
<script type="text/javascript"
src="@Url.Content("~/content/scripts/bootstrap.min.js")"></script>

如果使用完整的Bootstrap庫,一旦鏈接了CSS和腳本文件,就已經準備好了。如果只用Bootstrap庫的部分,則必須確保需要的所有部分都正確鏈接。值得注意的是,Bootstrap庫的某些特性(比如工具提示和彈出界面)需要一些啟動JavaScript代碼,這些代碼必須添加代碼到每個頁面。

■ 注意:

Bootstrap不受老的Internet Explorer兼容模式支持。要確保頁面在Internet Explorer下能以最佳渲染方式查看,最好的辦法是在你的頁面裡添加以下meta標籤。

<meta http-equiv="X-UA-Compatible" content="IE=edge">

Bootstrap的CSS類使用了最新的CSS特性(如圓角效果),這可能不適用於老的瀏覽器。Internet Explorer 8就是部分支持Bootstrap的老瀏覽器的好樣板。

9.1.3 透析Bootstrap

Twitter Bootstrap在今天幾乎是必備的,原因是它使得向現代網站添加高級特性變得快速容易。Bootstrap的學習曲線比較短,很多基於它的模板都是免費的。但對於任何Web設計師而言,自定義基本Bootstrap模板實現獨特的效果也不是什麼難事。

Bootstrap是否適合你的項目取決於外觀的重要性。如果你的客戶需要自己的外觀,Bootstrap可能不是理想的。在這種情況下,開發團隊只收到圖形模板並使用它。此外,Bootstrap非常適合外觀重要但不是根本的快速項目。

換句話說,Bootstrap是一個很好的產品,但無法取代很好的設計。同時,它無法取代為每個設備定義得很好的用戶體驗。很容易找到一些網站提供基於Bootstrap的免費或付費模板。如果你限制自己使用Bootstrap庫的默認樣式(不改變CSS或LESS源代碼),那麼面臨的風險就是所有網站最終看起來都一樣。

要不要使用Bootstrap是一個架構決定,必須在項目早期做,後期很難更改。把Bootstrap添加到正在進行的項目或者從中刪除雖然不是不可能,但也通常有問題。最後,考慮到完整的Bootstrap庫包含100KB的CSS和30KB的腳本,這不是很大的資源,但也不是輕量級資源,尤其是使用較慢連接的較小設備。

Bootstrap的快速普及的其中一個關鍵原因是創建從不同類型設備看起來不錯的頁面成本很低。

■ 注意:

正如你將在第15章中看到的,有兩種截然不同的方式為多個設備設計網站。反應式Web設計是一種讓一套HTML頁面自動適配實際屏幕大小的方案。這是Bootstrap推廣的方案。其他方案為一些關鍵設備創建一套單獨的頁面,最突出的是智能手機。我將會在第16章講述這個話題。

9.2 反應式佈局

今天,所有網站至少都應該反應託管屏幕的寬度變化。作為開發團隊的一員,你有兩種主要方式實現這個功能。你可以從供應商那裡購買一個HTML反應式模板,堅持使用,讓實現細節透明,或者自行開發這個模板。

在後一種情況中,你會使用哪個框架呢?Bootstrap可能是人們應該考慮的第一個框架,但不是唯一的。其他同樣熱門和有效的響應式框架有Foundation、Skeleton和Gumby。任何學習Bootstrap的方案都從它提供的賦予HTML視圖響應式佈局的服務開始。

9.2.1 網格系統

Bootstrap有一個靈活的網格系統,它把水平可用空間分成12等份物理列。Bootstrap提供預定義CSS類,讓你可以通過創建邏輯列隨意佈局模板。換句話說,Bootstrap讓你可以通過一個範圍從1~12個單位的測量系統來安排模板空間。Bootstrap單位的實際大小取決於設備的實際屏幕大小。

屏幕大小實際上是視口——內容的可視化區域。在移動設備上,設備屏幕和視口一致,因為設備通常不支持可調整大小的窗口。而在臺式機上,你可以把窗口的大小調整到比最大可用空間小。在這種情況下,Bootstrap認為視口是可用渲染空間。

1.整體模板

任何Bootstrap內容要響應屏幕大小的改變都會基於行列矩陣。整體容器(這個矩陣)是一個樣式設為container的DIV元素(見圖9-1)。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-1 Bootstrap流體網格的架構

2.容器和行

最外層的容器處理任何必要的對齊,也負責填充。如果你沒有顯式定義一行,就會假設這一行佔滿整個高度。任何用戶界面內容都是放在列中的。注意,只有列允許成為行的直接子元素。Bootstrap中的任何內容通常都會根據以下架構佈局。

容器 > 行 > 列

前面代碼中的每個單詞都是你平常應用到DIV元素的Bootstrap類名。特別地,container管理頁面寬度和填充。row樣式確保內容放在同一行中,多行垂直堆疊。如果你的代碼中沒有行元素,容器中的任何內容都會水平排列,在碰到屏幕邊緣時會換到下一行。

最後,column元素表示行中的單個內容快。Bootstrap為列定義了多個實際類。要定義行中的一個列,你可以根據這個模式使用類名:col-××-N。在這個模式中,××表示設備類型前綴,可以是表9-1中的任何值。很快就會看到,每個××代碼都綁到以像素為單位的特定寬度,也叫斷點(breakpoint)。

"

計算機非人性的一部分表現是,一旦完成編譯並且順利運行,它將忠實地完成工作。

——艾薩克·阿西莫夫

Bootstrap是一個CSS和JavaScript庫,它致力於簡化現代網頁的構建,原本是Twitter開發給內部使用的。但是,“現代網頁”到底是什麼呢?

非常簡單,現代網頁是按照現在大多數用戶想要的樣子構建的網頁。HTML語言仍然是網頁的基礎和核心語言。但是,HTML標記語言的構造越來越不能快速直接地表達構成現代網頁的複雜和成熟。比如,下拉菜單、分段選項按鈕、標籤欄、可摺疊標籤和模態對話框都是大多數頁面的常見元素,卻沒有現成的HTML元素。

Bootstrap提供直接的方式,把HTML塊變成現代網站所需的更加成熟的可視化元素。

9.1 Bootstrap概覽

Bootstrap是一個模塊化的Web庫,由CSS和JavaScript文件組成。CSS文件包含了重新設計常見HTML元素的類,使它們看上去不一樣,或許更好看。JavaScript文件是一組jQuery插件,支持更加複雜的特性,這些特性無法單純通過CSS實現。

Bootstrap最初開發成一組LESS文件,你仍然能夠以LESS文件的方式獲取CSS部分。一般來說,有組成Bootstrap庫的每個模塊的LESS或CSS文件:表單、按鈕、導航欄、對話框等。在深入Bootstrap庫之前,下面先來看看LESS。

9.1.1 LESS和Bootstrap基礎

LESS文件是構建在普通CSS語法之上的一個抽象層,讓開發者可以聲明一個CSS文件最終將會如何使用。你可以把LESS看作一門編程語言,一旦編譯就會產生CSS。在LESS文件裡,可以使用變量、函數和運算符,因此極大地提高了創建和維護大型複雜CSS樣式表的流程效率。

1.變量

開發者使用LESS解決的一大問題是信息的重複。軟件開發者可能深諳“自己不要重複”(Don’t Repeat Yourself, DRY)原則並且每天踐行。DRY的最大好處是減少相同信息保存位置的個數,因而減少應該更新的位置的個數。在普通CSS裡,無法做到DRY。比如,如果特定顏色在多個CSS類裡使用(某些時候要更新),除了在每個出現的地方更新,你可能沒有更好的辦法了。

CSS類的問題在於它們在語義HTML元素的級別工作。在構建各種CSS類時,你通常需要重複小塊信息,比如顏色或寬度。你無法輕易為每個可重複的小塊信息創建一個類。即使每個可重複樣式都有一個CSS類,如顏色和寬度,當把樣式應用到語義元素(如容器)時,需要聯合多個CSS類才能實現預期效果。

考慮以下CSS例子。

.container {
color: #111;
}
.header {
background-color: #111;
}

container和header兩個CSS類都使用相同的顏色。如果那個顏色需要改變,那麼必須找出所有使用它的地方然後編輯。下面使用LESS重寫相同的特性。

@black: #111;
.container {
color: @black;
}
.header {
background-color: @black;
}

現在,這個顏色定義在一個地方,作為全局變量。從這裡來看,LESS把程序員喜歡的概念添加到CSS編碼了,如變量。但它能做的不止這些。

2.導入

可以把LESS代碼分割到多個文件,在需要的時候引用它們。假設創建一個container.less文件,它包含如下內容。

@black: #111;
.container {
background-color: @black;
}

在另一個LESS文件裡,比如main.less,可以通過導入這個文件來引用整個CSS。

@import "container";
.body { .container; }

如果container.less文件(擴展名不是必需的)放在另一個文件夾裡,你應該在調用@import時給出路徑信息。

3.混入(Mixins)

讓CSS樣式適配不同分辨率的能力是很重要的,尤其在網頁必須適配不同屏幕大小時。比如,當按鈕在平板上顯示且針對粗粒度指針(如手指)時,開發者通常會增加按鈕周圍的邊距(padding)。一般來說,如何使相同的CSS類根據某些運行時條件改變並且產生不同的顯示效果,這就是LESS混入派上用場的地方了。

以下是幾個混入示例。

.shadow(@color) {
box-shadow: 3px 3px 2px @color;
}
.text-box(@width) {
.shadow(#555);
border: solid 1px #000;
background-color: #dddd00;
padding: 2px;
width: @width;
}

可以從這裡派生出更加具體的CSS類,如下所示。

.text-box-mini {
.text-box(50px);
}
.text-box-normal {
.text-box(100px);
}
.text-box-large {
.text-box(200px);
}

這正是Bootstrap為了支持常見元素(如按鈕和輸入框)的不同風格在內部做的。

4.把LESS變成CSS

雖然LESS可以用作CSS的元語言,但LESS不是CSS。它必須進行某種處理來生成普通CSS。LESS代碼可以原樣下載並在客戶端通過JavaScript代碼處理,或者也可以在服務器上預處理,然後把普通CSS下載到客戶端。前者像在使用普通CSS文件:服務器端的更改會在下個頁面刷新時應用到客戶端。

但是,如果你有性能顧慮,而且要處理很大很複雜的CSS文件,服務器端預處理可能是個更好的選擇。服務器端預處理會在你每次修改服務器上的CSS時發生。通常,你會在構建流程的最後通過命令行使用LESS編譯器執行額外的步驟。Gulp等工具可以使用JavaScript相關的步驟來擴展構建流程。另一個流行的工具是Microsoft Web Essentials(一個Visual Studio插件),可以用來添加專門的菜單命令、處理CSS和腳本文件等Web資源。

但是,在ASP.NET MVC裡,還有另一種做法。你可以通過捆綁和壓縮機制整合整個LESS框架。在第10章裡,你將會詳細瞭解到,捆綁流程會把多個不同資源打包成單個可下載資源。比如,一個捆綁可能包含多個JavaScript和CSS文件,你可以通過向專門的終結點發送單個HTTP請求把它下載到本地機器。壓縮是應用到資源的特殊轉換。具體來說,壓縮會從文本資源移除所有不必要的字符,但不會改變預期功能。這意味著移除註釋、空白字符、換行符以及所有用於改善可讀性但只佔用空間的非功能性字符。

9.1.2 設置Bootstrap

可以從NuGet獲取Bootstrap。這種情況下,可以只取框架中所需要的部分。Bootstrap通常會用於整個網站,這樣可以從主視圖連接它,如下所示。

<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" src="@Url.Content("~/content/styles/bootstrap.min.css")">

viewport meta標籤把瀏覽器視口(Viewport)的寬度設為實際設備寬度並把放大級別設為標準。link元素只是引入Bootstrap樣式表的壓縮版本。如果打算使用更高級的Bootstrap特性,鑑於這些特性需要JavaScript,可以鏈接腳本文件以及它依賴的jQuery文件。

<script type="text/javascript"
src="@Url.Content("~/content/scripts/jquery-2.1.4.min.js")"></script>
<script type="text/javascript"
src="@Url.Content("~/content/scripts/bootstrap.min.js")"></script>

如果使用完整的Bootstrap庫,一旦鏈接了CSS和腳本文件,就已經準備好了。如果只用Bootstrap庫的部分,則必須確保需要的所有部分都正確鏈接。值得注意的是,Bootstrap庫的某些特性(比如工具提示和彈出界面)需要一些啟動JavaScript代碼,這些代碼必須添加代碼到每個頁面。

■ 注意:

Bootstrap不受老的Internet Explorer兼容模式支持。要確保頁面在Internet Explorer下能以最佳渲染方式查看,最好的辦法是在你的頁面裡添加以下meta標籤。

<meta http-equiv="X-UA-Compatible" content="IE=edge">

Bootstrap的CSS類使用了最新的CSS特性(如圓角效果),這可能不適用於老的瀏覽器。Internet Explorer 8就是部分支持Bootstrap的老瀏覽器的好樣板。

9.1.3 透析Bootstrap

Twitter Bootstrap在今天幾乎是必備的,原因是它使得向現代網站添加高級特性變得快速容易。Bootstrap的學習曲線比較短,很多基於它的模板都是免費的。但對於任何Web設計師而言,自定義基本Bootstrap模板實現獨特的效果也不是什麼難事。

Bootstrap是否適合你的項目取決於外觀的重要性。如果你的客戶需要自己的外觀,Bootstrap可能不是理想的。在這種情況下,開發團隊只收到圖形模板並使用它。此外,Bootstrap非常適合外觀重要但不是根本的快速項目。

換句話說,Bootstrap是一個很好的產品,但無法取代很好的設計。同時,它無法取代為每個設備定義得很好的用戶體驗。很容易找到一些網站提供基於Bootstrap的免費或付費模板。如果你限制自己使用Bootstrap庫的默認樣式(不改變CSS或LESS源代碼),那麼面臨的風險就是所有網站最終看起來都一樣。

要不要使用Bootstrap是一個架構決定,必須在項目早期做,後期很難更改。把Bootstrap添加到正在進行的項目或者從中刪除雖然不是不可能,但也通常有問題。最後,考慮到完整的Bootstrap庫包含100KB的CSS和30KB的腳本,這不是很大的資源,但也不是輕量級資源,尤其是使用較慢連接的較小設備。

Bootstrap的快速普及的其中一個關鍵原因是創建從不同類型設備看起來不錯的頁面成本很低。

■ 注意:

正如你將在第15章中看到的,有兩種截然不同的方式為多個設備設計網站。反應式Web設計是一種讓一套HTML頁面自動適配實際屏幕大小的方案。這是Bootstrap推廣的方案。其他方案為一些關鍵設備創建一套單獨的頁面,最突出的是智能手機。我將會在第16章講述這個話題。

9.2 反應式佈局

今天,所有網站至少都應該反應託管屏幕的寬度變化。作為開發團隊的一員,你有兩種主要方式實現這個功能。你可以從供應商那裡購買一個HTML反應式模板,堅持使用,讓實現細節透明,或者自行開發這個模板。

在後一種情況中,你會使用哪個框架呢?Bootstrap可能是人們應該考慮的第一個框架,但不是唯一的。其他同樣熱門和有效的響應式框架有Foundation、Skeleton和Gumby。任何學習Bootstrap的方案都從它提供的賦予HTML視圖響應式佈局的服務開始。

9.2.1 網格系統

Bootstrap有一個靈活的網格系統,它把水平可用空間分成12等份物理列。Bootstrap提供預定義CSS類,讓你可以通過創建邏輯列隨意佈局模板。換句話說,Bootstrap讓你可以通過一個範圍從1~12個單位的測量系統來安排模板空間。Bootstrap單位的實際大小取決於設備的實際屏幕大小。

屏幕大小實際上是視口——內容的可視化區域。在移動設備上,設備屏幕和視口一致,因為設備通常不支持可調整大小的窗口。而在臺式機上,你可以把窗口的大小調整到比最大可用空間小。在這種情況下,Bootstrap認為視口是可用渲染空間。

1.整體模板

任何Bootstrap內容要響應屏幕大小的改變都會基於行列矩陣。整體容器(這個矩陣)是一個樣式設為container的DIV元素(見圖9-1)。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-1 Bootstrap流體網格的架構

2.容器和行

最外層的容器處理任何必要的對齊,也負責填充。如果你沒有顯式定義一行,就會假設這一行佔滿整個高度。任何用戶界面內容都是放在列中的。注意,只有列允許成為行的直接子元素。Bootstrap中的任何內容通常都會根據以下架構佈局。

容器 > 行 > 列

前面代碼中的每個單詞都是你平常應用到DIV元素的Bootstrap類名。特別地,container管理頁面寬度和填充。row樣式確保內容放在同一行中,多行垂直堆疊。如果你的代碼中沒有行元素,容器中的任何內容都會水平排列,在碰到屏幕邊緣時會換到下一行。

最後,column元素表示行中的單個內容快。Bootstrap為列定義了多個實際類。要定義行中的一個列,你可以根據這個模式使用類名:col-××-N。在這個模式中,××表示設備類型前綴,可以是表9-1中的任何值。很快就會看到,每個××代碼都綁到以像素為單位的特定寬度,也叫斷點(breakpoint)。

全棧工程師Web開發指南:Bootstrap的精髓

模式中的N是一個介於1~12的數字,它表示這列內容在這個虛擬的網格中實際佔用多少列。下面來看一個例子。

<div class="container">
<div class="row">
<div class="col-xs-6 col-md-4"> First </div>
<div class="col-xs-6 col-md-4"> Second </div>
<div class="col-xs-6 col-md-4"> Third </div>
</div>
</div>

在這種情況下,你想在1行中渲染3列布局。所有列都是一樣大小,所有列在中型設備中顯示成一行。col-md-4樣式讓每列在虛擬Bootstrap網格系統裡都佔用4列寬度(一共12列)。

更小和更大的設備呢?

在XS設備上,這3列內容每個都會在渲染時佔據半個屏幕寬度。你可能會想,如果每列都佔據半個屏幕寬度,那麼3列不可能放入整個屏幕寬度。在這裡,第3列會溢出到下一行。同樣的結果會發生在SM設備上。但在LG設備上會使用MD樣式設置的規則。

原則上,流體行中的每列都可以使用多個設備的屬性來為寬度設置樣式。那些屬性對於更大的設備總是適用的,直到出現更特定的設置。鑑於此,如果你不需要按照設備區分佈局,最好一直使用XS樣式。列樣式中的N之和應該總是不超過12。如果超過了,任何超出第12列的列都會溢出到下一行。

3.容器和流體容器

到目前為止,我們只考慮把container類用於DIV元素。還有一個稍微不同的版本你可能在某些情況下會考慮到:container-fluid類。普通容器的每個斷點都是固定寬度的,只有用戶調整瀏覽器大小時跨越了斷點才會改變視口寬度。

而流體容器佔據父元素的全部寬度,通常是100%的瀏覽器可用視口。視口寬度會在每次調整大小時重新計算和更新。在使用流體容器時,用戶體驗會更平滑,但使用流體容器通常對桌面設備更有意義。

9.2.2 基於屏幕大小的渲染

為什麼要使用多列設置呢?答案通常取決於所要展示的實際內容。套用前面的例子,三列布局在中型大小的設備上可能沒問題,但列的內容可能太多而不能在更小屏幕的三分之一上渲染。這就是為什麼我把col-xs-6添加到DIV樣式。最終的效果是,Bootstrap會根據屏幕的實際大小改變最終行為。

在中型和大型設備上,你會有三列布局,在小型和更小設備上每行只有兩列。第三列在小型和更小設備上會換到下一行。如果這不是你想要的,可以考慮在小型和更小設備上隱藏第三列。下面看看怎麼做到。

1.虛擬測量和實際屏幕大小

Bootstrap中的整個網格系統和設備類型都是基於斷點的,見表9-2。如你所見,每個屏幕代碼都關聯了一個表示更小、小型、中型和大型設備預期寬度的斷點。

"

計算機非人性的一部分表現是,一旦完成編譯並且順利運行,它將忠實地完成工作。

——艾薩克·阿西莫夫

Bootstrap是一個CSS和JavaScript庫,它致力於簡化現代網頁的構建,原本是Twitter開發給內部使用的。但是,“現代網頁”到底是什麼呢?

非常簡單,現代網頁是按照現在大多數用戶想要的樣子構建的網頁。HTML語言仍然是網頁的基礎和核心語言。但是,HTML標記語言的構造越來越不能快速直接地表達構成現代網頁的複雜和成熟。比如,下拉菜單、分段選項按鈕、標籤欄、可摺疊標籤和模態對話框都是大多數頁面的常見元素,卻沒有現成的HTML元素。

Bootstrap提供直接的方式,把HTML塊變成現代網站所需的更加成熟的可視化元素。

9.1 Bootstrap概覽

Bootstrap是一個模塊化的Web庫,由CSS和JavaScript文件組成。CSS文件包含了重新設計常見HTML元素的類,使它們看上去不一樣,或許更好看。JavaScript文件是一組jQuery插件,支持更加複雜的特性,這些特性無法單純通過CSS實現。

Bootstrap最初開發成一組LESS文件,你仍然能夠以LESS文件的方式獲取CSS部分。一般來說,有組成Bootstrap庫的每個模塊的LESS或CSS文件:表單、按鈕、導航欄、對話框等。在深入Bootstrap庫之前,下面先來看看LESS。

9.1.1 LESS和Bootstrap基礎

LESS文件是構建在普通CSS語法之上的一個抽象層,讓開發者可以聲明一個CSS文件最終將會如何使用。你可以把LESS看作一門編程語言,一旦編譯就會產生CSS。在LESS文件裡,可以使用變量、函數和運算符,因此極大地提高了創建和維護大型複雜CSS樣式表的流程效率。

1.變量

開發者使用LESS解決的一大問題是信息的重複。軟件開發者可能深諳“自己不要重複”(Don’t Repeat Yourself, DRY)原則並且每天踐行。DRY的最大好處是減少相同信息保存位置的個數,因而減少應該更新的位置的個數。在普通CSS裡,無法做到DRY。比如,如果特定顏色在多個CSS類裡使用(某些時候要更新),除了在每個出現的地方更新,你可能沒有更好的辦法了。

CSS類的問題在於它們在語義HTML元素的級別工作。在構建各種CSS類時,你通常需要重複小塊信息,比如顏色或寬度。你無法輕易為每個可重複的小塊信息創建一個類。即使每個可重複樣式都有一個CSS類,如顏色和寬度,當把樣式應用到語義元素(如容器)時,需要聯合多個CSS類才能實現預期效果。

考慮以下CSS例子。

.container {
color: #111;
}
.header {
background-color: #111;
}

container和header兩個CSS類都使用相同的顏色。如果那個顏色需要改變,那麼必須找出所有使用它的地方然後編輯。下面使用LESS重寫相同的特性。

@black: #111;
.container {
color: @black;
}
.header {
background-color: @black;
}

現在,這個顏色定義在一個地方,作為全局變量。從這裡來看,LESS把程序員喜歡的概念添加到CSS編碼了,如變量。但它能做的不止這些。

2.導入

可以把LESS代碼分割到多個文件,在需要的時候引用它們。假設創建一個container.less文件,它包含如下內容。

@black: #111;
.container {
background-color: @black;
}

在另一個LESS文件裡,比如main.less,可以通過導入這個文件來引用整個CSS。

@import "container";
.body { .container; }

如果container.less文件(擴展名不是必需的)放在另一個文件夾裡,你應該在調用@import時給出路徑信息。

3.混入(Mixins)

讓CSS樣式適配不同分辨率的能力是很重要的,尤其在網頁必須適配不同屏幕大小時。比如,當按鈕在平板上顯示且針對粗粒度指針(如手指)時,開發者通常會增加按鈕周圍的邊距(padding)。一般來說,如何使相同的CSS類根據某些運行時條件改變並且產生不同的顯示效果,這就是LESS混入派上用場的地方了。

以下是幾個混入示例。

.shadow(@color) {
box-shadow: 3px 3px 2px @color;
}
.text-box(@width) {
.shadow(#555);
border: solid 1px #000;
background-color: #dddd00;
padding: 2px;
width: @width;
}

可以從這裡派生出更加具體的CSS類,如下所示。

.text-box-mini {
.text-box(50px);
}
.text-box-normal {
.text-box(100px);
}
.text-box-large {
.text-box(200px);
}

這正是Bootstrap為了支持常見元素(如按鈕和輸入框)的不同風格在內部做的。

4.把LESS變成CSS

雖然LESS可以用作CSS的元語言,但LESS不是CSS。它必須進行某種處理來生成普通CSS。LESS代碼可以原樣下載並在客戶端通過JavaScript代碼處理,或者也可以在服務器上預處理,然後把普通CSS下載到客戶端。前者像在使用普通CSS文件:服務器端的更改會在下個頁面刷新時應用到客戶端。

但是,如果你有性能顧慮,而且要處理很大很複雜的CSS文件,服務器端預處理可能是個更好的選擇。服務器端預處理會在你每次修改服務器上的CSS時發生。通常,你會在構建流程的最後通過命令行使用LESS編譯器執行額外的步驟。Gulp等工具可以使用JavaScript相關的步驟來擴展構建流程。另一個流行的工具是Microsoft Web Essentials(一個Visual Studio插件),可以用來添加專門的菜單命令、處理CSS和腳本文件等Web資源。

但是,在ASP.NET MVC裡,還有另一種做法。你可以通過捆綁和壓縮機制整合整個LESS框架。在第10章裡,你將會詳細瞭解到,捆綁流程會把多個不同資源打包成單個可下載資源。比如,一個捆綁可能包含多個JavaScript和CSS文件,你可以通過向專門的終結點發送單個HTTP請求把它下載到本地機器。壓縮是應用到資源的特殊轉換。具體來說,壓縮會從文本資源移除所有不必要的字符,但不會改變預期功能。這意味著移除註釋、空白字符、換行符以及所有用於改善可讀性但只佔用空間的非功能性字符。

9.1.2 設置Bootstrap

可以從NuGet獲取Bootstrap。這種情況下,可以只取框架中所需要的部分。Bootstrap通常會用於整個網站,這樣可以從主視圖連接它,如下所示。

<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" src="@Url.Content("~/content/styles/bootstrap.min.css")">

viewport meta標籤把瀏覽器視口(Viewport)的寬度設為實際設備寬度並把放大級別設為標準。link元素只是引入Bootstrap樣式表的壓縮版本。如果打算使用更高級的Bootstrap特性,鑑於這些特性需要JavaScript,可以鏈接腳本文件以及它依賴的jQuery文件。

<script type="text/javascript"
src="@Url.Content("~/content/scripts/jquery-2.1.4.min.js")"></script>
<script type="text/javascript"
src="@Url.Content("~/content/scripts/bootstrap.min.js")"></script>

如果使用完整的Bootstrap庫,一旦鏈接了CSS和腳本文件,就已經準備好了。如果只用Bootstrap庫的部分,則必須確保需要的所有部分都正確鏈接。值得注意的是,Bootstrap庫的某些特性(比如工具提示和彈出界面)需要一些啟動JavaScript代碼,這些代碼必須添加代碼到每個頁面。

■ 注意:

Bootstrap不受老的Internet Explorer兼容模式支持。要確保頁面在Internet Explorer下能以最佳渲染方式查看,最好的辦法是在你的頁面裡添加以下meta標籤。

<meta http-equiv="X-UA-Compatible" content="IE=edge">

Bootstrap的CSS類使用了最新的CSS特性(如圓角效果),這可能不適用於老的瀏覽器。Internet Explorer 8就是部分支持Bootstrap的老瀏覽器的好樣板。

9.1.3 透析Bootstrap

Twitter Bootstrap在今天幾乎是必備的,原因是它使得向現代網站添加高級特性變得快速容易。Bootstrap的學習曲線比較短,很多基於它的模板都是免費的。但對於任何Web設計師而言,自定義基本Bootstrap模板實現獨特的效果也不是什麼難事。

Bootstrap是否適合你的項目取決於外觀的重要性。如果你的客戶需要自己的外觀,Bootstrap可能不是理想的。在這種情況下,開發團隊只收到圖形模板並使用它。此外,Bootstrap非常適合外觀重要但不是根本的快速項目。

換句話說,Bootstrap是一個很好的產品,但無法取代很好的設計。同時,它無法取代為每個設備定義得很好的用戶體驗。很容易找到一些網站提供基於Bootstrap的免費或付費模板。如果你限制自己使用Bootstrap庫的默認樣式(不改變CSS或LESS源代碼),那麼面臨的風險就是所有網站最終看起來都一樣。

要不要使用Bootstrap是一個架構決定,必須在項目早期做,後期很難更改。把Bootstrap添加到正在進行的項目或者從中刪除雖然不是不可能,但也通常有問題。最後,考慮到完整的Bootstrap庫包含100KB的CSS和30KB的腳本,這不是很大的資源,但也不是輕量級資源,尤其是使用較慢連接的較小設備。

Bootstrap的快速普及的其中一個關鍵原因是創建從不同類型設備看起來不錯的頁面成本很低。

■ 注意:

正如你將在第15章中看到的,有兩種截然不同的方式為多個設備設計網站。反應式Web設計是一種讓一套HTML頁面自動適配實際屏幕大小的方案。這是Bootstrap推廣的方案。其他方案為一些關鍵設備創建一套單獨的頁面,最突出的是智能手機。我將會在第16章講述這個話題。

9.2 反應式佈局

今天,所有網站至少都應該反應託管屏幕的寬度變化。作為開發團隊的一員,你有兩種主要方式實現這個功能。你可以從供應商那裡購買一個HTML反應式模板,堅持使用,讓實現細節透明,或者自行開發這個模板。

在後一種情況中,你會使用哪個框架呢?Bootstrap可能是人們應該考慮的第一個框架,但不是唯一的。其他同樣熱門和有效的響應式框架有Foundation、Skeleton和Gumby。任何學習Bootstrap的方案都從它提供的賦予HTML視圖響應式佈局的服務開始。

9.2.1 網格系統

Bootstrap有一個靈活的網格系統,它把水平可用空間分成12等份物理列。Bootstrap提供預定義CSS類,讓你可以通過創建邏輯列隨意佈局模板。換句話說,Bootstrap讓你可以通過一個範圍從1~12個單位的測量系統來安排模板空間。Bootstrap單位的實際大小取決於設備的實際屏幕大小。

屏幕大小實際上是視口——內容的可視化區域。在移動設備上,設備屏幕和視口一致,因為設備通常不支持可調整大小的窗口。而在臺式機上,你可以把窗口的大小調整到比最大可用空間小。在這種情況下,Bootstrap認為視口是可用渲染空間。

1.整體模板

任何Bootstrap內容要響應屏幕大小的改變都會基於行列矩陣。整體容器(這個矩陣)是一個樣式設為container的DIV元素(見圖9-1)。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-1 Bootstrap流體網格的架構

2.容器和行

最外層的容器處理任何必要的對齊,也負責填充。如果你沒有顯式定義一行,就會假設這一行佔滿整個高度。任何用戶界面內容都是放在列中的。注意,只有列允許成為行的直接子元素。Bootstrap中的任何內容通常都會根據以下架構佈局。

容器 > 行 > 列

前面代碼中的每個單詞都是你平常應用到DIV元素的Bootstrap類名。特別地,container管理頁面寬度和填充。row樣式確保內容放在同一行中,多行垂直堆疊。如果你的代碼中沒有行元素,容器中的任何內容都會水平排列,在碰到屏幕邊緣時會換到下一行。

最後,column元素表示行中的單個內容快。Bootstrap為列定義了多個實際類。要定義行中的一個列,你可以根據這個模式使用類名:col-××-N。在這個模式中,××表示設備類型前綴,可以是表9-1中的任何值。很快就會看到,每個××代碼都綁到以像素為單位的特定寬度,也叫斷點(breakpoint)。

全棧工程師Web開發指南:Bootstrap的精髓

模式中的N是一個介於1~12的數字,它表示這列內容在這個虛擬的網格中實際佔用多少列。下面來看一個例子。

<div class="container">
<div class="row">
<div class="col-xs-6 col-md-4"> First </div>
<div class="col-xs-6 col-md-4"> Second </div>
<div class="col-xs-6 col-md-4"> Third </div>
</div>
</div>

在這種情況下,你想在1行中渲染3列布局。所有列都是一樣大小,所有列在中型設備中顯示成一行。col-md-4樣式讓每列在虛擬Bootstrap網格系統裡都佔用4列寬度(一共12列)。

更小和更大的設備呢?

在XS設備上,這3列內容每個都會在渲染時佔據半個屏幕寬度。你可能會想,如果每列都佔據半個屏幕寬度,那麼3列不可能放入整個屏幕寬度。在這裡,第3列會溢出到下一行。同樣的結果會發生在SM設備上。但在LG設備上會使用MD樣式設置的規則。

原則上,流體行中的每列都可以使用多個設備的屬性來為寬度設置樣式。那些屬性對於更大的設備總是適用的,直到出現更特定的設置。鑑於此,如果你不需要按照設備區分佈局,最好一直使用XS樣式。列樣式中的N之和應該總是不超過12。如果超過了,任何超出第12列的列都會溢出到下一行。

3.容器和流體容器

到目前為止,我們只考慮把container類用於DIV元素。還有一個稍微不同的版本你可能在某些情況下會考慮到:container-fluid類。普通容器的每個斷點都是固定寬度的,只有用戶調整瀏覽器大小時跨越了斷點才會改變視口寬度。

而流體容器佔據父元素的全部寬度,通常是100%的瀏覽器可用視口。視口寬度會在每次調整大小時重新計算和更新。在使用流體容器時,用戶體驗會更平滑,但使用流體容器通常對桌面設備更有意義。

9.2.2 基於屏幕大小的渲染

為什麼要使用多列設置呢?答案通常取決於所要展示的實際內容。套用前面的例子,三列布局在中型大小的設備上可能沒問題,但列的內容可能太多而不能在更小屏幕的三分之一上渲染。這就是為什麼我把col-xs-6添加到DIV樣式。最終的效果是,Bootstrap會根據屏幕的實際大小改變最終行為。

在中型和大型設備上,你會有三列布局,在小型和更小設備上每行只有兩列。第三列在小型和更小設備上會換到下一行。如果這不是你想要的,可以考慮在小型和更小設備上隱藏第三列。下面看看怎麼做到。

1.虛擬測量和實際屏幕大小

Bootstrap中的整個網格系統和設備類型都是基於斷點的,見表9-2。如你所見,每個屏幕代碼都關聯了一個表示更小、小型、中型和大型設備預期寬度的斷點。

全棧工程師Web開發指南:Bootstrap的精髓

如果不指定col-xx-n樣式,會默認XS屏幕。對這些代碼類別的常見反應是Bootstrap不能讓你輕鬆處理這裡列出的非常小的設備,即768像素或更小的寬度。老設備落入這個範圍,它們可能需要和寬度大於768像素的更大設備不同的特定處理。

要監視Bootstrap如何改變頁面佈局,可以使用以下腳本代碼,只要把它添加到一個網頁就行了。

<script type="text/javascript">
updateSize();
$(window).resize(function() {
updateSize();
});
function currentBootstrapScreenClass() {
var screen = "LG";
var width = $(window).width();
if (width <= 768)
screen = "XS";
else if (width <= 992)
screen = "SM";
else if (width <= 1200)
screen = "MD";
return screen;
}
function updateSize() {
var info = currentBootstrapScreenClass();
$('#currentScreenWidth').text($(window).width() + "px");
$('#currentViewport').text(info);
}
</script>

顯然,這個網頁必須一些匹配一下ID的元素。

<span id="currentScreenWidth"></span>
<span id="currentViewport"></span>

效果如圖9-2所示。

"

計算機非人性的一部分表現是,一旦完成編譯並且順利運行,它將忠實地完成工作。

——艾薩克·阿西莫夫

Bootstrap是一個CSS和JavaScript庫,它致力於簡化現代網頁的構建,原本是Twitter開發給內部使用的。但是,“現代網頁”到底是什麼呢?

非常簡單,現代網頁是按照現在大多數用戶想要的樣子構建的網頁。HTML語言仍然是網頁的基礎和核心語言。但是,HTML標記語言的構造越來越不能快速直接地表達構成現代網頁的複雜和成熟。比如,下拉菜單、分段選項按鈕、標籤欄、可摺疊標籤和模態對話框都是大多數頁面的常見元素,卻沒有現成的HTML元素。

Bootstrap提供直接的方式,把HTML塊變成現代網站所需的更加成熟的可視化元素。

9.1 Bootstrap概覽

Bootstrap是一個模塊化的Web庫,由CSS和JavaScript文件組成。CSS文件包含了重新設計常見HTML元素的類,使它們看上去不一樣,或許更好看。JavaScript文件是一組jQuery插件,支持更加複雜的特性,這些特性無法單純通過CSS實現。

Bootstrap最初開發成一組LESS文件,你仍然能夠以LESS文件的方式獲取CSS部分。一般來說,有組成Bootstrap庫的每個模塊的LESS或CSS文件:表單、按鈕、導航欄、對話框等。在深入Bootstrap庫之前,下面先來看看LESS。

9.1.1 LESS和Bootstrap基礎

LESS文件是構建在普通CSS語法之上的一個抽象層,讓開發者可以聲明一個CSS文件最終將會如何使用。你可以把LESS看作一門編程語言,一旦編譯就會產生CSS。在LESS文件裡,可以使用變量、函數和運算符,因此極大地提高了創建和維護大型複雜CSS樣式表的流程效率。

1.變量

開發者使用LESS解決的一大問題是信息的重複。軟件開發者可能深諳“自己不要重複”(Don’t Repeat Yourself, DRY)原則並且每天踐行。DRY的最大好處是減少相同信息保存位置的個數,因而減少應該更新的位置的個數。在普通CSS裡,無法做到DRY。比如,如果特定顏色在多個CSS類裡使用(某些時候要更新),除了在每個出現的地方更新,你可能沒有更好的辦法了。

CSS類的問題在於它們在語義HTML元素的級別工作。在構建各種CSS類時,你通常需要重複小塊信息,比如顏色或寬度。你無法輕易為每個可重複的小塊信息創建一個類。即使每個可重複樣式都有一個CSS類,如顏色和寬度,當把樣式應用到語義元素(如容器)時,需要聯合多個CSS類才能實現預期效果。

考慮以下CSS例子。

.container {
color: #111;
}
.header {
background-color: #111;
}

container和header兩個CSS類都使用相同的顏色。如果那個顏色需要改變,那麼必須找出所有使用它的地方然後編輯。下面使用LESS重寫相同的特性。

@black: #111;
.container {
color: @black;
}
.header {
background-color: @black;
}

現在,這個顏色定義在一個地方,作為全局變量。從這裡來看,LESS把程序員喜歡的概念添加到CSS編碼了,如變量。但它能做的不止這些。

2.導入

可以把LESS代碼分割到多個文件,在需要的時候引用它們。假設創建一個container.less文件,它包含如下內容。

@black: #111;
.container {
background-color: @black;
}

在另一個LESS文件裡,比如main.less,可以通過導入這個文件來引用整個CSS。

@import "container";
.body { .container; }

如果container.less文件(擴展名不是必需的)放在另一個文件夾裡,你應該在調用@import時給出路徑信息。

3.混入(Mixins)

讓CSS樣式適配不同分辨率的能力是很重要的,尤其在網頁必須適配不同屏幕大小時。比如,當按鈕在平板上顯示且針對粗粒度指針(如手指)時,開發者通常會增加按鈕周圍的邊距(padding)。一般來說,如何使相同的CSS類根據某些運行時條件改變並且產生不同的顯示效果,這就是LESS混入派上用場的地方了。

以下是幾個混入示例。

.shadow(@color) {
box-shadow: 3px 3px 2px @color;
}
.text-box(@width) {
.shadow(#555);
border: solid 1px #000;
background-color: #dddd00;
padding: 2px;
width: @width;
}

可以從這裡派生出更加具體的CSS類,如下所示。

.text-box-mini {
.text-box(50px);
}
.text-box-normal {
.text-box(100px);
}
.text-box-large {
.text-box(200px);
}

這正是Bootstrap為了支持常見元素(如按鈕和輸入框)的不同風格在內部做的。

4.把LESS變成CSS

雖然LESS可以用作CSS的元語言,但LESS不是CSS。它必須進行某種處理來生成普通CSS。LESS代碼可以原樣下載並在客戶端通過JavaScript代碼處理,或者也可以在服務器上預處理,然後把普通CSS下載到客戶端。前者像在使用普通CSS文件:服務器端的更改會在下個頁面刷新時應用到客戶端。

但是,如果你有性能顧慮,而且要處理很大很複雜的CSS文件,服務器端預處理可能是個更好的選擇。服務器端預處理會在你每次修改服務器上的CSS時發生。通常,你會在構建流程的最後通過命令行使用LESS編譯器執行額外的步驟。Gulp等工具可以使用JavaScript相關的步驟來擴展構建流程。另一個流行的工具是Microsoft Web Essentials(一個Visual Studio插件),可以用來添加專門的菜單命令、處理CSS和腳本文件等Web資源。

但是,在ASP.NET MVC裡,還有另一種做法。你可以通過捆綁和壓縮機制整合整個LESS框架。在第10章裡,你將會詳細瞭解到,捆綁流程會把多個不同資源打包成單個可下載資源。比如,一個捆綁可能包含多個JavaScript和CSS文件,你可以通過向專門的終結點發送單個HTTP請求把它下載到本地機器。壓縮是應用到資源的特殊轉換。具體來說,壓縮會從文本資源移除所有不必要的字符,但不會改變預期功能。這意味著移除註釋、空白字符、換行符以及所有用於改善可讀性但只佔用空間的非功能性字符。

9.1.2 設置Bootstrap

可以從NuGet獲取Bootstrap。這種情況下,可以只取框架中所需要的部分。Bootstrap通常會用於整個網站,這樣可以從主視圖連接它,如下所示。

<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" src="@Url.Content("~/content/styles/bootstrap.min.css")">

viewport meta標籤把瀏覽器視口(Viewport)的寬度設為實際設備寬度並把放大級別設為標準。link元素只是引入Bootstrap樣式表的壓縮版本。如果打算使用更高級的Bootstrap特性,鑑於這些特性需要JavaScript,可以鏈接腳本文件以及它依賴的jQuery文件。

<script type="text/javascript"
src="@Url.Content("~/content/scripts/jquery-2.1.4.min.js")"></script>
<script type="text/javascript"
src="@Url.Content("~/content/scripts/bootstrap.min.js")"></script>

如果使用完整的Bootstrap庫,一旦鏈接了CSS和腳本文件,就已經準備好了。如果只用Bootstrap庫的部分,則必須確保需要的所有部分都正確鏈接。值得注意的是,Bootstrap庫的某些特性(比如工具提示和彈出界面)需要一些啟動JavaScript代碼,這些代碼必須添加代碼到每個頁面。

■ 注意:

Bootstrap不受老的Internet Explorer兼容模式支持。要確保頁面在Internet Explorer下能以最佳渲染方式查看,最好的辦法是在你的頁面裡添加以下meta標籤。

<meta http-equiv="X-UA-Compatible" content="IE=edge">

Bootstrap的CSS類使用了最新的CSS特性(如圓角效果),這可能不適用於老的瀏覽器。Internet Explorer 8就是部分支持Bootstrap的老瀏覽器的好樣板。

9.1.3 透析Bootstrap

Twitter Bootstrap在今天幾乎是必備的,原因是它使得向現代網站添加高級特性變得快速容易。Bootstrap的學習曲線比較短,很多基於它的模板都是免費的。但對於任何Web設計師而言,自定義基本Bootstrap模板實現獨特的效果也不是什麼難事。

Bootstrap是否適合你的項目取決於外觀的重要性。如果你的客戶需要自己的外觀,Bootstrap可能不是理想的。在這種情況下,開發團隊只收到圖形模板並使用它。此外,Bootstrap非常適合外觀重要但不是根本的快速項目。

換句話說,Bootstrap是一個很好的產品,但無法取代很好的設計。同時,它無法取代為每個設備定義得很好的用戶體驗。很容易找到一些網站提供基於Bootstrap的免費或付費模板。如果你限制自己使用Bootstrap庫的默認樣式(不改變CSS或LESS源代碼),那麼面臨的風險就是所有網站最終看起來都一樣。

要不要使用Bootstrap是一個架構決定,必須在項目早期做,後期很難更改。把Bootstrap添加到正在進行的項目或者從中刪除雖然不是不可能,但也通常有問題。最後,考慮到完整的Bootstrap庫包含100KB的CSS和30KB的腳本,這不是很大的資源,但也不是輕量級資源,尤其是使用較慢連接的較小設備。

Bootstrap的快速普及的其中一個關鍵原因是創建從不同類型設備看起來不錯的頁面成本很低。

■ 注意:

正如你將在第15章中看到的,有兩種截然不同的方式為多個設備設計網站。反應式Web設計是一種讓一套HTML頁面自動適配實際屏幕大小的方案。這是Bootstrap推廣的方案。其他方案為一些關鍵設備創建一套單獨的頁面,最突出的是智能手機。我將會在第16章講述這個話題。

9.2 反應式佈局

今天,所有網站至少都應該反應託管屏幕的寬度變化。作為開發團隊的一員,你有兩種主要方式實現這個功能。你可以從供應商那裡購買一個HTML反應式模板,堅持使用,讓實現細節透明,或者自行開發這個模板。

在後一種情況中,你會使用哪個框架呢?Bootstrap可能是人們應該考慮的第一個框架,但不是唯一的。其他同樣熱門和有效的響應式框架有Foundation、Skeleton和Gumby。任何學習Bootstrap的方案都從它提供的賦予HTML視圖響應式佈局的服務開始。

9.2.1 網格系統

Bootstrap有一個靈活的網格系統,它把水平可用空間分成12等份物理列。Bootstrap提供預定義CSS類,讓你可以通過創建邏輯列隨意佈局模板。換句話說,Bootstrap讓你可以通過一個範圍從1~12個單位的測量系統來安排模板空間。Bootstrap單位的實際大小取決於設備的實際屏幕大小。

屏幕大小實際上是視口——內容的可視化區域。在移動設備上,設備屏幕和視口一致,因為設備通常不支持可調整大小的窗口。而在臺式機上,你可以把窗口的大小調整到比最大可用空間小。在這種情況下,Bootstrap認為視口是可用渲染空間。

1.整體模板

任何Bootstrap內容要響應屏幕大小的改變都會基於行列矩陣。整體容器(這個矩陣)是一個樣式設為container的DIV元素(見圖9-1)。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-1 Bootstrap流體網格的架構

2.容器和行

最外層的容器處理任何必要的對齊,也負責填充。如果你沒有顯式定義一行,就會假設這一行佔滿整個高度。任何用戶界面內容都是放在列中的。注意,只有列允許成為行的直接子元素。Bootstrap中的任何內容通常都會根據以下架構佈局。

容器 > 行 > 列

前面代碼中的每個單詞都是你平常應用到DIV元素的Bootstrap類名。特別地,container管理頁面寬度和填充。row樣式確保內容放在同一行中,多行垂直堆疊。如果你的代碼中沒有行元素,容器中的任何內容都會水平排列,在碰到屏幕邊緣時會換到下一行。

最後,column元素表示行中的單個內容快。Bootstrap為列定義了多個實際類。要定義行中的一個列,你可以根據這個模式使用類名:col-××-N。在這個模式中,××表示設備類型前綴,可以是表9-1中的任何值。很快就會看到,每個××代碼都綁到以像素為單位的特定寬度,也叫斷點(breakpoint)。

全棧工程師Web開發指南:Bootstrap的精髓

模式中的N是一個介於1~12的數字,它表示這列內容在這個虛擬的網格中實際佔用多少列。下面來看一個例子。

<div class="container">
<div class="row">
<div class="col-xs-6 col-md-4"> First </div>
<div class="col-xs-6 col-md-4"> Second </div>
<div class="col-xs-6 col-md-4"> Third </div>
</div>
</div>

在這種情況下,你想在1行中渲染3列布局。所有列都是一樣大小,所有列在中型設備中顯示成一行。col-md-4樣式讓每列在虛擬Bootstrap網格系統裡都佔用4列寬度(一共12列)。

更小和更大的設備呢?

在XS設備上,這3列內容每個都會在渲染時佔據半個屏幕寬度。你可能會想,如果每列都佔據半個屏幕寬度,那麼3列不可能放入整個屏幕寬度。在這裡,第3列會溢出到下一行。同樣的結果會發生在SM設備上。但在LG設備上會使用MD樣式設置的規則。

原則上,流體行中的每列都可以使用多個設備的屬性來為寬度設置樣式。那些屬性對於更大的設備總是適用的,直到出現更特定的設置。鑑於此,如果你不需要按照設備區分佈局,最好一直使用XS樣式。列樣式中的N之和應該總是不超過12。如果超過了,任何超出第12列的列都會溢出到下一行。

3.容器和流體容器

到目前為止,我們只考慮把container類用於DIV元素。還有一個稍微不同的版本你可能在某些情況下會考慮到:container-fluid類。普通容器的每個斷點都是固定寬度的,只有用戶調整瀏覽器大小時跨越了斷點才會改變視口寬度。

而流體容器佔據父元素的全部寬度,通常是100%的瀏覽器可用視口。視口寬度會在每次調整大小時重新計算和更新。在使用流體容器時,用戶體驗會更平滑,但使用流體容器通常對桌面設備更有意義。

9.2.2 基於屏幕大小的渲染

為什麼要使用多列設置呢?答案通常取決於所要展示的實際內容。套用前面的例子,三列布局在中型大小的設備上可能沒問題,但列的內容可能太多而不能在更小屏幕的三分之一上渲染。這就是為什麼我把col-xs-6添加到DIV樣式。最終的效果是,Bootstrap會根據屏幕的實際大小改變最終行為。

在中型和大型設備上,你會有三列布局,在小型和更小設備上每行只有兩列。第三列在小型和更小設備上會換到下一行。如果這不是你想要的,可以考慮在小型和更小設備上隱藏第三列。下面看看怎麼做到。

1.虛擬測量和實際屏幕大小

Bootstrap中的整個網格系統和設備類型都是基於斷點的,見表9-2。如你所見,每個屏幕代碼都關聯了一個表示更小、小型、中型和大型設備預期寬度的斷點。

全棧工程師Web開發指南:Bootstrap的精髓

如果不指定col-xx-n樣式,會默認XS屏幕。對這些代碼類別的常見反應是Bootstrap不能讓你輕鬆處理這裡列出的非常小的設備,即768像素或更小的寬度。老設備落入這個範圍,它們可能需要和寬度大於768像素的更大設備不同的特定處理。

要監視Bootstrap如何改變頁面佈局,可以使用以下腳本代碼,只要把它添加到一個網頁就行了。

<script type="text/javascript">
updateSize();
$(window).resize(function() {
updateSize();
});
function currentBootstrapScreenClass() {
var screen = "LG";
var width = $(window).width();
if (width <= 768)
screen = "XS";
else if (width <= 992)
screen = "SM";
else if (width <= 1200)
screen = "MD";
return screen;
}
function updateSize() {
var info = currentBootstrapScreenClass();
$('#currentScreenWidth').text($(window).width() + "px");
$('#currentViewport').text(info);
}
</script>

顯然,這個網頁必須一些匹配一下ID的元素。

<span id="currentScreenWidth"></span>
<span id="currentViewport"></span>

效果如圖9-2所示。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-2 屏幕大小和Bootstrap類之間的關係

col-xx-n類是Bootstrap提供的讓頁面佈局適配屏幕大小的主要工具。還有更強大的工具可以針對特定屏幕大小隱藏和嵌套列。

2.多分辨率視圖

如前所述,就列布局而言,你可以把多個設置賦給容器和行。下面來看一個有趣的例子。

<div class="container">
<div class="row">
<div class="col-xs-6 col-md-4"> Column #1 <br /> Column #1 <br /></div>
<div class="col-xs-6 col-md-4"> Column #2 </div>
<div class="col-md-4"> Column #3 </div>
</div>
</div>

第一列在XS和SM模式中佔據了一半空間,在MD和LG模式中佔據了三分之一。但是,第一列的內容包含了一些BR元素,讓該列比其他列高。在MD和LG中,顯示效果跟預期的完全一樣,三列都在一行中。但在XS和SM中,第三列會在哪顯示?看看圖9-3。

"

計算機非人性的一部分表現是,一旦完成編譯並且順利運行,它將忠實地完成工作。

——艾薩克·阿西莫夫

Bootstrap是一個CSS和JavaScript庫,它致力於簡化現代網頁的構建,原本是Twitter開發給內部使用的。但是,“現代網頁”到底是什麼呢?

非常簡單,現代網頁是按照現在大多數用戶想要的樣子構建的網頁。HTML語言仍然是網頁的基礎和核心語言。但是,HTML標記語言的構造越來越不能快速直接地表達構成現代網頁的複雜和成熟。比如,下拉菜單、分段選項按鈕、標籤欄、可摺疊標籤和模態對話框都是大多數頁面的常見元素,卻沒有現成的HTML元素。

Bootstrap提供直接的方式,把HTML塊變成現代網站所需的更加成熟的可視化元素。

9.1 Bootstrap概覽

Bootstrap是一個模塊化的Web庫,由CSS和JavaScript文件組成。CSS文件包含了重新設計常見HTML元素的類,使它們看上去不一樣,或許更好看。JavaScript文件是一組jQuery插件,支持更加複雜的特性,這些特性無法單純通過CSS實現。

Bootstrap最初開發成一組LESS文件,你仍然能夠以LESS文件的方式獲取CSS部分。一般來說,有組成Bootstrap庫的每個模塊的LESS或CSS文件:表單、按鈕、導航欄、對話框等。在深入Bootstrap庫之前,下面先來看看LESS。

9.1.1 LESS和Bootstrap基礎

LESS文件是構建在普通CSS語法之上的一個抽象層,讓開發者可以聲明一個CSS文件最終將會如何使用。你可以把LESS看作一門編程語言,一旦編譯就會產生CSS。在LESS文件裡,可以使用變量、函數和運算符,因此極大地提高了創建和維護大型複雜CSS樣式表的流程效率。

1.變量

開發者使用LESS解決的一大問題是信息的重複。軟件開發者可能深諳“自己不要重複”(Don’t Repeat Yourself, DRY)原則並且每天踐行。DRY的最大好處是減少相同信息保存位置的個數,因而減少應該更新的位置的個數。在普通CSS裡,無法做到DRY。比如,如果特定顏色在多個CSS類裡使用(某些時候要更新),除了在每個出現的地方更新,你可能沒有更好的辦法了。

CSS類的問題在於它們在語義HTML元素的級別工作。在構建各種CSS類時,你通常需要重複小塊信息,比如顏色或寬度。你無法輕易為每個可重複的小塊信息創建一個類。即使每個可重複樣式都有一個CSS類,如顏色和寬度,當把樣式應用到語義元素(如容器)時,需要聯合多個CSS類才能實現預期效果。

考慮以下CSS例子。

.container {
color: #111;
}
.header {
background-color: #111;
}

container和header兩個CSS類都使用相同的顏色。如果那個顏色需要改變,那麼必須找出所有使用它的地方然後編輯。下面使用LESS重寫相同的特性。

@black: #111;
.container {
color: @black;
}
.header {
background-color: @black;
}

現在,這個顏色定義在一個地方,作為全局變量。從這裡來看,LESS把程序員喜歡的概念添加到CSS編碼了,如變量。但它能做的不止這些。

2.導入

可以把LESS代碼分割到多個文件,在需要的時候引用它們。假設創建一個container.less文件,它包含如下內容。

@black: #111;
.container {
background-color: @black;
}

在另一個LESS文件裡,比如main.less,可以通過導入這個文件來引用整個CSS。

@import "container";
.body { .container; }

如果container.less文件(擴展名不是必需的)放在另一個文件夾裡,你應該在調用@import時給出路徑信息。

3.混入(Mixins)

讓CSS樣式適配不同分辨率的能力是很重要的,尤其在網頁必須適配不同屏幕大小時。比如,當按鈕在平板上顯示且針對粗粒度指針(如手指)時,開發者通常會增加按鈕周圍的邊距(padding)。一般來說,如何使相同的CSS類根據某些運行時條件改變並且產生不同的顯示效果,這就是LESS混入派上用場的地方了。

以下是幾個混入示例。

.shadow(@color) {
box-shadow: 3px 3px 2px @color;
}
.text-box(@width) {
.shadow(#555);
border: solid 1px #000;
background-color: #dddd00;
padding: 2px;
width: @width;
}

可以從這裡派生出更加具體的CSS類,如下所示。

.text-box-mini {
.text-box(50px);
}
.text-box-normal {
.text-box(100px);
}
.text-box-large {
.text-box(200px);
}

這正是Bootstrap為了支持常見元素(如按鈕和輸入框)的不同風格在內部做的。

4.把LESS變成CSS

雖然LESS可以用作CSS的元語言,但LESS不是CSS。它必須進行某種處理來生成普通CSS。LESS代碼可以原樣下載並在客戶端通過JavaScript代碼處理,或者也可以在服務器上預處理,然後把普通CSS下載到客戶端。前者像在使用普通CSS文件:服務器端的更改會在下個頁面刷新時應用到客戶端。

但是,如果你有性能顧慮,而且要處理很大很複雜的CSS文件,服務器端預處理可能是個更好的選擇。服務器端預處理會在你每次修改服務器上的CSS時發生。通常,你會在構建流程的最後通過命令行使用LESS編譯器執行額外的步驟。Gulp等工具可以使用JavaScript相關的步驟來擴展構建流程。另一個流行的工具是Microsoft Web Essentials(一個Visual Studio插件),可以用來添加專門的菜單命令、處理CSS和腳本文件等Web資源。

但是,在ASP.NET MVC裡,還有另一種做法。你可以通過捆綁和壓縮機制整合整個LESS框架。在第10章裡,你將會詳細瞭解到,捆綁流程會把多個不同資源打包成單個可下載資源。比如,一個捆綁可能包含多個JavaScript和CSS文件,你可以通過向專門的終結點發送單個HTTP請求把它下載到本地機器。壓縮是應用到資源的特殊轉換。具體來說,壓縮會從文本資源移除所有不必要的字符,但不會改變預期功能。這意味著移除註釋、空白字符、換行符以及所有用於改善可讀性但只佔用空間的非功能性字符。

9.1.2 設置Bootstrap

可以從NuGet獲取Bootstrap。這種情況下,可以只取框架中所需要的部分。Bootstrap通常會用於整個網站,這樣可以從主視圖連接它,如下所示。

<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" src="@Url.Content("~/content/styles/bootstrap.min.css")">

viewport meta標籤把瀏覽器視口(Viewport)的寬度設為實際設備寬度並把放大級別設為標準。link元素只是引入Bootstrap樣式表的壓縮版本。如果打算使用更高級的Bootstrap特性,鑑於這些特性需要JavaScript,可以鏈接腳本文件以及它依賴的jQuery文件。

<script type="text/javascript"
src="@Url.Content("~/content/scripts/jquery-2.1.4.min.js")"></script>
<script type="text/javascript"
src="@Url.Content("~/content/scripts/bootstrap.min.js")"></script>

如果使用完整的Bootstrap庫,一旦鏈接了CSS和腳本文件,就已經準備好了。如果只用Bootstrap庫的部分,則必須確保需要的所有部分都正確鏈接。值得注意的是,Bootstrap庫的某些特性(比如工具提示和彈出界面)需要一些啟動JavaScript代碼,這些代碼必須添加代碼到每個頁面。

■ 注意:

Bootstrap不受老的Internet Explorer兼容模式支持。要確保頁面在Internet Explorer下能以最佳渲染方式查看,最好的辦法是在你的頁面裡添加以下meta標籤。

<meta http-equiv="X-UA-Compatible" content="IE=edge">

Bootstrap的CSS類使用了最新的CSS特性(如圓角效果),這可能不適用於老的瀏覽器。Internet Explorer 8就是部分支持Bootstrap的老瀏覽器的好樣板。

9.1.3 透析Bootstrap

Twitter Bootstrap在今天幾乎是必備的,原因是它使得向現代網站添加高級特性變得快速容易。Bootstrap的學習曲線比較短,很多基於它的模板都是免費的。但對於任何Web設計師而言,自定義基本Bootstrap模板實現獨特的效果也不是什麼難事。

Bootstrap是否適合你的項目取決於外觀的重要性。如果你的客戶需要自己的外觀,Bootstrap可能不是理想的。在這種情況下,開發團隊只收到圖形模板並使用它。此外,Bootstrap非常適合外觀重要但不是根本的快速項目。

換句話說,Bootstrap是一個很好的產品,但無法取代很好的設計。同時,它無法取代為每個設備定義得很好的用戶體驗。很容易找到一些網站提供基於Bootstrap的免費或付費模板。如果你限制自己使用Bootstrap庫的默認樣式(不改變CSS或LESS源代碼),那麼面臨的風險就是所有網站最終看起來都一樣。

要不要使用Bootstrap是一個架構決定,必須在項目早期做,後期很難更改。把Bootstrap添加到正在進行的項目或者從中刪除雖然不是不可能,但也通常有問題。最後,考慮到完整的Bootstrap庫包含100KB的CSS和30KB的腳本,這不是很大的資源,但也不是輕量級資源,尤其是使用較慢連接的較小設備。

Bootstrap的快速普及的其中一個關鍵原因是創建從不同類型設備看起來不錯的頁面成本很低。

■ 注意:

正如你將在第15章中看到的,有兩種截然不同的方式為多個設備設計網站。反應式Web設計是一種讓一套HTML頁面自動適配實際屏幕大小的方案。這是Bootstrap推廣的方案。其他方案為一些關鍵設備創建一套單獨的頁面,最突出的是智能手機。我將會在第16章講述這個話題。

9.2 反應式佈局

今天,所有網站至少都應該反應託管屏幕的寬度變化。作為開發團隊的一員,你有兩種主要方式實現這個功能。你可以從供應商那裡購買一個HTML反應式模板,堅持使用,讓實現細節透明,或者自行開發這個模板。

在後一種情況中,你會使用哪個框架呢?Bootstrap可能是人們應該考慮的第一個框架,但不是唯一的。其他同樣熱門和有效的響應式框架有Foundation、Skeleton和Gumby。任何學習Bootstrap的方案都從它提供的賦予HTML視圖響應式佈局的服務開始。

9.2.1 網格系統

Bootstrap有一個靈活的網格系統,它把水平可用空間分成12等份物理列。Bootstrap提供預定義CSS類,讓你可以通過創建邏輯列隨意佈局模板。換句話說,Bootstrap讓你可以通過一個範圍從1~12個單位的測量系統來安排模板空間。Bootstrap單位的實際大小取決於設備的實際屏幕大小。

屏幕大小實際上是視口——內容的可視化區域。在移動設備上,設備屏幕和視口一致,因為設備通常不支持可調整大小的窗口。而在臺式機上,你可以把窗口的大小調整到比最大可用空間小。在這種情況下,Bootstrap認為視口是可用渲染空間。

1.整體模板

任何Bootstrap內容要響應屏幕大小的改變都會基於行列矩陣。整體容器(這個矩陣)是一個樣式設為container的DIV元素(見圖9-1)。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-1 Bootstrap流體網格的架構

2.容器和行

最外層的容器處理任何必要的對齊,也負責填充。如果你沒有顯式定義一行,就會假設這一行佔滿整個高度。任何用戶界面內容都是放在列中的。注意,只有列允許成為行的直接子元素。Bootstrap中的任何內容通常都會根據以下架構佈局。

容器 > 行 > 列

前面代碼中的每個單詞都是你平常應用到DIV元素的Bootstrap類名。特別地,container管理頁面寬度和填充。row樣式確保內容放在同一行中,多行垂直堆疊。如果你的代碼中沒有行元素,容器中的任何內容都會水平排列,在碰到屏幕邊緣時會換到下一行。

最後,column元素表示行中的單個內容快。Bootstrap為列定義了多個實際類。要定義行中的一個列,你可以根據這個模式使用類名:col-××-N。在這個模式中,××表示設備類型前綴,可以是表9-1中的任何值。很快就會看到,每個××代碼都綁到以像素為單位的特定寬度,也叫斷點(breakpoint)。

全棧工程師Web開發指南:Bootstrap的精髓

模式中的N是一個介於1~12的數字,它表示這列內容在這個虛擬的網格中實際佔用多少列。下面來看一個例子。

<div class="container">
<div class="row">
<div class="col-xs-6 col-md-4"> First </div>
<div class="col-xs-6 col-md-4"> Second </div>
<div class="col-xs-6 col-md-4"> Third </div>
</div>
</div>

在這種情況下,你想在1行中渲染3列布局。所有列都是一樣大小,所有列在中型設備中顯示成一行。col-md-4樣式讓每列在虛擬Bootstrap網格系統裡都佔用4列寬度(一共12列)。

更小和更大的設備呢?

在XS設備上,這3列內容每個都會在渲染時佔據半個屏幕寬度。你可能會想,如果每列都佔據半個屏幕寬度,那麼3列不可能放入整個屏幕寬度。在這裡,第3列會溢出到下一行。同樣的結果會發生在SM設備上。但在LG設備上會使用MD樣式設置的規則。

原則上,流體行中的每列都可以使用多個設備的屬性來為寬度設置樣式。那些屬性對於更大的設備總是適用的,直到出現更特定的設置。鑑於此,如果你不需要按照設備區分佈局,最好一直使用XS樣式。列樣式中的N之和應該總是不超過12。如果超過了,任何超出第12列的列都會溢出到下一行。

3.容器和流體容器

到目前為止,我們只考慮把container類用於DIV元素。還有一個稍微不同的版本你可能在某些情況下會考慮到:container-fluid類。普通容器的每個斷點都是固定寬度的,只有用戶調整瀏覽器大小時跨越了斷點才會改變視口寬度。

而流體容器佔據父元素的全部寬度,通常是100%的瀏覽器可用視口。視口寬度會在每次調整大小時重新計算和更新。在使用流體容器時,用戶體驗會更平滑,但使用流體容器通常對桌面設備更有意義。

9.2.2 基於屏幕大小的渲染

為什麼要使用多列設置呢?答案通常取決於所要展示的實際內容。套用前面的例子,三列布局在中型大小的設備上可能沒問題,但列的內容可能太多而不能在更小屏幕的三分之一上渲染。這就是為什麼我把col-xs-6添加到DIV樣式。最終的效果是,Bootstrap會根據屏幕的實際大小改變最終行為。

在中型和大型設備上,你會有三列布局,在小型和更小設備上每行只有兩列。第三列在小型和更小設備上會換到下一行。如果這不是你想要的,可以考慮在小型和更小設備上隱藏第三列。下面看看怎麼做到。

1.虛擬測量和實際屏幕大小

Bootstrap中的整個網格系統和設備類型都是基於斷點的,見表9-2。如你所見,每個屏幕代碼都關聯了一個表示更小、小型、中型和大型設備預期寬度的斷點。

全棧工程師Web開發指南:Bootstrap的精髓

如果不指定col-xx-n樣式,會默認XS屏幕。對這些代碼類別的常見反應是Bootstrap不能讓你輕鬆處理這裡列出的非常小的設備,即768像素或更小的寬度。老設備落入這個範圍,它們可能需要和寬度大於768像素的更大設備不同的特定處理。

要監視Bootstrap如何改變頁面佈局,可以使用以下腳本代碼,只要把它添加到一個網頁就行了。

<script type="text/javascript">
updateSize();
$(window).resize(function() {
updateSize();
});
function currentBootstrapScreenClass() {
var screen = "LG";
var width = $(window).width();
if (width <= 768)
screen = "XS";
else if (width <= 992)
screen = "SM";
else if (width <= 1200)
screen = "MD";
return screen;
}
function updateSize() {
var info = currentBootstrapScreenClass();
$('#currentScreenWidth').text($(window).width() + "px");
$('#currentViewport').text(info);
}
</script>

顯然,這個網頁必須一些匹配一下ID的元素。

<span id="currentScreenWidth"></span>
<span id="currentViewport"></span>

效果如圖9-2所示。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-2 屏幕大小和Bootstrap類之間的關係

col-xx-n類是Bootstrap提供的讓頁面佈局適配屏幕大小的主要工具。還有更強大的工具可以針對特定屏幕大小隱藏和嵌套列。

2.多分辨率視圖

如前所述,就列布局而言,你可以把多個設置賦給容器和行。下面來看一個有趣的例子。

<div class="container">
<div class="row">
<div class="col-xs-6 col-md-4"> Column #1 <br /> Column #1 <br /></div>
<div class="col-xs-6 col-md-4"> Column #2 </div>
<div class="col-md-4"> Column #3 </div>
</div>
</div>

第一列在XS和SM模式中佔據了一半空間,在MD和LG模式中佔據了三分之一。但是,第一列的內容包含了一些BR元素,讓該列比其他列高。在MD和LG中,顯示效果跟預期的完全一樣,三列都在一行中。但在XS和SM中,第三列會在哪顯示?看看圖9-3。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-3 第三列浮在行的左側佔據任何可用的空間

在XS和SM模式中,前兩列由於它們的col-xs-6類佔據了整個屏幕。結果,第三列流到下一行。但是,在這個特例中,第一列比其他的高,這會留出右邊的空間。Bootstrap重用屏幕實際空間來放置換到下一行的列。

一般來說,每當使用col-xx-n類時候,實際上是把CSS的float屬性設為left(或right)並讓瀏覽器找出最左(或最右)可用空間來放置特定元素。注意,要向右對齊,你只需把pull-right類添加到目標元素。

3.特定大小的類

如果想強制第三列去到下一行最左呢?你要顯式停用默認對齊,恢復DIV元素的區塊性質。在純CSS中,通過使用clear:both屬性的空DIV可以實現這點。這在Bootstrap中對應clearfix類。

<div class="clearfix"></div>

圖9-4展示瞭如果盲目使用clearfix類來強制第三列在下一行開始將會得到什麼。

"

計算機非人性的一部分表現是,一旦完成編譯並且順利運行,它將忠實地完成工作。

——艾薩克·阿西莫夫

Bootstrap是一個CSS和JavaScript庫,它致力於簡化現代網頁的構建,原本是Twitter開發給內部使用的。但是,“現代網頁”到底是什麼呢?

非常簡單,現代網頁是按照現在大多數用戶想要的樣子構建的網頁。HTML語言仍然是網頁的基礎和核心語言。但是,HTML標記語言的構造越來越不能快速直接地表達構成現代網頁的複雜和成熟。比如,下拉菜單、分段選項按鈕、標籤欄、可摺疊標籤和模態對話框都是大多數頁面的常見元素,卻沒有現成的HTML元素。

Bootstrap提供直接的方式,把HTML塊變成現代網站所需的更加成熟的可視化元素。

9.1 Bootstrap概覽

Bootstrap是一個模塊化的Web庫,由CSS和JavaScript文件組成。CSS文件包含了重新設計常見HTML元素的類,使它們看上去不一樣,或許更好看。JavaScript文件是一組jQuery插件,支持更加複雜的特性,這些特性無法單純通過CSS實現。

Bootstrap最初開發成一組LESS文件,你仍然能夠以LESS文件的方式獲取CSS部分。一般來說,有組成Bootstrap庫的每個模塊的LESS或CSS文件:表單、按鈕、導航欄、對話框等。在深入Bootstrap庫之前,下面先來看看LESS。

9.1.1 LESS和Bootstrap基礎

LESS文件是構建在普通CSS語法之上的一個抽象層,讓開發者可以聲明一個CSS文件最終將會如何使用。你可以把LESS看作一門編程語言,一旦編譯就會產生CSS。在LESS文件裡,可以使用變量、函數和運算符,因此極大地提高了創建和維護大型複雜CSS樣式表的流程效率。

1.變量

開發者使用LESS解決的一大問題是信息的重複。軟件開發者可能深諳“自己不要重複”(Don’t Repeat Yourself, DRY)原則並且每天踐行。DRY的最大好處是減少相同信息保存位置的個數,因而減少應該更新的位置的個數。在普通CSS裡,無法做到DRY。比如,如果特定顏色在多個CSS類裡使用(某些時候要更新),除了在每個出現的地方更新,你可能沒有更好的辦法了。

CSS類的問題在於它們在語義HTML元素的級別工作。在構建各種CSS類時,你通常需要重複小塊信息,比如顏色或寬度。你無法輕易為每個可重複的小塊信息創建一個類。即使每個可重複樣式都有一個CSS類,如顏色和寬度,當把樣式應用到語義元素(如容器)時,需要聯合多個CSS類才能實現預期效果。

考慮以下CSS例子。

.container {
color: #111;
}
.header {
background-color: #111;
}

container和header兩個CSS類都使用相同的顏色。如果那個顏色需要改變,那麼必須找出所有使用它的地方然後編輯。下面使用LESS重寫相同的特性。

@black: #111;
.container {
color: @black;
}
.header {
background-color: @black;
}

現在,這個顏色定義在一個地方,作為全局變量。從這裡來看,LESS把程序員喜歡的概念添加到CSS編碼了,如變量。但它能做的不止這些。

2.導入

可以把LESS代碼分割到多個文件,在需要的時候引用它們。假設創建一個container.less文件,它包含如下內容。

@black: #111;
.container {
background-color: @black;
}

在另一個LESS文件裡,比如main.less,可以通過導入這個文件來引用整個CSS。

@import "container";
.body { .container; }

如果container.less文件(擴展名不是必需的)放在另一個文件夾裡,你應該在調用@import時給出路徑信息。

3.混入(Mixins)

讓CSS樣式適配不同分辨率的能力是很重要的,尤其在網頁必須適配不同屏幕大小時。比如,當按鈕在平板上顯示且針對粗粒度指針(如手指)時,開發者通常會增加按鈕周圍的邊距(padding)。一般來說,如何使相同的CSS類根據某些運行時條件改變並且產生不同的顯示效果,這就是LESS混入派上用場的地方了。

以下是幾個混入示例。

.shadow(@color) {
box-shadow: 3px 3px 2px @color;
}
.text-box(@width) {
.shadow(#555);
border: solid 1px #000;
background-color: #dddd00;
padding: 2px;
width: @width;
}

可以從這裡派生出更加具體的CSS類,如下所示。

.text-box-mini {
.text-box(50px);
}
.text-box-normal {
.text-box(100px);
}
.text-box-large {
.text-box(200px);
}

這正是Bootstrap為了支持常見元素(如按鈕和輸入框)的不同風格在內部做的。

4.把LESS變成CSS

雖然LESS可以用作CSS的元語言,但LESS不是CSS。它必須進行某種處理來生成普通CSS。LESS代碼可以原樣下載並在客戶端通過JavaScript代碼處理,或者也可以在服務器上預處理,然後把普通CSS下載到客戶端。前者像在使用普通CSS文件:服務器端的更改會在下個頁面刷新時應用到客戶端。

但是,如果你有性能顧慮,而且要處理很大很複雜的CSS文件,服務器端預處理可能是個更好的選擇。服務器端預處理會在你每次修改服務器上的CSS時發生。通常,你會在構建流程的最後通過命令行使用LESS編譯器執行額外的步驟。Gulp等工具可以使用JavaScript相關的步驟來擴展構建流程。另一個流行的工具是Microsoft Web Essentials(一個Visual Studio插件),可以用來添加專門的菜單命令、處理CSS和腳本文件等Web資源。

但是,在ASP.NET MVC裡,還有另一種做法。你可以通過捆綁和壓縮機制整合整個LESS框架。在第10章裡,你將會詳細瞭解到,捆綁流程會把多個不同資源打包成單個可下載資源。比如,一個捆綁可能包含多個JavaScript和CSS文件,你可以通過向專門的終結點發送單個HTTP請求把它下載到本地機器。壓縮是應用到資源的特殊轉換。具體來說,壓縮會從文本資源移除所有不必要的字符,但不會改變預期功能。這意味著移除註釋、空白字符、換行符以及所有用於改善可讀性但只佔用空間的非功能性字符。

9.1.2 設置Bootstrap

可以從NuGet獲取Bootstrap。這種情況下,可以只取框架中所需要的部分。Bootstrap通常會用於整個網站,這樣可以從主視圖連接它,如下所示。

<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" src="@Url.Content("~/content/styles/bootstrap.min.css")">

viewport meta標籤把瀏覽器視口(Viewport)的寬度設為實際設備寬度並把放大級別設為標準。link元素只是引入Bootstrap樣式表的壓縮版本。如果打算使用更高級的Bootstrap特性,鑑於這些特性需要JavaScript,可以鏈接腳本文件以及它依賴的jQuery文件。

<script type="text/javascript"
src="@Url.Content("~/content/scripts/jquery-2.1.4.min.js")"></script>
<script type="text/javascript"
src="@Url.Content("~/content/scripts/bootstrap.min.js")"></script>

如果使用完整的Bootstrap庫,一旦鏈接了CSS和腳本文件,就已經準備好了。如果只用Bootstrap庫的部分,則必須確保需要的所有部分都正確鏈接。值得注意的是,Bootstrap庫的某些特性(比如工具提示和彈出界面)需要一些啟動JavaScript代碼,這些代碼必須添加代碼到每個頁面。

■ 注意:

Bootstrap不受老的Internet Explorer兼容模式支持。要確保頁面在Internet Explorer下能以最佳渲染方式查看,最好的辦法是在你的頁面裡添加以下meta標籤。

<meta http-equiv="X-UA-Compatible" content="IE=edge">

Bootstrap的CSS類使用了最新的CSS特性(如圓角效果),這可能不適用於老的瀏覽器。Internet Explorer 8就是部分支持Bootstrap的老瀏覽器的好樣板。

9.1.3 透析Bootstrap

Twitter Bootstrap在今天幾乎是必備的,原因是它使得向現代網站添加高級特性變得快速容易。Bootstrap的學習曲線比較短,很多基於它的模板都是免費的。但對於任何Web設計師而言,自定義基本Bootstrap模板實現獨特的效果也不是什麼難事。

Bootstrap是否適合你的項目取決於外觀的重要性。如果你的客戶需要自己的外觀,Bootstrap可能不是理想的。在這種情況下,開發團隊只收到圖形模板並使用它。此外,Bootstrap非常適合外觀重要但不是根本的快速項目。

換句話說,Bootstrap是一個很好的產品,但無法取代很好的設計。同時,它無法取代為每個設備定義得很好的用戶體驗。很容易找到一些網站提供基於Bootstrap的免費或付費模板。如果你限制自己使用Bootstrap庫的默認樣式(不改變CSS或LESS源代碼),那麼面臨的風險就是所有網站最終看起來都一樣。

要不要使用Bootstrap是一個架構決定,必須在項目早期做,後期很難更改。把Bootstrap添加到正在進行的項目或者從中刪除雖然不是不可能,但也通常有問題。最後,考慮到完整的Bootstrap庫包含100KB的CSS和30KB的腳本,這不是很大的資源,但也不是輕量級資源,尤其是使用較慢連接的較小設備。

Bootstrap的快速普及的其中一個關鍵原因是創建從不同類型設備看起來不錯的頁面成本很低。

■ 注意:

正如你將在第15章中看到的,有兩種截然不同的方式為多個設備設計網站。反應式Web設計是一種讓一套HTML頁面自動適配實際屏幕大小的方案。這是Bootstrap推廣的方案。其他方案為一些關鍵設備創建一套單獨的頁面,最突出的是智能手機。我將會在第16章講述這個話題。

9.2 反應式佈局

今天,所有網站至少都應該反應託管屏幕的寬度變化。作為開發團隊的一員,你有兩種主要方式實現這個功能。你可以從供應商那裡購買一個HTML反應式模板,堅持使用,讓實現細節透明,或者自行開發這個模板。

在後一種情況中,你會使用哪個框架呢?Bootstrap可能是人們應該考慮的第一個框架,但不是唯一的。其他同樣熱門和有效的響應式框架有Foundation、Skeleton和Gumby。任何學習Bootstrap的方案都從它提供的賦予HTML視圖響應式佈局的服務開始。

9.2.1 網格系統

Bootstrap有一個靈活的網格系統,它把水平可用空間分成12等份物理列。Bootstrap提供預定義CSS類,讓你可以通過創建邏輯列隨意佈局模板。換句話說,Bootstrap讓你可以通過一個範圍從1~12個單位的測量系統來安排模板空間。Bootstrap單位的實際大小取決於設備的實際屏幕大小。

屏幕大小實際上是視口——內容的可視化區域。在移動設備上,設備屏幕和視口一致,因為設備通常不支持可調整大小的窗口。而在臺式機上,你可以把窗口的大小調整到比最大可用空間小。在這種情況下,Bootstrap認為視口是可用渲染空間。

1.整體模板

任何Bootstrap內容要響應屏幕大小的改變都會基於行列矩陣。整體容器(這個矩陣)是一個樣式設為container的DIV元素(見圖9-1)。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-1 Bootstrap流體網格的架構

2.容器和行

最外層的容器處理任何必要的對齊,也負責填充。如果你沒有顯式定義一行,就會假設這一行佔滿整個高度。任何用戶界面內容都是放在列中的。注意,只有列允許成為行的直接子元素。Bootstrap中的任何內容通常都會根據以下架構佈局。

容器 > 行 > 列

前面代碼中的每個單詞都是你平常應用到DIV元素的Bootstrap類名。特別地,container管理頁面寬度和填充。row樣式確保內容放在同一行中,多行垂直堆疊。如果你的代碼中沒有行元素,容器中的任何內容都會水平排列,在碰到屏幕邊緣時會換到下一行。

最後,column元素表示行中的單個內容快。Bootstrap為列定義了多個實際類。要定義行中的一個列,你可以根據這個模式使用類名:col-××-N。在這個模式中,××表示設備類型前綴,可以是表9-1中的任何值。很快就會看到,每個××代碼都綁到以像素為單位的特定寬度,也叫斷點(breakpoint)。

全棧工程師Web開發指南:Bootstrap的精髓

模式中的N是一個介於1~12的數字,它表示這列內容在這個虛擬的網格中實際佔用多少列。下面來看一個例子。

<div class="container">
<div class="row">
<div class="col-xs-6 col-md-4"> First </div>
<div class="col-xs-6 col-md-4"> Second </div>
<div class="col-xs-6 col-md-4"> Third </div>
</div>
</div>

在這種情況下,你想在1行中渲染3列布局。所有列都是一樣大小,所有列在中型設備中顯示成一行。col-md-4樣式讓每列在虛擬Bootstrap網格系統裡都佔用4列寬度(一共12列)。

更小和更大的設備呢?

在XS設備上,這3列內容每個都會在渲染時佔據半個屏幕寬度。你可能會想,如果每列都佔據半個屏幕寬度,那麼3列不可能放入整個屏幕寬度。在這裡,第3列會溢出到下一行。同樣的結果會發生在SM設備上。但在LG設備上會使用MD樣式設置的規則。

原則上,流體行中的每列都可以使用多個設備的屬性來為寬度設置樣式。那些屬性對於更大的設備總是適用的,直到出現更特定的設置。鑑於此,如果你不需要按照設備區分佈局,最好一直使用XS樣式。列樣式中的N之和應該總是不超過12。如果超過了,任何超出第12列的列都會溢出到下一行。

3.容器和流體容器

到目前為止,我們只考慮把container類用於DIV元素。還有一個稍微不同的版本你可能在某些情況下會考慮到:container-fluid類。普通容器的每個斷點都是固定寬度的,只有用戶調整瀏覽器大小時跨越了斷點才會改變視口寬度。

而流體容器佔據父元素的全部寬度,通常是100%的瀏覽器可用視口。視口寬度會在每次調整大小時重新計算和更新。在使用流體容器時,用戶體驗會更平滑,但使用流體容器通常對桌面設備更有意義。

9.2.2 基於屏幕大小的渲染

為什麼要使用多列設置呢?答案通常取決於所要展示的實際內容。套用前面的例子,三列布局在中型大小的設備上可能沒問題,但列的內容可能太多而不能在更小屏幕的三分之一上渲染。這就是為什麼我把col-xs-6添加到DIV樣式。最終的效果是,Bootstrap會根據屏幕的實際大小改變最終行為。

在中型和大型設備上,你會有三列布局,在小型和更小設備上每行只有兩列。第三列在小型和更小設備上會換到下一行。如果這不是你想要的,可以考慮在小型和更小設備上隱藏第三列。下面看看怎麼做到。

1.虛擬測量和實際屏幕大小

Bootstrap中的整個網格系統和設備類型都是基於斷點的,見表9-2。如你所見,每個屏幕代碼都關聯了一個表示更小、小型、中型和大型設備預期寬度的斷點。

全棧工程師Web開發指南:Bootstrap的精髓

如果不指定col-xx-n樣式,會默認XS屏幕。對這些代碼類別的常見反應是Bootstrap不能讓你輕鬆處理這裡列出的非常小的設備,即768像素或更小的寬度。老設備落入這個範圍,它們可能需要和寬度大於768像素的更大設備不同的特定處理。

要監視Bootstrap如何改變頁面佈局,可以使用以下腳本代碼,只要把它添加到一個網頁就行了。

<script type="text/javascript">
updateSize();
$(window).resize(function() {
updateSize();
});
function currentBootstrapScreenClass() {
var screen = "LG";
var width = $(window).width();
if (width <= 768)
screen = "XS";
else if (width <= 992)
screen = "SM";
else if (width <= 1200)
screen = "MD";
return screen;
}
function updateSize() {
var info = currentBootstrapScreenClass();
$('#currentScreenWidth').text($(window).width() + "px");
$('#currentViewport').text(info);
}
</script>

顯然,這個網頁必須一些匹配一下ID的元素。

<span id="currentScreenWidth"></span>
<span id="currentViewport"></span>

效果如圖9-2所示。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-2 屏幕大小和Bootstrap類之間的關係

col-xx-n類是Bootstrap提供的讓頁面佈局適配屏幕大小的主要工具。還有更強大的工具可以針對特定屏幕大小隱藏和嵌套列。

2.多分辨率視圖

如前所述,就列布局而言,你可以把多個設置賦給容器和行。下面來看一個有趣的例子。

<div class="container">
<div class="row">
<div class="col-xs-6 col-md-4"> Column #1 <br /> Column #1 <br /></div>
<div class="col-xs-6 col-md-4"> Column #2 </div>
<div class="col-md-4"> Column #3 </div>
</div>
</div>

第一列在XS和SM模式中佔據了一半空間,在MD和LG模式中佔據了三分之一。但是,第一列的內容包含了一些BR元素,讓該列比其他列高。在MD和LG中,顯示效果跟預期的完全一樣,三列都在一行中。但在XS和SM中,第三列會在哪顯示?看看圖9-3。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-3 第三列浮在行的左側佔據任何可用的空間

在XS和SM模式中,前兩列由於它們的col-xs-6類佔據了整個屏幕。結果,第三列流到下一行。但是,在這個特例中,第一列比其他的高,這會留出右邊的空間。Bootstrap重用屏幕實際空間來放置換到下一行的列。

一般來說,每當使用col-xx-n類時候,實際上是把CSS的float屬性設為left(或right)並讓瀏覽器找出最左(或最右)可用空間來放置特定元素。注意,要向右對齊,你只需把pull-right類添加到目標元素。

3.特定大小的類

如果想強制第三列去到下一行最左呢?你要顯式停用默認對齊,恢復DIV元素的區塊性質。在純CSS中,通過使用clear:both屬性的空DIV可以實現這點。這在Bootstrap中對應clearfix類。

<div class="clearfix"></div>

圖9-4展示瞭如果盲目使用clearfix類來強制第三列在下一行開始將會得到什麼。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-4 第三列現在從下一行最左邊開始

如果調整瀏覽器的窗口大小到XS或SM模式,一切如常。但是,圖9-4只展示了MD和LG模式的樣子。如你所見,使用clearfix類會留出右邊的空間,這裡本來可以放得下第三列。理想情況下,你可能想清除DIV元素的浮動樣式,但只針對XS和SM模式。

在Bootstrap中,visible-xx類和hidden-xx類就是為此而來的。

<div class="clearfix visible-xs"></div>

現在的效果就是你想要的。使用clearfix類的DIV現在只會在XS和SM屏幕上才會出現。類似的,你可以使用hidden-xx類隱藏元素和整行。

■ 注意:

hidden-xx類本身是Bootstrap提供的一個強大的工具,可以讓你創建專門的響應式Web模板,用來在用戶調整視口時或者在較小的全屏設備上查看內容時調整這些內容。我將會在第15章詳細講述響應式Web設計的代價是隱藏不想要的內容。這個效果對於用戶來說是好的,但對於應用程序來說是不必要的,尤其是在移動設備上使用RWD。

4.靈活渲染

下面簡單看看使用hidden-xx類的具體例子。假設你有一個登錄表單,在經典的用戶名/密碼錶單週圍有很多介紹文字和一幅圖片。

<div class="container">
<h1 class="hidden-xs">WELCOME to CONTOSO Industries</h1>
<h4 class="visible-xs">WELCOME to CONTOSO</h4>
<div class="col-md-4 hidden-xs hidden-sm">
<div class="center">
<img src="~/Content/Images/contoso.png" />
</div>
</div>
</div>

圖9-5展示了這個登錄表單在LG屏幕上的樣子。

"

計算機非人性的一部分表現是,一旦完成編譯並且順利運行,它將忠實地完成工作。

——艾薩克·阿西莫夫

Bootstrap是一個CSS和JavaScript庫,它致力於簡化現代網頁的構建,原本是Twitter開發給內部使用的。但是,“現代網頁”到底是什麼呢?

非常簡單,現代網頁是按照現在大多數用戶想要的樣子構建的網頁。HTML語言仍然是網頁的基礎和核心語言。但是,HTML標記語言的構造越來越不能快速直接地表達構成現代網頁的複雜和成熟。比如,下拉菜單、分段選項按鈕、標籤欄、可摺疊標籤和模態對話框都是大多數頁面的常見元素,卻沒有現成的HTML元素。

Bootstrap提供直接的方式,把HTML塊變成現代網站所需的更加成熟的可視化元素。

9.1 Bootstrap概覽

Bootstrap是一個模塊化的Web庫,由CSS和JavaScript文件組成。CSS文件包含了重新設計常見HTML元素的類,使它們看上去不一樣,或許更好看。JavaScript文件是一組jQuery插件,支持更加複雜的特性,這些特性無法單純通過CSS實現。

Bootstrap最初開發成一組LESS文件,你仍然能夠以LESS文件的方式獲取CSS部分。一般來說,有組成Bootstrap庫的每個模塊的LESS或CSS文件:表單、按鈕、導航欄、對話框等。在深入Bootstrap庫之前,下面先來看看LESS。

9.1.1 LESS和Bootstrap基礎

LESS文件是構建在普通CSS語法之上的一個抽象層,讓開發者可以聲明一個CSS文件最終將會如何使用。你可以把LESS看作一門編程語言,一旦編譯就會產生CSS。在LESS文件裡,可以使用變量、函數和運算符,因此極大地提高了創建和維護大型複雜CSS樣式表的流程效率。

1.變量

開發者使用LESS解決的一大問題是信息的重複。軟件開發者可能深諳“自己不要重複”(Don’t Repeat Yourself, DRY)原則並且每天踐行。DRY的最大好處是減少相同信息保存位置的個數,因而減少應該更新的位置的個數。在普通CSS裡,無法做到DRY。比如,如果特定顏色在多個CSS類裡使用(某些時候要更新),除了在每個出現的地方更新,你可能沒有更好的辦法了。

CSS類的問題在於它們在語義HTML元素的級別工作。在構建各種CSS類時,你通常需要重複小塊信息,比如顏色或寬度。你無法輕易為每個可重複的小塊信息創建一個類。即使每個可重複樣式都有一個CSS類,如顏色和寬度,當把樣式應用到語義元素(如容器)時,需要聯合多個CSS類才能實現預期效果。

考慮以下CSS例子。

.container {
color: #111;
}
.header {
background-color: #111;
}

container和header兩個CSS類都使用相同的顏色。如果那個顏色需要改變,那麼必須找出所有使用它的地方然後編輯。下面使用LESS重寫相同的特性。

@black: #111;
.container {
color: @black;
}
.header {
background-color: @black;
}

現在,這個顏色定義在一個地方,作為全局變量。從這裡來看,LESS把程序員喜歡的概念添加到CSS編碼了,如變量。但它能做的不止這些。

2.導入

可以把LESS代碼分割到多個文件,在需要的時候引用它們。假設創建一個container.less文件,它包含如下內容。

@black: #111;
.container {
background-color: @black;
}

在另一個LESS文件裡,比如main.less,可以通過導入這個文件來引用整個CSS。

@import "container";
.body { .container; }

如果container.less文件(擴展名不是必需的)放在另一個文件夾裡,你應該在調用@import時給出路徑信息。

3.混入(Mixins)

讓CSS樣式適配不同分辨率的能力是很重要的,尤其在網頁必須適配不同屏幕大小時。比如,當按鈕在平板上顯示且針對粗粒度指針(如手指)時,開發者通常會增加按鈕周圍的邊距(padding)。一般來說,如何使相同的CSS類根據某些運行時條件改變並且產生不同的顯示效果,這就是LESS混入派上用場的地方了。

以下是幾個混入示例。

.shadow(@color) {
box-shadow: 3px 3px 2px @color;
}
.text-box(@width) {
.shadow(#555);
border: solid 1px #000;
background-color: #dddd00;
padding: 2px;
width: @width;
}

可以從這裡派生出更加具體的CSS類,如下所示。

.text-box-mini {
.text-box(50px);
}
.text-box-normal {
.text-box(100px);
}
.text-box-large {
.text-box(200px);
}

這正是Bootstrap為了支持常見元素(如按鈕和輸入框)的不同風格在內部做的。

4.把LESS變成CSS

雖然LESS可以用作CSS的元語言,但LESS不是CSS。它必須進行某種處理來生成普通CSS。LESS代碼可以原樣下載並在客戶端通過JavaScript代碼處理,或者也可以在服務器上預處理,然後把普通CSS下載到客戶端。前者像在使用普通CSS文件:服務器端的更改會在下個頁面刷新時應用到客戶端。

但是,如果你有性能顧慮,而且要處理很大很複雜的CSS文件,服務器端預處理可能是個更好的選擇。服務器端預處理會在你每次修改服務器上的CSS時發生。通常,你會在構建流程的最後通過命令行使用LESS編譯器執行額外的步驟。Gulp等工具可以使用JavaScript相關的步驟來擴展構建流程。另一個流行的工具是Microsoft Web Essentials(一個Visual Studio插件),可以用來添加專門的菜單命令、處理CSS和腳本文件等Web資源。

但是,在ASP.NET MVC裡,還有另一種做法。你可以通過捆綁和壓縮機制整合整個LESS框架。在第10章裡,你將會詳細瞭解到,捆綁流程會把多個不同資源打包成單個可下載資源。比如,一個捆綁可能包含多個JavaScript和CSS文件,你可以通過向專門的終結點發送單個HTTP請求把它下載到本地機器。壓縮是應用到資源的特殊轉換。具體來說,壓縮會從文本資源移除所有不必要的字符,但不會改變預期功能。這意味著移除註釋、空白字符、換行符以及所有用於改善可讀性但只佔用空間的非功能性字符。

9.1.2 設置Bootstrap

可以從NuGet獲取Bootstrap。這種情況下,可以只取框架中所需要的部分。Bootstrap通常會用於整個網站,這樣可以從主視圖連接它,如下所示。

<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" src="@Url.Content("~/content/styles/bootstrap.min.css")">

viewport meta標籤把瀏覽器視口(Viewport)的寬度設為實際設備寬度並把放大級別設為標準。link元素只是引入Bootstrap樣式表的壓縮版本。如果打算使用更高級的Bootstrap特性,鑑於這些特性需要JavaScript,可以鏈接腳本文件以及它依賴的jQuery文件。

<script type="text/javascript"
src="@Url.Content("~/content/scripts/jquery-2.1.4.min.js")"></script>
<script type="text/javascript"
src="@Url.Content("~/content/scripts/bootstrap.min.js")"></script>

如果使用完整的Bootstrap庫,一旦鏈接了CSS和腳本文件,就已經準備好了。如果只用Bootstrap庫的部分,則必須確保需要的所有部分都正確鏈接。值得注意的是,Bootstrap庫的某些特性(比如工具提示和彈出界面)需要一些啟動JavaScript代碼,這些代碼必須添加代碼到每個頁面。

■ 注意:

Bootstrap不受老的Internet Explorer兼容模式支持。要確保頁面在Internet Explorer下能以最佳渲染方式查看,最好的辦法是在你的頁面裡添加以下meta標籤。

<meta http-equiv="X-UA-Compatible" content="IE=edge">

Bootstrap的CSS類使用了最新的CSS特性(如圓角效果),這可能不適用於老的瀏覽器。Internet Explorer 8就是部分支持Bootstrap的老瀏覽器的好樣板。

9.1.3 透析Bootstrap

Twitter Bootstrap在今天幾乎是必備的,原因是它使得向現代網站添加高級特性變得快速容易。Bootstrap的學習曲線比較短,很多基於它的模板都是免費的。但對於任何Web設計師而言,自定義基本Bootstrap模板實現獨特的效果也不是什麼難事。

Bootstrap是否適合你的項目取決於外觀的重要性。如果你的客戶需要自己的外觀,Bootstrap可能不是理想的。在這種情況下,開發團隊只收到圖形模板並使用它。此外,Bootstrap非常適合外觀重要但不是根本的快速項目。

換句話說,Bootstrap是一個很好的產品,但無法取代很好的設計。同時,它無法取代為每個設備定義得很好的用戶體驗。很容易找到一些網站提供基於Bootstrap的免費或付費模板。如果你限制自己使用Bootstrap庫的默認樣式(不改變CSS或LESS源代碼),那麼面臨的風險就是所有網站最終看起來都一樣。

要不要使用Bootstrap是一個架構決定,必須在項目早期做,後期很難更改。把Bootstrap添加到正在進行的項目或者從中刪除雖然不是不可能,但也通常有問題。最後,考慮到完整的Bootstrap庫包含100KB的CSS和30KB的腳本,這不是很大的資源,但也不是輕量級資源,尤其是使用較慢連接的較小設備。

Bootstrap的快速普及的其中一個關鍵原因是創建從不同類型設備看起來不錯的頁面成本很低。

■ 注意:

正如你將在第15章中看到的,有兩種截然不同的方式為多個設備設計網站。反應式Web設計是一種讓一套HTML頁面自動適配實際屏幕大小的方案。這是Bootstrap推廣的方案。其他方案為一些關鍵設備創建一套單獨的頁面,最突出的是智能手機。我將會在第16章講述這個話題。

9.2 反應式佈局

今天,所有網站至少都應該反應託管屏幕的寬度變化。作為開發團隊的一員,你有兩種主要方式實現這個功能。你可以從供應商那裡購買一個HTML反應式模板,堅持使用,讓實現細節透明,或者自行開發這個模板。

在後一種情況中,你會使用哪個框架呢?Bootstrap可能是人們應該考慮的第一個框架,但不是唯一的。其他同樣熱門和有效的響應式框架有Foundation、Skeleton和Gumby。任何學習Bootstrap的方案都從它提供的賦予HTML視圖響應式佈局的服務開始。

9.2.1 網格系統

Bootstrap有一個靈活的網格系統,它把水平可用空間分成12等份物理列。Bootstrap提供預定義CSS類,讓你可以通過創建邏輯列隨意佈局模板。換句話說,Bootstrap讓你可以通過一個範圍從1~12個單位的測量系統來安排模板空間。Bootstrap單位的實際大小取決於設備的實際屏幕大小。

屏幕大小實際上是視口——內容的可視化區域。在移動設備上,設備屏幕和視口一致,因為設備通常不支持可調整大小的窗口。而在臺式機上,你可以把窗口的大小調整到比最大可用空間小。在這種情況下,Bootstrap認為視口是可用渲染空間。

1.整體模板

任何Bootstrap內容要響應屏幕大小的改變都會基於行列矩陣。整體容器(這個矩陣)是一個樣式設為container的DIV元素(見圖9-1)。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-1 Bootstrap流體網格的架構

2.容器和行

最外層的容器處理任何必要的對齊,也負責填充。如果你沒有顯式定義一行,就會假設這一行佔滿整個高度。任何用戶界面內容都是放在列中的。注意,只有列允許成為行的直接子元素。Bootstrap中的任何內容通常都會根據以下架構佈局。

容器 > 行 > 列

前面代碼中的每個單詞都是你平常應用到DIV元素的Bootstrap類名。特別地,container管理頁面寬度和填充。row樣式確保內容放在同一行中,多行垂直堆疊。如果你的代碼中沒有行元素,容器中的任何內容都會水平排列,在碰到屏幕邊緣時會換到下一行。

最後,column元素表示行中的單個內容快。Bootstrap為列定義了多個實際類。要定義行中的一個列,你可以根據這個模式使用類名:col-××-N。在這個模式中,××表示設備類型前綴,可以是表9-1中的任何值。很快就會看到,每個××代碼都綁到以像素為單位的特定寬度,也叫斷點(breakpoint)。

全棧工程師Web開發指南:Bootstrap的精髓

模式中的N是一個介於1~12的數字,它表示這列內容在這個虛擬的網格中實際佔用多少列。下面來看一個例子。

<div class="container">
<div class="row">
<div class="col-xs-6 col-md-4"> First </div>
<div class="col-xs-6 col-md-4"> Second </div>
<div class="col-xs-6 col-md-4"> Third </div>
</div>
</div>

在這種情況下,你想在1行中渲染3列布局。所有列都是一樣大小,所有列在中型設備中顯示成一行。col-md-4樣式讓每列在虛擬Bootstrap網格系統裡都佔用4列寬度(一共12列)。

更小和更大的設備呢?

在XS設備上,這3列內容每個都會在渲染時佔據半個屏幕寬度。你可能會想,如果每列都佔據半個屏幕寬度,那麼3列不可能放入整個屏幕寬度。在這裡,第3列會溢出到下一行。同樣的結果會發生在SM設備上。但在LG設備上會使用MD樣式設置的規則。

原則上,流體行中的每列都可以使用多個設備的屬性來為寬度設置樣式。那些屬性對於更大的設備總是適用的,直到出現更特定的設置。鑑於此,如果你不需要按照設備區分佈局,最好一直使用XS樣式。列樣式中的N之和應該總是不超過12。如果超過了,任何超出第12列的列都會溢出到下一行。

3.容器和流體容器

到目前為止,我們只考慮把container類用於DIV元素。還有一個稍微不同的版本你可能在某些情況下會考慮到:container-fluid類。普通容器的每個斷點都是固定寬度的,只有用戶調整瀏覽器大小時跨越了斷點才會改變視口寬度。

而流體容器佔據父元素的全部寬度,通常是100%的瀏覽器可用視口。視口寬度會在每次調整大小時重新計算和更新。在使用流體容器時,用戶體驗會更平滑,但使用流體容器通常對桌面設備更有意義。

9.2.2 基於屏幕大小的渲染

為什麼要使用多列設置呢?答案通常取決於所要展示的實際內容。套用前面的例子,三列布局在中型大小的設備上可能沒問題,但列的內容可能太多而不能在更小屏幕的三分之一上渲染。這就是為什麼我把col-xs-6添加到DIV樣式。最終的效果是,Bootstrap會根據屏幕的實際大小改變最終行為。

在中型和大型設備上,你會有三列布局,在小型和更小設備上每行只有兩列。第三列在小型和更小設備上會換到下一行。如果這不是你想要的,可以考慮在小型和更小設備上隱藏第三列。下面看看怎麼做到。

1.虛擬測量和實際屏幕大小

Bootstrap中的整個網格系統和設備類型都是基於斷點的,見表9-2。如你所見,每個屏幕代碼都關聯了一個表示更小、小型、中型和大型設備預期寬度的斷點。

全棧工程師Web開發指南:Bootstrap的精髓

如果不指定col-xx-n樣式,會默認XS屏幕。對這些代碼類別的常見反應是Bootstrap不能讓你輕鬆處理這裡列出的非常小的設備,即768像素或更小的寬度。老設備落入這個範圍,它們可能需要和寬度大於768像素的更大設備不同的特定處理。

要監視Bootstrap如何改變頁面佈局,可以使用以下腳本代碼,只要把它添加到一個網頁就行了。

<script type="text/javascript">
updateSize();
$(window).resize(function() {
updateSize();
});
function currentBootstrapScreenClass() {
var screen = "LG";
var width = $(window).width();
if (width <= 768)
screen = "XS";
else if (width <= 992)
screen = "SM";
else if (width <= 1200)
screen = "MD";
return screen;
}
function updateSize() {
var info = currentBootstrapScreenClass();
$('#currentScreenWidth').text($(window).width() + "px");
$('#currentViewport').text(info);
}
</script>

顯然,這個網頁必須一些匹配一下ID的元素。

<span id="currentScreenWidth"></span>
<span id="currentViewport"></span>

效果如圖9-2所示。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-2 屏幕大小和Bootstrap類之間的關係

col-xx-n類是Bootstrap提供的讓頁面佈局適配屏幕大小的主要工具。還有更強大的工具可以針對特定屏幕大小隱藏和嵌套列。

2.多分辨率視圖

如前所述,就列布局而言,你可以把多個設置賦給容器和行。下面來看一個有趣的例子。

<div class="container">
<div class="row">
<div class="col-xs-6 col-md-4"> Column #1 <br /> Column #1 <br /></div>
<div class="col-xs-6 col-md-4"> Column #2 </div>
<div class="col-md-4"> Column #3 </div>
</div>
</div>

第一列在XS和SM模式中佔據了一半空間,在MD和LG模式中佔據了三分之一。但是,第一列的內容包含了一些BR元素,讓該列比其他列高。在MD和LG中,顯示效果跟預期的完全一樣,三列都在一行中。但在XS和SM中,第三列會在哪顯示?看看圖9-3。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-3 第三列浮在行的左側佔據任何可用的空間

在XS和SM模式中,前兩列由於它們的col-xs-6類佔據了整個屏幕。結果,第三列流到下一行。但是,在這個特例中,第一列比其他的高,這會留出右邊的空間。Bootstrap重用屏幕實際空間來放置換到下一行的列。

一般來說,每當使用col-xx-n類時候,實際上是把CSS的float屬性設為left(或right)並讓瀏覽器找出最左(或最右)可用空間來放置特定元素。注意,要向右對齊,你只需把pull-right類添加到目標元素。

3.特定大小的類

如果想強制第三列去到下一行最左呢?你要顯式停用默認對齊,恢復DIV元素的區塊性質。在純CSS中,通過使用clear:both屬性的空DIV可以實現這點。這在Bootstrap中對應clearfix類。

<div class="clearfix"></div>

圖9-4展示瞭如果盲目使用clearfix類來強制第三列在下一行開始將會得到什麼。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-4 第三列現在從下一行最左邊開始

如果調整瀏覽器的窗口大小到XS或SM模式,一切如常。但是,圖9-4只展示了MD和LG模式的樣子。如你所見,使用clearfix類會留出右邊的空間,這裡本來可以放得下第三列。理想情況下,你可能想清除DIV元素的浮動樣式,但只針對XS和SM模式。

在Bootstrap中,visible-xx類和hidden-xx類就是為此而來的。

<div class="clearfix visible-xs"></div>

現在的效果就是你想要的。使用clearfix類的DIV現在只會在XS和SM屏幕上才會出現。類似的,你可以使用hidden-xx類隱藏元素和整行。

■ 注意:

hidden-xx類本身是Bootstrap提供的一個強大的工具,可以讓你創建專門的響應式Web模板,用來在用戶調整視口時或者在較小的全屏設備上查看內容時調整這些內容。我將會在第15章詳細講述響應式Web設計的代價是隱藏不想要的內容。這個效果對於用戶來說是好的,但對於應用程序來說是不必要的,尤其是在移動設備上使用RWD。

4.靈活渲染

下面簡單看看使用hidden-xx類的具體例子。假設你有一個登錄表單,在經典的用戶名/密碼錶單週圍有很多介紹文字和一幅圖片。

<div class="container">
<h1 class="hidden-xs">WELCOME to CONTOSO Industries</h1>
<h4 class="visible-xs">WELCOME to CONTOSO</h4>
<div class="col-md-4 hidden-xs hidden-sm">
<div class="center">
<img src="~/Content/Images/contoso.png" />
</div>
</div>
</div>

圖9-5展示了這個登錄表單在LG屏幕上的樣子。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-5 在MD和LG模式中顯示的靈活登錄表單

H1元素只在SM和更大的設備上顯示。但在XS設備上,H1元素會替換成更小的H4元素。另外,圖片只會在MD和LG屏幕上顯示。你可以在調整瀏覽器窗口的大小時看到區別。

5.偏移和把列往回拉

Bootstrap網格系統也支持嵌套列。你要做的就是把子行嵌入一列中。除此之外,一切都按照到目前為止討論的規則進行。列偏移也是支持的。它通過col-XX-offset-N類發揮作用。比如,col-md-offset-2會在MD和更大的設備上跳過接下來兩個網格列。

一般來說,列是按照它們在HTML代碼中出現的順序來渲染的。但是,col-XX-pull-N類和col-XX-push-N類可以用來修改列的自然順序,把列往前推或者往回拉。這有時候可以用來修改生產環節中的現有頁面。事實上,如果還在開發中,你可以輕易在源代碼中移動列並按照定義的自然順序渲染。

■ 注意:

使用Bootstrap時,會假設使用四個預定義的可視化斷點,即XS、SM、MD和LG。這些斷點在從頁面鏈接的源CSS中定義,不需要重新定義。如果想修改,只需編輯CSS文件副本。

9.3 現今Web元素的分類體系

Bootstrap是一個很大的庫,不可能在一章中講完。我強烈建議在瀏覽器中收藏getbootstrap.com鏈接,以便日後快速訪問在線文檔。總的來說,有兩種方式使用這個庫。一種是使用簡單的單個HTML元素(如按鈕和錨)並以不同的方式對它們進行樣式設置。另一種是創建專門的HTML塊,這是Bootstrap CSS和腳本代碼的預定義組合,可以變成完全不同且能工作的用戶界面。

總的來說,Bootstrap促成了現代Web用戶界面元素的分類體系的定義,包括基本元素(如輸入字段和按鈕)以及更復雜的組件,如導航欄、下拉列表、標籤條和彈框。最後,還對核心Bootstrap庫創建了一些擴展,這些在今天是難以忽略的。這當中有兩個是自動完成庫typeahead和日期選擇器組件。

9.3.1 重塑基本HTML元素的樣式

下面通過探討專門用於定製輸入字段、按鈕、導航欄和文本元素的樣式,來深入瞭解Bootstrap HTML編程。

1.輸入字段

輸入字段通常用在HTML表單中。我說“通常”是因為某些現代Web應用程序傾向於通過JavaScript把內容提交到遠程端點,並不一定要用HTML表單。如果你決定自己序列化要提交的內容,並不一定需要通過HTML表單收集內容。但是,不管你通過瀏覽器還是以編程的方式提交,HTML表單都是輸入字段的最常見容器。

以下是典型的Bootstrap輸入表單,用於登錄頁面。

<form class="form-inline" method="post"
action="@Url.Action("login", "account")">
<div class="form-group">
<div class="input-group">
<label for="username">User name</label>
<div class="input-group-addon">
<span class="glyphicon glyphicon-user"></span>
</div>
<input type="text" class="form-control" id="username" name="username"
maxlength="30" placeholder="User name">
</div>
</div>
<div class="form-group">
<div class="input-group">
<label for="password">Password</label>
<div class="input-group-addon">
<span class="glyphicon glyphicon-lock"></span>
</div>
<input type="password" class="form-control" id="password" name="password"
maxlength="30" placeholder="Password">
</div>
</div>
...
</form>

這個HTML表單可以採用兩個類:form-inline或form-horizontal。顧名思義,二者都會側重通知這個庫在一行上或者在多個水平行(標籤和輸入字段垂直排列)上優化子輸入元素的渲染。

Bootstrap HTML表單由多個分組組成。每個分組通常包含一個標籤和一個輸入字段,它可以是text、date、password、checkbox、hidden等。輸入元素應該套用form-control類並用input-lg或input-sm類設置大小。

<input type="password" class="form-control input-lg" id="password">

其他可以用在輸入字段上的所有屬性(如maxlength、placeholder、id、name和value)都正常使用和處理。

Bootstrap中有一個有趣的特性是輸入插件。輸入插件是輸入字段和按鈕、靜態文本的組合。單個輸入分組中的所有元素Bootstrap都會看作同一個HTML元素,如圖9-6所示。

"

計算機非人性的一部分表現是,一旦完成編譯並且順利運行,它將忠實地完成工作。

——艾薩克·阿西莫夫

Bootstrap是一個CSS和JavaScript庫,它致力於簡化現代網頁的構建,原本是Twitter開發給內部使用的。但是,“現代網頁”到底是什麼呢?

非常簡單,現代網頁是按照現在大多數用戶想要的樣子構建的網頁。HTML語言仍然是網頁的基礎和核心語言。但是,HTML標記語言的構造越來越不能快速直接地表達構成現代網頁的複雜和成熟。比如,下拉菜單、分段選項按鈕、標籤欄、可摺疊標籤和模態對話框都是大多數頁面的常見元素,卻沒有現成的HTML元素。

Bootstrap提供直接的方式,把HTML塊變成現代網站所需的更加成熟的可視化元素。

9.1 Bootstrap概覽

Bootstrap是一個模塊化的Web庫,由CSS和JavaScript文件組成。CSS文件包含了重新設計常見HTML元素的類,使它們看上去不一樣,或許更好看。JavaScript文件是一組jQuery插件,支持更加複雜的特性,這些特性無法單純通過CSS實現。

Bootstrap最初開發成一組LESS文件,你仍然能夠以LESS文件的方式獲取CSS部分。一般來說,有組成Bootstrap庫的每個模塊的LESS或CSS文件:表單、按鈕、導航欄、對話框等。在深入Bootstrap庫之前,下面先來看看LESS。

9.1.1 LESS和Bootstrap基礎

LESS文件是構建在普通CSS語法之上的一個抽象層,讓開發者可以聲明一個CSS文件最終將會如何使用。你可以把LESS看作一門編程語言,一旦編譯就會產生CSS。在LESS文件裡,可以使用變量、函數和運算符,因此極大地提高了創建和維護大型複雜CSS樣式表的流程效率。

1.變量

開發者使用LESS解決的一大問題是信息的重複。軟件開發者可能深諳“自己不要重複”(Don’t Repeat Yourself, DRY)原則並且每天踐行。DRY的最大好處是減少相同信息保存位置的個數,因而減少應該更新的位置的個數。在普通CSS裡,無法做到DRY。比如,如果特定顏色在多個CSS類裡使用(某些時候要更新),除了在每個出現的地方更新,你可能沒有更好的辦法了。

CSS類的問題在於它們在語義HTML元素的級別工作。在構建各種CSS類時,你通常需要重複小塊信息,比如顏色或寬度。你無法輕易為每個可重複的小塊信息創建一個類。即使每個可重複樣式都有一個CSS類,如顏色和寬度,當把樣式應用到語義元素(如容器)時,需要聯合多個CSS類才能實現預期效果。

考慮以下CSS例子。

.container {
color: #111;
}
.header {
background-color: #111;
}

container和header兩個CSS類都使用相同的顏色。如果那個顏色需要改變,那麼必須找出所有使用它的地方然後編輯。下面使用LESS重寫相同的特性。

@black: #111;
.container {
color: @black;
}
.header {
background-color: @black;
}

現在,這個顏色定義在一個地方,作為全局變量。從這裡來看,LESS把程序員喜歡的概念添加到CSS編碼了,如變量。但它能做的不止這些。

2.導入

可以把LESS代碼分割到多個文件,在需要的時候引用它們。假設創建一個container.less文件,它包含如下內容。

@black: #111;
.container {
background-color: @black;
}

在另一個LESS文件裡,比如main.less,可以通過導入這個文件來引用整個CSS。

@import "container";
.body { .container; }

如果container.less文件(擴展名不是必需的)放在另一個文件夾裡,你應該在調用@import時給出路徑信息。

3.混入(Mixins)

讓CSS樣式適配不同分辨率的能力是很重要的,尤其在網頁必須適配不同屏幕大小時。比如,當按鈕在平板上顯示且針對粗粒度指針(如手指)時,開發者通常會增加按鈕周圍的邊距(padding)。一般來說,如何使相同的CSS類根據某些運行時條件改變並且產生不同的顯示效果,這就是LESS混入派上用場的地方了。

以下是幾個混入示例。

.shadow(@color) {
box-shadow: 3px 3px 2px @color;
}
.text-box(@width) {
.shadow(#555);
border: solid 1px #000;
background-color: #dddd00;
padding: 2px;
width: @width;
}

可以從這裡派生出更加具體的CSS類,如下所示。

.text-box-mini {
.text-box(50px);
}
.text-box-normal {
.text-box(100px);
}
.text-box-large {
.text-box(200px);
}

這正是Bootstrap為了支持常見元素(如按鈕和輸入框)的不同風格在內部做的。

4.把LESS變成CSS

雖然LESS可以用作CSS的元語言,但LESS不是CSS。它必須進行某種處理來生成普通CSS。LESS代碼可以原樣下載並在客戶端通過JavaScript代碼處理,或者也可以在服務器上預處理,然後把普通CSS下載到客戶端。前者像在使用普通CSS文件:服務器端的更改會在下個頁面刷新時應用到客戶端。

但是,如果你有性能顧慮,而且要處理很大很複雜的CSS文件,服務器端預處理可能是個更好的選擇。服務器端預處理會在你每次修改服務器上的CSS時發生。通常,你會在構建流程的最後通過命令行使用LESS編譯器執行額外的步驟。Gulp等工具可以使用JavaScript相關的步驟來擴展構建流程。另一個流行的工具是Microsoft Web Essentials(一個Visual Studio插件),可以用來添加專門的菜單命令、處理CSS和腳本文件等Web資源。

但是,在ASP.NET MVC裡,還有另一種做法。你可以通過捆綁和壓縮機制整合整個LESS框架。在第10章裡,你將會詳細瞭解到,捆綁流程會把多個不同資源打包成單個可下載資源。比如,一個捆綁可能包含多個JavaScript和CSS文件,你可以通過向專門的終結點發送單個HTTP請求把它下載到本地機器。壓縮是應用到資源的特殊轉換。具體來說,壓縮會從文本資源移除所有不必要的字符,但不會改變預期功能。這意味著移除註釋、空白字符、換行符以及所有用於改善可讀性但只佔用空間的非功能性字符。

9.1.2 設置Bootstrap

可以從NuGet獲取Bootstrap。這種情況下,可以只取框架中所需要的部分。Bootstrap通常會用於整個網站,這樣可以從主視圖連接它,如下所示。

<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" src="@Url.Content("~/content/styles/bootstrap.min.css")">

viewport meta標籤把瀏覽器視口(Viewport)的寬度設為實際設備寬度並把放大級別設為標準。link元素只是引入Bootstrap樣式表的壓縮版本。如果打算使用更高級的Bootstrap特性,鑑於這些特性需要JavaScript,可以鏈接腳本文件以及它依賴的jQuery文件。

<script type="text/javascript"
src="@Url.Content("~/content/scripts/jquery-2.1.4.min.js")"></script>
<script type="text/javascript"
src="@Url.Content("~/content/scripts/bootstrap.min.js")"></script>

如果使用完整的Bootstrap庫,一旦鏈接了CSS和腳本文件,就已經準備好了。如果只用Bootstrap庫的部分,則必須確保需要的所有部分都正確鏈接。值得注意的是,Bootstrap庫的某些特性(比如工具提示和彈出界面)需要一些啟動JavaScript代碼,這些代碼必須添加代碼到每個頁面。

■ 注意:

Bootstrap不受老的Internet Explorer兼容模式支持。要確保頁面在Internet Explorer下能以最佳渲染方式查看,最好的辦法是在你的頁面裡添加以下meta標籤。

<meta http-equiv="X-UA-Compatible" content="IE=edge">

Bootstrap的CSS類使用了最新的CSS特性(如圓角效果),這可能不適用於老的瀏覽器。Internet Explorer 8就是部分支持Bootstrap的老瀏覽器的好樣板。

9.1.3 透析Bootstrap

Twitter Bootstrap在今天幾乎是必備的,原因是它使得向現代網站添加高級特性變得快速容易。Bootstrap的學習曲線比較短,很多基於它的模板都是免費的。但對於任何Web設計師而言,自定義基本Bootstrap模板實現獨特的效果也不是什麼難事。

Bootstrap是否適合你的項目取決於外觀的重要性。如果你的客戶需要自己的外觀,Bootstrap可能不是理想的。在這種情況下,開發團隊只收到圖形模板並使用它。此外,Bootstrap非常適合外觀重要但不是根本的快速項目。

換句話說,Bootstrap是一個很好的產品,但無法取代很好的設計。同時,它無法取代為每個設備定義得很好的用戶體驗。很容易找到一些網站提供基於Bootstrap的免費或付費模板。如果你限制自己使用Bootstrap庫的默認樣式(不改變CSS或LESS源代碼),那麼面臨的風險就是所有網站最終看起來都一樣。

要不要使用Bootstrap是一個架構決定,必須在項目早期做,後期很難更改。把Bootstrap添加到正在進行的項目或者從中刪除雖然不是不可能,但也通常有問題。最後,考慮到完整的Bootstrap庫包含100KB的CSS和30KB的腳本,這不是很大的資源,但也不是輕量級資源,尤其是使用較慢連接的較小設備。

Bootstrap的快速普及的其中一個關鍵原因是創建從不同類型設備看起來不錯的頁面成本很低。

■ 注意:

正如你將在第15章中看到的,有兩種截然不同的方式為多個設備設計網站。反應式Web設計是一種讓一套HTML頁面自動適配實際屏幕大小的方案。這是Bootstrap推廣的方案。其他方案為一些關鍵設備創建一套單獨的頁面,最突出的是智能手機。我將會在第16章講述這個話題。

9.2 反應式佈局

今天,所有網站至少都應該反應託管屏幕的寬度變化。作為開發團隊的一員,你有兩種主要方式實現這個功能。你可以從供應商那裡購買一個HTML反應式模板,堅持使用,讓實現細節透明,或者自行開發這個模板。

在後一種情況中,你會使用哪個框架呢?Bootstrap可能是人們應該考慮的第一個框架,但不是唯一的。其他同樣熱門和有效的響應式框架有Foundation、Skeleton和Gumby。任何學習Bootstrap的方案都從它提供的賦予HTML視圖響應式佈局的服務開始。

9.2.1 網格系統

Bootstrap有一個靈活的網格系統,它把水平可用空間分成12等份物理列。Bootstrap提供預定義CSS類,讓你可以通過創建邏輯列隨意佈局模板。換句話說,Bootstrap讓你可以通過一個範圍從1~12個單位的測量系統來安排模板空間。Bootstrap單位的實際大小取決於設備的實際屏幕大小。

屏幕大小實際上是視口——內容的可視化區域。在移動設備上,設備屏幕和視口一致,因為設備通常不支持可調整大小的窗口。而在臺式機上,你可以把窗口的大小調整到比最大可用空間小。在這種情況下,Bootstrap認為視口是可用渲染空間。

1.整體模板

任何Bootstrap內容要響應屏幕大小的改變都會基於行列矩陣。整體容器(這個矩陣)是一個樣式設為container的DIV元素(見圖9-1)。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-1 Bootstrap流體網格的架構

2.容器和行

最外層的容器處理任何必要的對齊,也負責填充。如果你沒有顯式定義一行,就會假設這一行佔滿整個高度。任何用戶界面內容都是放在列中的。注意,只有列允許成為行的直接子元素。Bootstrap中的任何內容通常都會根據以下架構佈局。

容器 > 行 > 列

前面代碼中的每個單詞都是你平常應用到DIV元素的Bootstrap類名。特別地,container管理頁面寬度和填充。row樣式確保內容放在同一行中,多行垂直堆疊。如果你的代碼中沒有行元素,容器中的任何內容都會水平排列,在碰到屏幕邊緣時會換到下一行。

最後,column元素表示行中的單個內容快。Bootstrap為列定義了多個實際類。要定義行中的一個列,你可以根據這個模式使用類名:col-××-N。在這個模式中,××表示設備類型前綴,可以是表9-1中的任何值。很快就會看到,每個××代碼都綁到以像素為單位的特定寬度,也叫斷點(breakpoint)。

全棧工程師Web開發指南:Bootstrap的精髓

模式中的N是一個介於1~12的數字,它表示這列內容在這個虛擬的網格中實際佔用多少列。下面來看一個例子。

<div class="container">
<div class="row">
<div class="col-xs-6 col-md-4"> First </div>
<div class="col-xs-6 col-md-4"> Second </div>
<div class="col-xs-6 col-md-4"> Third </div>
</div>
</div>

在這種情況下,你想在1行中渲染3列布局。所有列都是一樣大小,所有列在中型設備中顯示成一行。col-md-4樣式讓每列在虛擬Bootstrap網格系統裡都佔用4列寬度(一共12列)。

更小和更大的設備呢?

在XS設備上,這3列內容每個都會在渲染時佔據半個屏幕寬度。你可能會想,如果每列都佔據半個屏幕寬度,那麼3列不可能放入整個屏幕寬度。在這裡,第3列會溢出到下一行。同樣的結果會發生在SM設備上。但在LG設備上會使用MD樣式設置的規則。

原則上,流體行中的每列都可以使用多個設備的屬性來為寬度設置樣式。那些屬性對於更大的設備總是適用的,直到出現更特定的設置。鑑於此,如果你不需要按照設備區分佈局,最好一直使用XS樣式。列樣式中的N之和應該總是不超過12。如果超過了,任何超出第12列的列都會溢出到下一行。

3.容器和流體容器

到目前為止,我們只考慮把container類用於DIV元素。還有一個稍微不同的版本你可能在某些情況下會考慮到:container-fluid類。普通容器的每個斷點都是固定寬度的,只有用戶調整瀏覽器大小時跨越了斷點才會改變視口寬度。

而流體容器佔據父元素的全部寬度,通常是100%的瀏覽器可用視口。視口寬度會在每次調整大小時重新計算和更新。在使用流體容器時,用戶體驗會更平滑,但使用流體容器通常對桌面設備更有意義。

9.2.2 基於屏幕大小的渲染

為什麼要使用多列設置呢?答案通常取決於所要展示的實際內容。套用前面的例子,三列布局在中型大小的設備上可能沒問題,但列的內容可能太多而不能在更小屏幕的三分之一上渲染。這就是為什麼我把col-xs-6添加到DIV樣式。最終的效果是,Bootstrap會根據屏幕的實際大小改變最終行為。

在中型和大型設備上,你會有三列布局,在小型和更小設備上每行只有兩列。第三列在小型和更小設備上會換到下一行。如果這不是你想要的,可以考慮在小型和更小設備上隱藏第三列。下面看看怎麼做到。

1.虛擬測量和實際屏幕大小

Bootstrap中的整個網格系統和設備類型都是基於斷點的,見表9-2。如你所見,每個屏幕代碼都關聯了一個表示更小、小型、中型和大型設備預期寬度的斷點。

全棧工程師Web開發指南:Bootstrap的精髓

如果不指定col-xx-n樣式,會默認XS屏幕。對這些代碼類別的常見反應是Bootstrap不能讓你輕鬆處理這裡列出的非常小的設備,即768像素或更小的寬度。老設備落入這個範圍,它們可能需要和寬度大於768像素的更大設備不同的特定處理。

要監視Bootstrap如何改變頁面佈局,可以使用以下腳本代碼,只要把它添加到一個網頁就行了。

<script type="text/javascript">
updateSize();
$(window).resize(function() {
updateSize();
});
function currentBootstrapScreenClass() {
var screen = "LG";
var width = $(window).width();
if (width <= 768)
screen = "XS";
else if (width <= 992)
screen = "SM";
else if (width <= 1200)
screen = "MD";
return screen;
}
function updateSize() {
var info = currentBootstrapScreenClass();
$('#currentScreenWidth').text($(window).width() + "px");
$('#currentViewport').text(info);
}
</script>

顯然,這個網頁必須一些匹配一下ID的元素。

<span id="currentScreenWidth"></span>
<span id="currentViewport"></span>

效果如圖9-2所示。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-2 屏幕大小和Bootstrap類之間的關係

col-xx-n類是Bootstrap提供的讓頁面佈局適配屏幕大小的主要工具。還有更強大的工具可以針對特定屏幕大小隱藏和嵌套列。

2.多分辨率視圖

如前所述,就列布局而言,你可以把多個設置賦給容器和行。下面來看一個有趣的例子。

<div class="container">
<div class="row">
<div class="col-xs-6 col-md-4"> Column #1 <br /> Column #1 <br /></div>
<div class="col-xs-6 col-md-4"> Column #2 </div>
<div class="col-md-4"> Column #3 </div>
</div>
</div>

第一列在XS和SM模式中佔據了一半空間,在MD和LG模式中佔據了三分之一。但是,第一列的內容包含了一些BR元素,讓該列比其他列高。在MD和LG中,顯示效果跟預期的完全一樣,三列都在一行中。但在XS和SM中,第三列會在哪顯示?看看圖9-3。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-3 第三列浮在行的左側佔據任何可用的空間

在XS和SM模式中,前兩列由於它們的col-xs-6類佔據了整個屏幕。結果,第三列流到下一行。但是,在這個特例中,第一列比其他的高,這會留出右邊的空間。Bootstrap重用屏幕實際空間來放置換到下一行的列。

一般來說,每當使用col-xx-n類時候,實際上是把CSS的float屬性設為left(或right)並讓瀏覽器找出最左(或最右)可用空間來放置特定元素。注意,要向右對齊,你只需把pull-right類添加到目標元素。

3.特定大小的類

如果想強制第三列去到下一行最左呢?你要顯式停用默認對齊,恢復DIV元素的區塊性質。在純CSS中,通過使用clear:both屬性的空DIV可以實現這點。這在Bootstrap中對應clearfix類。

<div class="clearfix"></div>

圖9-4展示瞭如果盲目使用clearfix類來強制第三列在下一行開始將會得到什麼。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-4 第三列現在從下一行最左邊開始

如果調整瀏覽器的窗口大小到XS或SM模式,一切如常。但是,圖9-4只展示了MD和LG模式的樣子。如你所見,使用clearfix類會留出右邊的空間,這裡本來可以放得下第三列。理想情況下,你可能想清除DIV元素的浮動樣式,但只針對XS和SM模式。

在Bootstrap中,visible-xx類和hidden-xx類就是為此而來的。

<div class="clearfix visible-xs"></div>

現在的效果就是你想要的。使用clearfix類的DIV現在只會在XS和SM屏幕上才會出現。類似的,你可以使用hidden-xx類隱藏元素和整行。

■ 注意:

hidden-xx類本身是Bootstrap提供的一個強大的工具,可以讓你創建專門的響應式Web模板,用來在用戶調整視口時或者在較小的全屏設備上查看內容時調整這些內容。我將會在第15章詳細講述響應式Web設計的代價是隱藏不想要的內容。這個效果對於用戶來說是好的,但對於應用程序來說是不必要的,尤其是在移動設備上使用RWD。

4.靈活渲染

下面簡單看看使用hidden-xx類的具體例子。假設你有一個登錄表單,在經典的用戶名/密碼錶單週圍有很多介紹文字和一幅圖片。

<div class="container">
<h1 class="hidden-xs">WELCOME to CONTOSO Industries</h1>
<h4 class="visible-xs">WELCOME to CONTOSO</h4>
<div class="col-md-4 hidden-xs hidden-sm">
<div class="center">
<img src="~/Content/Images/contoso.png" />
</div>
</div>
</div>

圖9-5展示了這個登錄表單在LG屏幕上的樣子。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-5 在MD和LG模式中顯示的靈活登錄表單

H1元素只在SM和更大的設備上顯示。但在XS設備上,H1元素會替換成更小的H4元素。另外,圖片只會在MD和LG屏幕上顯示。你可以在調整瀏覽器窗口的大小時看到區別。

5.偏移和把列往回拉

Bootstrap網格系統也支持嵌套列。你要做的就是把子行嵌入一列中。除此之外,一切都按照到目前為止討論的規則進行。列偏移也是支持的。它通過col-XX-offset-N類發揮作用。比如,col-md-offset-2會在MD和更大的設備上跳過接下來兩個網格列。

一般來說,列是按照它們在HTML代碼中出現的順序來渲染的。但是,col-XX-pull-N類和col-XX-push-N類可以用來修改列的自然順序,把列往前推或者往回拉。這有時候可以用來修改生產環節中的現有頁面。事實上,如果還在開發中,你可以輕易在源代碼中移動列並按照定義的自然順序渲染。

■ 注意:

使用Bootstrap時,會假設使用四個預定義的可視化斷點,即XS、SM、MD和LG。這些斷點在從頁面鏈接的源CSS中定義,不需要重新定義。如果想修改,只需編輯CSS文件副本。

9.3 現今Web元素的分類體系

Bootstrap是一個很大的庫,不可能在一章中講完。我強烈建議在瀏覽器中收藏getbootstrap.com鏈接,以便日後快速訪問在線文檔。總的來說,有兩種方式使用這個庫。一種是使用簡單的單個HTML元素(如按鈕和錨)並以不同的方式對它們進行樣式設置。另一種是創建專門的HTML塊,這是Bootstrap CSS和腳本代碼的預定義組合,可以變成完全不同且能工作的用戶界面。

總的來說,Bootstrap促成了現代Web用戶界面元素的分類體系的定義,包括基本元素(如輸入字段和按鈕)以及更復雜的組件,如導航欄、下拉列表、標籤條和彈框。最後,還對核心Bootstrap庫創建了一些擴展,這些在今天是難以忽略的。這當中有兩個是自動完成庫typeahead和日期選擇器組件。

9.3.1 重塑基本HTML元素的樣式

下面通過探討專門用於定製輸入字段、按鈕、導航欄和文本元素的樣式,來深入瞭解Bootstrap HTML編程。

1.輸入字段

輸入字段通常用在HTML表單中。我說“通常”是因為某些現代Web應用程序傾向於通過JavaScript把內容提交到遠程端點,並不一定要用HTML表單。如果你決定自己序列化要提交的內容,並不一定需要通過HTML表單收集內容。但是,不管你通過瀏覽器還是以編程的方式提交,HTML表單都是輸入字段的最常見容器。

以下是典型的Bootstrap輸入表單,用於登錄頁面。

<form class="form-inline" method="post"
action="@Url.Action("login", "account")">
<div class="form-group">
<div class="input-group">
<label for="username">User name</label>
<div class="input-group-addon">
<span class="glyphicon glyphicon-user"></span>
</div>
<input type="text" class="form-control" id="username" name="username"
maxlength="30" placeholder="User name">
</div>
</div>
<div class="form-group">
<div class="input-group">
<label for="password">Password</label>
<div class="input-group-addon">
<span class="glyphicon glyphicon-lock"></span>
</div>
<input type="password" class="form-control" id="password" name="password"
maxlength="30" placeholder="Password">
</div>
</div>
...
</form>

這個HTML表單可以採用兩個類:form-inline或form-horizontal。顧名思義,二者都會側重通知這個庫在一行上或者在多個水平行(標籤和輸入字段垂直排列)上優化子輸入元素的渲染。

Bootstrap HTML表單由多個分組組成。每個分組通常包含一個標籤和一個輸入字段,它可以是text、date、password、checkbox、hidden等。輸入元素應該套用form-control類並用input-lg或input-sm類設置大小。

<input type="password" class="form-control input-lg" id="password">

其他可以用在輸入字段上的所有屬性(如maxlength、placeholder、id、name和value)都正常使用和處理。

Bootstrap中有一個有趣的特性是輸入插件。輸入插件是輸入字段和按鈕、靜態文本的組合。單個輸入分組中的所有元素Bootstrap都會看作同一個HTML元素,如圖9-6所示。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-6 使用插件的Bootstrap輸入分組

以下是讓Bootstrap生成圖9-6所示的東西需要的全部標記內容。

<div class="input-group input-group-lg">
<span class="input-group-addon">@</span>
<input type="text" class="form-control" placeholder="Search for...">
<span class="input-group-btn">
<button class="btn btn-default" type="button">Action</button>
</span>
<div class="input-group-btn">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
...
</ul>
</div>

你可以使用input-group-addon類來創建文本佔位符,使用input-group-btn類向輸入字段田間按鈕或菜單。caret類應用到SPAN元素可以渲染出經典的向下三角形,表示更多內容。UL元素定義了一組下拉項。caret按鈕使用dropdown-toggle樣式來表示它可以按需顯示內容。最後,data-toggle類表示內容顯示的方式,在這裡是下拉顯示。

■ 重要:

仍然可以在應用了Bootstrap的頁面中使用輸入字段、按鈕和HTML元素。只要不向這些元素添加Bootstrap特定的類,Bootstrap就不會干涉瀏覽器的渲染。但是,整體外觀效果可能會與頁面的其他部分或者應用程序的其他頁面衝突,導致用戶不太滿意。如果選擇Bootstrap,就應該在要創建的所有頁面中使用它。

2.按鈕

在Bootstrap中,btn類會把提交按鈕、常規HTML按鈕和錨變成可點擊的方形區域。btn類的效果是純圖形的,它所做的就是添加填充、邊框、圓角和顏色。令人驚喜的是,把非文本內容添加到按鈕的標題非常簡單。

以下是使用btn類的最簡單方式。

<button class="btn">
Log in
</button>
<a href="#" class="btn" role="button">
...
</a>

btn類附帶一些輔助類可以定製按鈕的大小和顏色。默認情況下,Bootstrap按鈕會使用渲染指派給它的內容所需空間加上常規填充。btn-xs和btn-lg等類只是從默認btn移除或者添加額外填充。對於顏色,btn-primary、btn-danger、btn-alert、btn-success和btn-info樣式的按鈕採用不同顏色來表示通過這個按鈕實現的操作的重要程度。從開發者的角度來看,這是一種給頁面更一致的設計便捷  方式。

以下是定義Bootstrap按鈕的常見方式(見圖9-7)。

"

計算機非人性的一部分表現是,一旦完成編譯並且順利運行,它將忠實地完成工作。

——艾薩克·阿西莫夫

Bootstrap是一個CSS和JavaScript庫,它致力於簡化現代網頁的構建,原本是Twitter開發給內部使用的。但是,“現代網頁”到底是什麼呢?

非常簡單,現代網頁是按照現在大多數用戶想要的樣子構建的網頁。HTML語言仍然是網頁的基礎和核心語言。但是,HTML標記語言的構造越來越不能快速直接地表達構成現代網頁的複雜和成熟。比如,下拉菜單、分段選項按鈕、標籤欄、可摺疊標籤和模態對話框都是大多數頁面的常見元素,卻沒有現成的HTML元素。

Bootstrap提供直接的方式,把HTML塊變成現代網站所需的更加成熟的可視化元素。

9.1 Bootstrap概覽

Bootstrap是一個模塊化的Web庫,由CSS和JavaScript文件組成。CSS文件包含了重新設計常見HTML元素的類,使它們看上去不一樣,或許更好看。JavaScript文件是一組jQuery插件,支持更加複雜的特性,這些特性無法單純通過CSS實現。

Bootstrap最初開發成一組LESS文件,你仍然能夠以LESS文件的方式獲取CSS部分。一般來說,有組成Bootstrap庫的每個模塊的LESS或CSS文件:表單、按鈕、導航欄、對話框等。在深入Bootstrap庫之前,下面先來看看LESS。

9.1.1 LESS和Bootstrap基礎

LESS文件是構建在普通CSS語法之上的一個抽象層,讓開發者可以聲明一個CSS文件最終將會如何使用。你可以把LESS看作一門編程語言,一旦編譯就會產生CSS。在LESS文件裡,可以使用變量、函數和運算符,因此極大地提高了創建和維護大型複雜CSS樣式表的流程效率。

1.變量

開發者使用LESS解決的一大問題是信息的重複。軟件開發者可能深諳“自己不要重複”(Don’t Repeat Yourself, DRY)原則並且每天踐行。DRY的最大好處是減少相同信息保存位置的個數,因而減少應該更新的位置的個數。在普通CSS裡,無法做到DRY。比如,如果特定顏色在多個CSS類裡使用(某些時候要更新),除了在每個出現的地方更新,你可能沒有更好的辦法了。

CSS類的問題在於它們在語義HTML元素的級別工作。在構建各種CSS類時,你通常需要重複小塊信息,比如顏色或寬度。你無法輕易為每個可重複的小塊信息創建一個類。即使每個可重複樣式都有一個CSS類,如顏色和寬度,當把樣式應用到語義元素(如容器)時,需要聯合多個CSS類才能實現預期效果。

考慮以下CSS例子。

.container {
color: #111;
}
.header {
background-color: #111;
}

container和header兩個CSS類都使用相同的顏色。如果那個顏色需要改變,那麼必須找出所有使用它的地方然後編輯。下面使用LESS重寫相同的特性。

@black: #111;
.container {
color: @black;
}
.header {
background-color: @black;
}

現在,這個顏色定義在一個地方,作為全局變量。從這裡來看,LESS把程序員喜歡的概念添加到CSS編碼了,如變量。但它能做的不止這些。

2.導入

可以把LESS代碼分割到多個文件,在需要的時候引用它們。假設創建一個container.less文件,它包含如下內容。

@black: #111;
.container {
background-color: @black;
}

在另一個LESS文件裡,比如main.less,可以通過導入這個文件來引用整個CSS。

@import "container";
.body { .container; }

如果container.less文件(擴展名不是必需的)放在另一個文件夾裡,你應該在調用@import時給出路徑信息。

3.混入(Mixins)

讓CSS樣式適配不同分辨率的能力是很重要的,尤其在網頁必須適配不同屏幕大小時。比如,當按鈕在平板上顯示且針對粗粒度指針(如手指)時,開發者通常會增加按鈕周圍的邊距(padding)。一般來說,如何使相同的CSS類根據某些運行時條件改變並且產生不同的顯示效果,這就是LESS混入派上用場的地方了。

以下是幾個混入示例。

.shadow(@color) {
box-shadow: 3px 3px 2px @color;
}
.text-box(@width) {
.shadow(#555);
border: solid 1px #000;
background-color: #dddd00;
padding: 2px;
width: @width;
}

可以從這裡派生出更加具體的CSS類,如下所示。

.text-box-mini {
.text-box(50px);
}
.text-box-normal {
.text-box(100px);
}
.text-box-large {
.text-box(200px);
}

這正是Bootstrap為了支持常見元素(如按鈕和輸入框)的不同風格在內部做的。

4.把LESS變成CSS

雖然LESS可以用作CSS的元語言,但LESS不是CSS。它必須進行某種處理來生成普通CSS。LESS代碼可以原樣下載並在客戶端通過JavaScript代碼處理,或者也可以在服務器上預處理,然後把普通CSS下載到客戶端。前者像在使用普通CSS文件:服務器端的更改會在下個頁面刷新時應用到客戶端。

但是,如果你有性能顧慮,而且要處理很大很複雜的CSS文件,服務器端預處理可能是個更好的選擇。服務器端預處理會在你每次修改服務器上的CSS時發生。通常,你會在構建流程的最後通過命令行使用LESS編譯器執行額外的步驟。Gulp等工具可以使用JavaScript相關的步驟來擴展構建流程。另一個流行的工具是Microsoft Web Essentials(一個Visual Studio插件),可以用來添加專門的菜單命令、處理CSS和腳本文件等Web資源。

但是,在ASP.NET MVC裡,還有另一種做法。你可以通過捆綁和壓縮機制整合整個LESS框架。在第10章裡,你將會詳細瞭解到,捆綁流程會把多個不同資源打包成單個可下載資源。比如,一個捆綁可能包含多個JavaScript和CSS文件,你可以通過向專門的終結點發送單個HTTP請求把它下載到本地機器。壓縮是應用到資源的特殊轉換。具體來說,壓縮會從文本資源移除所有不必要的字符,但不會改變預期功能。這意味著移除註釋、空白字符、換行符以及所有用於改善可讀性但只佔用空間的非功能性字符。

9.1.2 設置Bootstrap

可以從NuGet獲取Bootstrap。這種情況下,可以只取框架中所需要的部分。Bootstrap通常會用於整個網站,這樣可以從主視圖連接它,如下所示。

<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" src="@Url.Content("~/content/styles/bootstrap.min.css")">

viewport meta標籤把瀏覽器視口(Viewport)的寬度設為實際設備寬度並把放大級別設為標準。link元素只是引入Bootstrap樣式表的壓縮版本。如果打算使用更高級的Bootstrap特性,鑑於這些特性需要JavaScript,可以鏈接腳本文件以及它依賴的jQuery文件。

<script type="text/javascript"
src="@Url.Content("~/content/scripts/jquery-2.1.4.min.js")"></script>
<script type="text/javascript"
src="@Url.Content("~/content/scripts/bootstrap.min.js")"></script>

如果使用完整的Bootstrap庫,一旦鏈接了CSS和腳本文件,就已經準備好了。如果只用Bootstrap庫的部分,則必須確保需要的所有部分都正確鏈接。值得注意的是,Bootstrap庫的某些特性(比如工具提示和彈出界面)需要一些啟動JavaScript代碼,這些代碼必須添加代碼到每個頁面。

■ 注意:

Bootstrap不受老的Internet Explorer兼容模式支持。要確保頁面在Internet Explorer下能以最佳渲染方式查看,最好的辦法是在你的頁面裡添加以下meta標籤。

<meta http-equiv="X-UA-Compatible" content="IE=edge">

Bootstrap的CSS類使用了最新的CSS特性(如圓角效果),這可能不適用於老的瀏覽器。Internet Explorer 8就是部分支持Bootstrap的老瀏覽器的好樣板。

9.1.3 透析Bootstrap

Twitter Bootstrap在今天幾乎是必備的,原因是它使得向現代網站添加高級特性變得快速容易。Bootstrap的學習曲線比較短,很多基於它的模板都是免費的。但對於任何Web設計師而言,自定義基本Bootstrap模板實現獨特的效果也不是什麼難事。

Bootstrap是否適合你的項目取決於外觀的重要性。如果你的客戶需要自己的外觀,Bootstrap可能不是理想的。在這種情況下,開發團隊只收到圖形模板並使用它。此外,Bootstrap非常適合外觀重要但不是根本的快速項目。

換句話說,Bootstrap是一個很好的產品,但無法取代很好的設計。同時,它無法取代為每個設備定義得很好的用戶體驗。很容易找到一些網站提供基於Bootstrap的免費或付費模板。如果你限制自己使用Bootstrap庫的默認樣式(不改變CSS或LESS源代碼),那麼面臨的風險就是所有網站最終看起來都一樣。

要不要使用Bootstrap是一個架構決定,必須在項目早期做,後期很難更改。把Bootstrap添加到正在進行的項目或者從中刪除雖然不是不可能,但也通常有問題。最後,考慮到完整的Bootstrap庫包含100KB的CSS和30KB的腳本,這不是很大的資源,但也不是輕量級資源,尤其是使用較慢連接的較小設備。

Bootstrap的快速普及的其中一個關鍵原因是創建從不同類型設備看起來不錯的頁面成本很低。

■ 注意:

正如你將在第15章中看到的,有兩種截然不同的方式為多個設備設計網站。反應式Web設計是一種讓一套HTML頁面自動適配實際屏幕大小的方案。這是Bootstrap推廣的方案。其他方案為一些關鍵設備創建一套單獨的頁面,最突出的是智能手機。我將會在第16章講述這個話題。

9.2 反應式佈局

今天,所有網站至少都應該反應託管屏幕的寬度變化。作為開發團隊的一員,你有兩種主要方式實現這個功能。你可以從供應商那裡購買一個HTML反應式模板,堅持使用,讓實現細節透明,或者自行開發這個模板。

在後一種情況中,你會使用哪個框架呢?Bootstrap可能是人們應該考慮的第一個框架,但不是唯一的。其他同樣熱門和有效的響應式框架有Foundation、Skeleton和Gumby。任何學習Bootstrap的方案都從它提供的賦予HTML視圖響應式佈局的服務開始。

9.2.1 網格系統

Bootstrap有一個靈活的網格系統,它把水平可用空間分成12等份物理列。Bootstrap提供預定義CSS類,讓你可以通過創建邏輯列隨意佈局模板。換句話說,Bootstrap讓你可以通過一個範圍從1~12個單位的測量系統來安排模板空間。Bootstrap單位的實際大小取決於設備的實際屏幕大小。

屏幕大小實際上是視口——內容的可視化區域。在移動設備上,設備屏幕和視口一致,因為設備通常不支持可調整大小的窗口。而在臺式機上,你可以把窗口的大小調整到比最大可用空間小。在這種情況下,Bootstrap認為視口是可用渲染空間。

1.整體模板

任何Bootstrap內容要響應屏幕大小的改變都會基於行列矩陣。整體容器(這個矩陣)是一個樣式設為container的DIV元素(見圖9-1)。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-1 Bootstrap流體網格的架構

2.容器和行

最外層的容器處理任何必要的對齊,也負責填充。如果你沒有顯式定義一行,就會假設這一行佔滿整個高度。任何用戶界面內容都是放在列中的。注意,只有列允許成為行的直接子元素。Bootstrap中的任何內容通常都會根據以下架構佈局。

容器 > 行 > 列

前面代碼中的每個單詞都是你平常應用到DIV元素的Bootstrap類名。特別地,container管理頁面寬度和填充。row樣式確保內容放在同一行中,多行垂直堆疊。如果你的代碼中沒有行元素,容器中的任何內容都會水平排列,在碰到屏幕邊緣時會換到下一行。

最後,column元素表示行中的單個內容快。Bootstrap為列定義了多個實際類。要定義行中的一個列,你可以根據這個模式使用類名:col-××-N。在這個模式中,××表示設備類型前綴,可以是表9-1中的任何值。很快就會看到,每個××代碼都綁到以像素為單位的特定寬度,也叫斷點(breakpoint)。

全棧工程師Web開發指南:Bootstrap的精髓

模式中的N是一個介於1~12的數字,它表示這列內容在這個虛擬的網格中實際佔用多少列。下面來看一個例子。

<div class="container">
<div class="row">
<div class="col-xs-6 col-md-4"> First </div>
<div class="col-xs-6 col-md-4"> Second </div>
<div class="col-xs-6 col-md-4"> Third </div>
</div>
</div>

在這種情況下,你想在1行中渲染3列布局。所有列都是一樣大小,所有列在中型設備中顯示成一行。col-md-4樣式讓每列在虛擬Bootstrap網格系統裡都佔用4列寬度(一共12列)。

更小和更大的設備呢?

在XS設備上,這3列內容每個都會在渲染時佔據半個屏幕寬度。你可能會想,如果每列都佔據半個屏幕寬度,那麼3列不可能放入整個屏幕寬度。在這裡,第3列會溢出到下一行。同樣的結果會發生在SM設備上。但在LG設備上會使用MD樣式設置的規則。

原則上,流體行中的每列都可以使用多個設備的屬性來為寬度設置樣式。那些屬性對於更大的設備總是適用的,直到出現更特定的設置。鑑於此,如果你不需要按照設備區分佈局,最好一直使用XS樣式。列樣式中的N之和應該總是不超過12。如果超過了,任何超出第12列的列都會溢出到下一行。

3.容器和流體容器

到目前為止,我們只考慮把container類用於DIV元素。還有一個稍微不同的版本你可能在某些情況下會考慮到:container-fluid類。普通容器的每個斷點都是固定寬度的,只有用戶調整瀏覽器大小時跨越了斷點才會改變視口寬度。

而流體容器佔據父元素的全部寬度,通常是100%的瀏覽器可用視口。視口寬度會在每次調整大小時重新計算和更新。在使用流體容器時,用戶體驗會更平滑,但使用流體容器通常對桌面設備更有意義。

9.2.2 基於屏幕大小的渲染

為什麼要使用多列設置呢?答案通常取決於所要展示的實際內容。套用前面的例子,三列布局在中型大小的設備上可能沒問題,但列的內容可能太多而不能在更小屏幕的三分之一上渲染。這就是為什麼我把col-xs-6添加到DIV樣式。最終的效果是,Bootstrap會根據屏幕的實際大小改變最終行為。

在中型和大型設備上,你會有三列布局,在小型和更小設備上每行只有兩列。第三列在小型和更小設備上會換到下一行。如果這不是你想要的,可以考慮在小型和更小設備上隱藏第三列。下面看看怎麼做到。

1.虛擬測量和實際屏幕大小

Bootstrap中的整個網格系統和設備類型都是基於斷點的,見表9-2。如你所見,每個屏幕代碼都關聯了一個表示更小、小型、中型和大型設備預期寬度的斷點。

全棧工程師Web開發指南:Bootstrap的精髓

如果不指定col-xx-n樣式,會默認XS屏幕。對這些代碼類別的常見反應是Bootstrap不能讓你輕鬆處理這裡列出的非常小的設備,即768像素或更小的寬度。老設備落入這個範圍,它們可能需要和寬度大於768像素的更大設備不同的特定處理。

要監視Bootstrap如何改變頁面佈局,可以使用以下腳本代碼,只要把它添加到一個網頁就行了。

<script type="text/javascript">
updateSize();
$(window).resize(function() {
updateSize();
});
function currentBootstrapScreenClass() {
var screen = "LG";
var width = $(window).width();
if (width <= 768)
screen = "XS";
else if (width <= 992)
screen = "SM";
else if (width <= 1200)
screen = "MD";
return screen;
}
function updateSize() {
var info = currentBootstrapScreenClass();
$('#currentScreenWidth').text($(window).width() + "px");
$('#currentViewport').text(info);
}
</script>

顯然,這個網頁必須一些匹配一下ID的元素。

<span id="currentScreenWidth"></span>
<span id="currentViewport"></span>

效果如圖9-2所示。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-2 屏幕大小和Bootstrap類之間的關係

col-xx-n類是Bootstrap提供的讓頁面佈局適配屏幕大小的主要工具。還有更強大的工具可以針對特定屏幕大小隱藏和嵌套列。

2.多分辨率視圖

如前所述,就列布局而言,你可以把多個設置賦給容器和行。下面來看一個有趣的例子。

<div class="container">
<div class="row">
<div class="col-xs-6 col-md-4"> Column #1 <br /> Column #1 <br /></div>
<div class="col-xs-6 col-md-4"> Column #2 </div>
<div class="col-md-4"> Column #3 </div>
</div>
</div>

第一列在XS和SM模式中佔據了一半空間,在MD和LG模式中佔據了三分之一。但是,第一列的內容包含了一些BR元素,讓該列比其他列高。在MD和LG中,顯示效果跟預期的完全一樣,三列都在一行中。但在XS和SM中,第三列會在哪顯示?看看圖9-3。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-3 第三列浮在行的左側佔據任何可用的空間

在XS和SM模式中,前兩列由於它們的col-xs-6類佔據了整個屏幕。結果,第三列流到下一行。但是,在這個特例中,第一列比其他的高,這會留出右邊的空間。Bootstrap重用屏幕實際空間來放置換到下一行的列。

一般來說,每當使用col-xx-n類時候,實際上是把CSS的float屬性設為left(或right)並讓瀏覽器找出最左(或最右)可用空間來放置特定元素。注意,要向右對齊,你只需把pull-right類添加到目標元素。

3.特定大小的類

如果想強制第三列去到下一行最左呢?你要顯式停用默認對齊,恢復DIV元素的區塊性質。在純CSS中,通過使用clear:both屬性的空DIV可以實現這點。這在Bootstrap中對應clearfix類。

<div class="clearfix"></div>

圖9-4展示瞭如果盲目使用clearfix類來強制第三列在下一行開始將會得到什麼。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-4 第三列現在從下一行最左邊開始

如果調整瀏覽器的窗口大小到XS或SM模式,一切如常。但是,圖9-4只展示了MD和LG模式的樣子。如你所見,使用clearfix類會留出右邊的空間,這裡本來可以放得下第三列。理想情況下,你可能想清除DIV元素的浮動樣式,但只針對XS和SM模式。

在Bootstrap中,visible-xx類和hidden-xx類就是為此而來的。

<div class="clearfix visible-xs"></div>

現在的效果就是你想要的。使用clearfix類的DIV現在只會在XS和SM屏幕上才會出現。類似的,你可以使用hidden-xx類隱藏元素和整行。

■ 注意:

hidden-xx類本身是Bootstrap提供的一個強大的工具,可以讓你創建專門的響應式Web模板,用來在用戶調整視口時或者在較小的全屏設備上查看內容時調整這些內容。我將會在第15章詳細講述響應式Web設計的代價是隱藏不想要的內容。這個效果對於用戶來說是好的,但對於應用程序來說是不必要的,尤其是在移動設備上使用RWD。

4.靈活渲染

下面簡單看看使用hidden-xx類的具體例子。假設你有一個登錄表單,在經典的用戶名/密碼錶單週圍有很多介紹文字和一幅圖片。

<div class="container">
<h1 class="hidden-xs">WELCOME to CONTOSO Industries</h1>
<h4 class="visible-xs">WELCOME to CONTOSO</h4>
<div class="col-md-4 hidden-xs hidden-sm">
<div class="center">
<img src="~/Content/Images/contoso.png" />
</div>
</div>
</div>

圖9-5展示了這個登錄表單在LG屏幕上的樣子。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-5 在MD和LG模式中顯示的靈活登錄表單

H1元素只在SM和更大的設備上顯示。但在XS設備上,H1元素會替換成更小的H4元素。另外,圖片只會在MD和LG屏幕上顯示。你可以在調整瀏覽器窗口的大小時看到區別。

5.偏移和把列往回拉

Bootstrap網格系統也支持嵌套列。你要做的就是把子行嵌入一列中。除此之外,一切都按照到目前為止討論的規則進行。列偏移也是支持的。它通過col-XX-offset-N類發揮作用。比如,col-md-offset-2會在MD和更大的設備上跳過接下來兩個網格列。

一般來說,列是按照它們在HTML代碼中出現的順序來渲染的。但是,col-XX-pull-N類和col-XX-push-N類可以用來修改列的自然順序,把列往前推或者往回拉。這有時候可以用來修改生產環節中的現有頁面。事實上,如果還在開發中,你可以輕易在源代碼中移動列並按照定義的自然順序渲染。

■ 注意:

使用Bootstrap時,會假設使用四個預定義的可視化斷點,即XS、SM、MD和LG。這些斷點在從頁面鏈接的源CSS中定義,不需要重新定義。如果想修改,只需編輯CSS文件副本。

9.3 現今Web元素的分類體系

Bootstrap是一個很大的庫,不可能在一章中講完。我強烈建議在瀏覽器中收藏getbootstrap.com鏈接,以便日後快速訪問在線文檔。總的來說,有兩種方式使用這個庫。一種是使用簡單的單個HTML元素(如按鈕和錨)並以不同的方式對它們進行樣式設置。另一種是創建專門的HTML塊,這是Bootstrap CSS和腳本代碼的預定義組合,可以變成完全不同且能工作的用戶界面。

總的來說,Bootstrap促成了現代Web用戶界面元素的分類體系的定義,包括基本元素(如輸入字段和按鈕)以及更復雜的組件,如導航欄、下拉列表、標籤條和彈框。最後,還對核心Bootstrap庫創建了一些擴展,這些在今天是難以忽略的。這當中有兩個是自動完成庫typeahead和日期選擇器組件。

9.3.1 重塑基本HTML元素的樣式

下面通過探討專門用於定製輸入字段、按鈕、導航欄和文本元素的樣式,來深入瞭解Bootstrap HTML編程。

1.輸入字段

輸入字段通常用在HTML表單中。我說“通常”是因為某些現代Web應用程序傾向於通過JavaScript把內容提交到遠程端點,並不一定要用HTML表單。如果你決定自己序列化要提交的內容,並不一定需要通過HTML表單收集內容。但是,不管你通過瀏覽器還是以編程的方式提交,HTML表單都是輸入字段的最常見容器。

以下是典型的Bootstrap輸入表單,用於登錄頁面。

<form class="form-inline" method="post"
action="@Url.Action("login", "account")">
<div class="form-group">
<div class="input-group">
<label for="username">User name</label>
<div class="input-group-addon">
<span class="glyphicon glyphicon-user"></span>
</div>
<input type="text" class="form-control" id="username" name="username"
maxlength="30" placeholder="User name">
</div>
</div>
<div class="form-group">
<div class="input-group">
<label for="password">Password</label>
<div class="input-group-addon">
<span class="glyphicon glyphicon-lock"></span>
</div>
<input type="password" class="form-control" id="password" name="password"
maxlength="30" placeholder="Password">
</div>
</div>
...
</form>

這個HTML表單可以採用兩個類:form-inline或form-horizontal。顧名思義,二者都會側重通知這個庫在一行上或者在多個水平行(標籤和輸入字段垂直排列)上優化子輸入元素的渲染。

Bootstrap HTML表單由多個分組組成。每個分組通常包含一個標籤和一個輸入字段,它可以是text、date、password、checkbox、hidden等。輸入元素應該套用form-control類並用input-lg或input-sm類設置大小。

<input type="password" class="form-control input-lg" id="password">

其他可以用在輸入字段上的所有屬性(如maxlength、placeholder、id、name和value)都正常使用和處理。

Bootstrap中有一個有趣的特性是輸入插件。輸入插件是輸入字段和按鈕、靜態文本的組合。單個輸入分組中的所有元素Bootstrap都會看作同一個HTML元素,如圖9-6所示。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-6 使用插件的Bootstrap輸入分組

以下是讓Bootstrap生成圖9-6所示的東西需要的全部標記內容。

<div class="input-group input-group-lg">
<span class="input-group-addon">@</span>
<input type="text" class="form-control" placeholder="Search for...">
<span class="input-group-btn">
<button class="btn btn-default" type="button">Action</button>
</span>
<div class="input-group-btn">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
...
</ul>
</div>

你可以使用input-group-addon類來創建文本佔位符,使用input-group-btn類向輸入字段田間按鈕或菜單。caret類應用到SPAN元素可以渲染出經典的向下三角形,表示更多內容。UL元素定義了一組下拉項。caret按鈕使用dropdown-toggle樣式來表示它可以按需顯示內容。最後,data-toggle類表示內容顯示的方式,在這裡是下拉顯示。

■ 重要:

仍然可以在應用了Bootstrap的頁面中使用輸入字段、按鈕和HTML元素。只要不向這些元素添加Bootstrap特定的類,Bootstrap就不會干涉瀏覽器的渲染。但是,整體外觀效果可能會與頁面的其他部分或者應用程序的其他頁面衝突,導致用戶不太滿意。如果選擇Bootstrap,就應該在要創建的所有頁面中使用它。

2.按鈕

在Bootstrap中,btn類會把提交按鈕、常規HTML按鈕和錨變成可點擊的方形區域。btn類的效果是純圖形的,它所做的就是添加填充、邊框、圓角和顏色。令人驚喜的是,把非文本內容添加到按鈕的標題非常簡單。

以下是使用btn類的最簡單方式。

<button class="btn">
Log in
</button>
<a href="#" class="btn" role="button">
...
</a>

btn類附帶一些輔助類可以定製按鈕的大小和顏色。默認情況下,Bootstrap按鈕會使用渲染指派給它的內容所需空間加上常規填充。btn-xs和btn-lg等類只是從默認btn移除或者添加額外填充。對於顏色,btn-primary、btn-danger、btn-alert、btn-success和btn-info樣式的按鈕採用不同顏色來表示通過這個按鈕實現的操作的重要程度。從開發者的角度來看,這是一種給頁面更一致的設計便捷  方式。

以下是定義Bootstrap按鈕的常見方式(見圖9-7)。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-7 示例Bootstrap按鈕

<button class="btn">
<span class="glyphicon glyphicon-ok"></span>
Log in
</button>

如你所見,在按鈕的標題中混用小圖片和文字非常容易。對於Bootstrap按鈕,通常使用glyphicons,這是一個特殊的內嵌字體,由渲染圖標和極小剪貼畫的庫附帶。如果不用原生Bootstrap圖標,你可以添加現有的圖標庫。一個最流行的圖標庫是FontAwesome,你可以登錄fontawesome官網瞭解到更多關於它的內容。一旦FontAwesome就緒,你可以像這樣重寫登錄按鈕。

<button class="btn">
<i class="fa fa-lg fa-ok"></i>
Log in
</button>

3.分組按鈕

通常,網頁需要顯示多個有著某種聯繫的按鈕。當然你可以單獨處理這些按鈕,按照喜歡的方式來設置它們的樣式。但是,幾年前iOS用戶界面引入了分段按鈕(segmented button)的概念。現在,如果不是必須情況下,分段按鈕成了想要的特性。分段按鈕本質上是一組單獨操作的按鈕,但渲染成單個按鈕條。最好看的效果是這個按鈕條的第一個和最後一個按鈕是圓角的,中間的按鈕是完全四方的。在Bootstrap中,可以使用以下HTML標記。

<div class="btn-group">
<button type="button" class="btn btn-success">Agree</button>
<button type="button" class="btn btn-default">Not sure</button>
<button type="button" class="btn btn-danger">Disagree</button>
</div>

每個按鈕都有自己的點擊處理器,顯式通過onclick屬性或悄悄通過jQuery添加。要創建按鈕分組,你要做的就是把一組按鈕包在一個使用btn-group樣式的DIV元素中。

分組中的按鈕大小可以通過額外的類btn-group-lg或btn-group-xs來控制。默認情況下,按鈕是水平堆疊的。要垂直堆疊它們,只需把btn-group-vertical類添加到按鈕分組。多個分組可以通過包裝在按鈕工具欄容器中並排放置。

<div>
<div class="btn-group">...</div>
<div class="btn-group">...</div>
<div class="btn-group">...</div>
</div>

從圖9-6來看,你可能覺得Bootstrap按鈕也可以用來實現下拉菜單,以下示範如何做到。

<div class="btn-group">
<button type="button" class="btn btn-default">One</button>
<button type="button" class="btn btn-default">Two</button>
<div class="btn-group">
<button type="button" class="btn dropdown-toggle" data-toggle="dropdown">
Numbers
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
</ul>
</div>
</div>

這個分組中前兩項是普通按鈕,接著是一個嵌套的下拉分組。這個按鈕分組由一個按鈕和一個附加的下拉菜單組成。有趣的是,按鈕有一個caret分段,通過視覺的方式傳遞更多選項可以看的消息。通過把dropup類添加到包裝這個列表的按鈕分組,你可以使這個列表向上顯示。

■ 重要:

在觀察Bootstrap的下拉按鈕時,你可能想到兩個常見的用戶界面元素:下拉菜單和下拉列表。按鈕分組是普通下拉菜單。下拉列表(就像你在普通HTML中通過SELECT/OPTION元素獲得的)是一個稍微不同的東西。對於選擇操作,Bootstrap沒有內置工具。在表單中使用的SELECT元素會和其他可視化元素有著明顯不同的樣式,這會是個問題。讓SELECT不同於普通菜單的是它跟蹤選中的項並把它展示給用戶和程序。

4.單選按鈕

很多用戶界面中的一個常見元素是單選按鈕。這是一組一起工作的互斥按鈕:每次只能選擇一個,選擇新的會自動移除當前選擇的按鈕。HTML為實現單選按鈕提供輸入元素的專門類型。藉助Bootstrap,你可以結合原生HTML輸入單選按鈕和分組按鈕創建更好的用戶界面。

下面演示如何創建一個單選按鈕列表用來在用戶個人資料編輯器中選擇性別。

<div class="btn-group" data-toggle="buttons">
<label class="btn btn-primary @active1">
<input type="radio" id="gender" name="gender" value="X" @checked1>
Don't show
</label>
<label class="btn btn-primary @active2">
<input type="radio" id="gender" name="gender" value="M" @checked2>
Male
</label>
<label class="btn btn-primary @active3">
<input type="radio" id="gender" name="gender" value="F" @checked3>
Female
</label>
</div>

圖9-8展示了結果。注意,按照設計,按鈕不是一樣大小的。你可以通過添加一些額外的自定義樣式來做到。

"

計算機非人性的一部分表現是,一旦完成編譯並且順利運行,它將忠實地完成工作。

——艾薩克·阿西莫夫

Bootstrap是一個CSS和JavaScript庫,它致力於簡化現代網頁的構建,原本是Twitter開發給內部使用的。但是,“現代網頁”到底是什麼呢?

非常簡單,現代網頁是按照現在大多數用戶想要的樣子構建的網頁。HTML語言仍然是網頁的基礎和核心語言。但是,HTML標記語言的構造越來越不能快速直接地表達構成現代網頁的複雜和成熟。比如,下拉菜單、分段選項按鈕、標籤欄、可摺疊標籤和模態對話框都是大多數頁面的常見元素,卻沒有現成的HTML元素。

Bootstrap提供直接的方式,把HTML塊變成現代網站所需的更加成熟的可視化元素。

9.1 Bootstrap概覽

Bootstrap是一個模塊化的Web庫,由CSS和JavaScript文件組成。CSS文件包含了重新設計常見HTML元素的類,使它們看上去不一樣,或許更好看。JavaScript文件是一組jQuery插件,支持更加複雜的特性,這些特性無法單純通過CSS實現。

Bootstrap最初開發成一組LESS文件,你仍然能夠以LESS文件的方式獲取CSS部分。一般來說,有組成Bootstrap庫的每個模塊的LESS或CSS文件:表單、按鈕、導航欄、對話框等。在深入Bootstrap庫之前,下面先來看看LESS。

9.1.1 LESS和Bootstrap基礎

LESS文件是構建在普通CSS語法之上的一個抽象層,讓開發者可以聲明一個CSS文件最終將會如何使用。你可以把LESS看作一門編程語言,一旦編譯就會產生CSS。在LESS文件裡,可以使用變量、函數和運算符,因此極大地提高了創建和維護大型複雜CSS樣式表的流程效率。

1.變量

開發者使用LESS解決的一大問題是信息的重複。軟件開發者可能深諳“自己不要重複”(Don’t Repeat Yourself, DRY)原則並且每天踐行。DRY的最大好處是減少相同信息保存位置的個數,因而減少應該更新的位置的個數。在普通CSS裡,無法做到DRY。比如,如果特定顏色在多個CSS類裡使用(某些時候要更新),除了在每個出現的地方更新,你可能沒有更好的辦法了。

CSS類的問題在於它們在語義HTML元素的級別工作。在構建各種CSS類時,你通常需要重複小塊信息,比如顏色或寬度。你無法輕易為每個可重複的小塊信息創建一個類。即使每個可重複樣式都有一個CSS類,如顏色和寬度,當把樣式應用到語義元素(如容器)時,需要聯合多個CSS類才能實現預期效果。

考慮以下CSS例子。

.container {
color: #111;
}
.header {
background-color: #111;
}

container和header兩個CSS類都使用相同的顏色。如果那個顏色需要改變,那麼必須找出所有使用它的地方然後編輯。下面使用LESS重寫相同的特性。

@black: #111;
.container {
color: @black;
}
.header {
background-color: @black;
}

現在,這個顏色定義在一個地方,作為全局變量。從這裡來看,LESS把程序員喜歡的概念添加到CSS編碼了,如變量。但它能做的不止這些。

2.導入

可以把LESS代碼分割到多個文件,在需要的時候引用它們。假設創建一個container.less文件,它包含如下內容。

@black: #111;
.container {
background-color: @black;
}

在另一個LESS文件裡,比如main.less,可以通過導入這個文件來引用整個CSS。

@import "container";
.body { .container; }

如果container.less文件(擴展名不是必需的)放在另一個文件夾裡,你應該在調用@import時給出路徑信息。

3.混入(Mixins)

讓CSS樣式適配不同分辨率的能力是很重要的,尤其在網頁必須適配不同屏幕大小時。比如,當按鈕在平板上顯示且針對粗粒度指針(如手指)時,開發者通常會增加按鈕周圍的邊距(padding)。一般來說,如何使相同的CSS類根據某些運行時條件改變並且產生不同的顯示效果,這就是LESS混入派上用場的地方了。

以下是幾個混入示例。

.shadow(@color) {
box-shadow: 3px 3px 2px @color;
}
.text-box(@width) {
.shadow(#555);
border: solid 1px #000;
background-color: #dddd00;
padding: 2px;
width: @width;
}

可以從這裡派生出更加具體的CSS類,如下所示。

.text-box-mini {
.text-box(50px);
}
.text-box-normal {
.text-box(100px);
}
.text-box-large {
.text-box(200px);
}

這正是Bootstrap為了支持常見元素(如按鈕和輸入框)的不同風格在內部做的。

4.把LESS變成CSS

雖然LESS可以用作CSS的元語言,但LESS不是CSS。它必須進行某種處理來生成普通CSS。LESS代碼可以原樣下載並在客戶端通過JavaScript代碼處理,或者也可以在服務器上預處理,然後把普通CSS下載到客戶端。前者像在使用普通CSS文件:服務器端的更改會在下個頁面刷新時應用到客戶端。

但是,如果你有性能顧慮,而且要處理很大很複雜的CSS文件,服務器端預處理可能是個更好的選擇。服務器端預處理會在你每次修改服務器上的CSS時發生。通常,你會在構建流程的最後通過命令行使用LESS編譯器執行額外的步驟。Gulp等工具可以使用JavaScript相關的步驟來擴展構建流程。另一個流行的工具是Microsoft Web Essentials(一個Visual Studio插件),可以用來添加專門的菜單命令、處理CSS和腳本文件等Web資源。

但是,在ASP.NET MVC裡,還有另一種做法。你可以通過捆綁和壓縮機制整合整個LESS框架。在第10章裡,你將會詳細瞭解到,捆綁流程會把多個不同資源打包成單個可下載資源。比如,一個捆綁可能包含多個JavaScript和CSS文件,你可以通過向專門的終結點發送單個HTTP請求把它下載到本地機器。壓縮是應用到資源的特殊轉換。具體來說,壓縮會從文本資源移除所有不必要的字符,但不會改變預期功能。這意味著移除註釋、空白字符、換行符以及所有用於改善可讀性但只佔用空間的非功能性字符。

9.1.2 設置Bootstrap

可以從NuGet獲取Bootstrap。這種情況下,可以只取框架中所需要的部分。Bootstrap通常會用於整個網站,這樣可以從主視圖連接它,如下所示。

<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" src="@Url.Content("~/content/styles/bootstrap.min.css")">

viewport meta標籤把瀏覽器視口(Viewport)的寬度設為實際設備寬度並把放大級別設為標準。link元素只是引入Bootstrap樣式表的壓縮版本。如果打算使用更高級的Bootstrap特性,鑑於這些特性需要JavaScript,可以鏈接腳本文件以及它依賴的jQuery文件。

<script type="text/javascript"
src="@Url.Content("~/content/scripts/jquery-2.1.4.min.js")"></script>
<script type="text/javascript"
src="@Url.Content("~/content/scripts/bootstrap.min.js")"></script>

如果使用完整的Bootstrap庫,一旦鏈接了CSS和腳本文件,就已經準備好了。如果只用Bootstrap庫的部分,則必須確保需要的所有部分都正確鏈接。值得注意的是,Bootstrap庫的某些特性(比如工具提示和彈出界面)需要一些啟動JavaScript代碼,這些代碼必須添加代碼到每個頁面。

■ 注意:

Bootstrap不受老的Internet Explorer兼容模式支持。要確保頁面在Internet Explorer下能以最佳渲染方式查看,最好的辦法是在你的頁面裡添加以下meta標籤。

<meta http-equiv="X-UA-Compatible" content="IE=edge">

Bootstrap的CSS類使用了最新的CSS特性(如圓角效果),這可能不適用於老的瀏覽器。Internet Explorer 8就是部分支持Bootstrap的老瀏覽器的好樣板。

9.1.3 透析Bootstrap

Twitter Bootstrap在今天幾乎是必備的,原因是它使得向現代網站添加高級特性變得快速容易。Bootstrap的學習曲線比較短,很多基於它的模板都是免費的。但對於任何Web設計師而言,自定義基本Bootstrap模板實現獨特的效果也不是什麼難事。

Bootstrap是否適合你的項目取決於外觀的重要性。如果你的客戶需要自己的外觀,Bootstrap可能不是理想的。在這種情況下,開發團隊只收到圖形模板並使用它。此外,Bootstrap非常適合外觀重要但不是根本的快速項目。

換句話說,Bootstrap是一個很好的產品,但無法取代很好的設計。同時,它無法取代為每個設備定義得很好的用戶體驗。很容易找到一些網站提供基於Bootstrap的免費或付費模板。如果你限制自己使用Bootstrap庫的默認樣式(不改變CSS或LESS源代碼),那麼面臨的風險就是所有網站最終看起來都一樣。

要不要使用Bootstrap是一個架構決定,必須在項目早期做,後期很難更改。把Bootstrap添加到正在進行的項目或者從中刪除雖然不是不可能,但也通常有問題。最後,考慮到完整的Bootstrap庫包含100KB的CSS和30KB的腳本,這不是很大的資源,但也不是輕量級資源,尤其是使用較慢連接的較小設備。

Bootstrap的快速普及的其中一個關鍵原因是創建從不同類型設備看起來不錯的頁面成本很低。

■ 注意:

正如你將在第15章中看到的,有兩種截然不同的方式為多個設備設計網站。反應式Web設計是一種讓一套HTML頁面自動適配實際屏幕大小的方案。這是Bootstrap推廣的方案。其他方案為一些關鍵設備創建一套單獨的頁面,最突出的是智能手機。我將會在第16章講述這個話題。

9.2 反應式佈局

今天,所有網站至少都應該反應託管屏幕的寬度變化。作為開發團隊的一員,你有兩種主要方式實現這個功能。你可以從供應商那裡購買一個HTML反應式模板,堅持使用,讓實現細節透明,或者自行開發這個模板。

在後一種情況中,你會使用哪個框架呢?Bootstrap可能是人們應該考慮的第一個框架,但不是唯一的。其他同樣熱門和有效的響應式框架有Foundation、Skeleton和Gumby。任何學習Bootstrap的方案都從它提供的賦予HTML視圖響應式佈局的服務開始。

9.2.1 網格系統

Bootstrap有一個靈活的網格系統,它把水平可用空間分成12等份物理列。Bootstrap提供預定義CSS類,讓你可以通過創建邏輯列隨意佈局模板。換句話說,Bootstrap讓你可以通過一個範圍從1~12個單位的測量系統來安排模板空間。Bootstrap單位的實際大小取決於設備的實際屏幕大小。

屏幕大小實際上是視口——內容的可視化區域。在移動設備上,設備屏幕和視口一致,因為設備通常不支持可調整大小的窗口。而在臺式機上,你可以把窗口的大小調整到比最大可用空間小。在這種情況下,Bootstrap認為視口是可用渲染空間。

1.整體模板

任何Bootstrap內容要響應屏幕大小的改變都會基於行列矩陣。整體容器(這個矩陣)是一個樣式設為container的DIV元素(見圖9-1)。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-1 Bootstrap流體網格的架構

2.容器和行

最外層的容器處理任何必要的對齊,也負責填充。如果你沒有顯式定義一行,就會假設這一行佔滿整個高度。任何用戶界面內容都是放在列中的。注意,只有列允許成為行的直接子元素。Bootstrap中的任何內容通常都會根據以下架構佈局。

容器 > 行 > 列

前面代碼中的每個單詞都是你平常應用到DIV元素的Bootstrap類名。特別地,container管理頁面寬度和填充。row樣式確保內容放在同一行中,多行垂直堆疊。如果你的代碼中沒有行元素,容器中的任何內容都會水平排列,在碰到屏幕邊緣時會換到下一行。

最後,column元素表示行中的單個內容快。Bootstrap為列定義了多個實際類。要定義行中的一個列,你可以根據這個模式使用類名:col-××-N。在這個模式中,××表示設備類型前綴,可以是表9-1中的任何值。很快就會看到,每個××代碼都綁到以像素為單位的特定寬度,也叫斷點(breakpoint)。

全棧工程師Web開發指南:Bootstrap的精髓

模式中的N是一個介於1~12的數字,它表示這列內容在這個虛擬的網格中實際佔用多少列。下面來看一個例子。

<div class="container">
<div class="row">
<div class="col-xs-6 col-md-4"> First </div>
<div class="col-xs-6 col-md-4"> Second </div>
<div class="col-xs-6 col-md-4"> Third </div>
</div>
</div>

在這種情況下,你想在1行中渲染3列布局。所有列都是一樣大小,所有列在中型設備中顯示成一行。col-md-4樣式讓每列在虛擬Bootstrap網格系統裡都佔用4列寬度(一共12列)。

更小和更大的設備呢?

在XS設備上,這3列內容每個都會在渲染時佔據半個屏幕寬度。你可能會想,如果每列都佔據半個屏幕寬度,那麼3列不可能放入整個屏幕寬度。在這裡,第3列會溢出到下一行。同樣的結果會發生在SM設備上。但在LG設備上會使用MD樣式設置的規則。

原則上,流體行中的每列都可以使用多個設備的屬性來為寬度設置樣式。那些屬性對於更大的設備總是適用的,直到出現更特定的設置。鑑於此,如果你不需要按照設備區分佈局,最好一直使用XS樣式。列樣式中的N之和應該總是不超過12。如果超過了,任何超出第12列的列都會溢出到下一行。

3.容器和流體容器

到目前為止,我們只考慮把container類用於DIV元素。還有一個稍微不同的版本你可能在某些情況下會考慮到:container-fluid類。普通容器的每個斷點都是固定寬度的,只有用戶調整瀏覽器大小時跨越了斷點才會改變視口寬度。

而流體容器佔據父元素的全部寬度,通常是100%的瀏覽器可用視口。視口寬度會在每次調整大小時重新計算和更新。在使用流體容器時,用戶體驗會更平滑,但使用流體容器通常對桌面設備更有意義。

9.2.2 基於屏幕大小的渲染

為什麼要使用多列設置呢?答案通常取決於所要展示的實際內容。套用前面的例子,三列布局在中型大小的設備上可能沒問題,但列的內容可能太多而不能在更小屏幕的三分之一上渲染。這就是為什麼我把col-xs-6添加到DIV樣式。最終的效果是,Bootstrap會根據屏幕的實際大小改變最終行為。

在中型和大型設備上,你會有三列布局,在小型和更小設備上每行只有兩列。第三列在小型和更小設備上會換到下一行。如果這不是你想要的,可以考慮在小型和更小設備上隱藏第三列。下面看看怎麼做到。

1.虛擬測量和實際屏幕大小

Bootstrap中的整個網格系統和設備類型都是基於斷點的,見表9-2。如你所見,每個屏幕代碼都關聯了一個表示更小、小型、中型和大型設備預期寬度的斷點。

全棧工程師Web開發指南:Bootstrap的精髓

如果不指定col-xx-n樣式,會默認XS屏幕。對這些代碼類別的常見反應是Bootstrap不能讓你輕鬆處理這裡列出的非常小的設備,即768像素或更小的寬度。老設備落入這個範圍,它們可能需要和寬度大於768像素的更大設備不同的特定處理。

要監視Bootstrap如何改變頁面佈局,可以使用以下腳本代碼,只要把它添加到一個網頁就行了。

<script type="text/javascript">
updateSize();
$(window).resize(function() {
updateSize();
});
function currentBootstrapScreenClass() {
var screen = "LG";
var width = $(window).width();
if (width <= 768)
screen = "XS";
else if (width <= 992)
screen = "SM";
else if (width <= 1200)
screen = "MD";
return screen;
}
function updateSize() {
var info = currentBootstrapScreenClass();
$('#currentScreenWidth').text($(window).width() + "px");
$('#currentViewport').text(info);
}
</script>

顯然,這個網頁必須一些匹配一下ID的元素。

<span id="currentScreenWidth"></span>
<span id="currentViewport"></span>

效果如圖9-2所示。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-2 屏幕大小和Bootstrap類之間的關係

col-xx-n類是Bootstrap提供的讓頁面佈局適配屏幕大小的主要工具。還有更強大的工具可以針對特定屏幕大小隱藏和嵌套列。

2.多分辨率視圖

如前所述,就列布局而言,你可以把多個設置賦給容器和行。下面來看一個有趣的例子。

<div class="container">
<div class="row">
<div class="col-xs-6 col-md-4"> Column #1 <br /> Column #1 <br /></div>
<div class="col-xs-6 col-md-4"> Column #2 </div>
<div class="col-md-4"> Column #3 </div>
</div>
</div>

第一列在XS和SM模式中佔據了一半空間,在MD和LG模式中佔據了三分之一。但是,第一列的內容包含了一些BR元素,讓該列比其他列高。在MD和LG中,顯示效果跟預期的完全一樣,三列都在一行中。但在XS和SM中,第三列會在哪顯示?看看圖9-3。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-3 第三列浮在行的左側佔據任何可用的空間

在XS和SM模式中,前兩列由於它們的col-xs-6類佔據了整個屏幕。結果,第三列流到下一行。但是,在這個特例中,第一列比其他的高,這會留出右邊的空間。Bootstrap重用屏幕實際空間來放置換到下一行的列。

一般來說,每當使用col-xx-n類時候,實際上是把CSS的float屬性設為left(或right)並讓瀏覽器找出最左(或最右)可用空間來放置特定元素。注意,要向右對齊,你只需把pull-right類添加到目標元素。

3.特定大小的類

如果想強制第三列去到下一行最左呢?你要顯式停用默認對齊,恢復DIV元素的區塊性質。在純CSS中,通過使用clear:both屬性的空DIV可以實現這點。這在Bootstrap中對應clearfix類。

<div class="clearfix"></div>

圖9-4展示瞭如果盲目使用clearfix類來強制第三列在下一行開始將會得到什麼。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-4 第三列現在從下一行最左邊開始

如果調整瀏覽器的窗口大小到XS或SM模式,一切如常。但是,圖9-4只展示了MD和LG模式的樣子。如你所見,使用clearfix類會留出右邊的空間,這裡本來可以放得下第三列。理想情況下,你可能想清除DIV元素的浮動樣式,但只針對XS和SM模式。

在Bootstrap中,visible-xx類和hidden-xx類就是為此而來的。

<div class="clearfix visible-xs"></div>

現在的效果就是你想要的。使用clearfix類的DIV現在只會在XS和SM屏幕上才會出現。類似的,你可以使用hidden-xx類隱藏元素和整行。

■ 注意:

hidden-xx類本身是Bootstrap提供的一個強大的工具,可以讓你創建專門的響應式Web模板,用來在用戶調整視口時或者在較小的全屏設備上查看內容時調整這些內容。我將會在第15章詳細講述響應式Web設計的代價是隱藏不想要的內容。這個效果對於用戶來說是好的,但對於應用程序來說是不必要的,尤其是在移動設備上使用RWD。

4.靈活渲染

下面簡單看看使用hidden-xx類的具體例子。假設你有一個登錄表單,在經典的用戶名/密碼錶單週圍有很多介紹文字和一幅圖片。

<div class="container">
<h1 class="hidden-xs">WELCOME to CONTOSO Industries</h1>
<h4 class="visible-xs">WELCOME to CONTOSO</h4>
<div class="col-md-4 hidden-xs hidden-sm">
<div class="center">
<img src="~/Content/Images/contoso.png" />
</div>
</div>
</div>

圖9-5展示了這個登錄表單在LG屏幕上的樣子。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-5 在MD和LG模式中顯示的靈活登錄表單

H1元素只在SM和更大的設備上顯示。但在XS設備上,H1元素會替換成更小的H4元素。另外,圖片只會在MD和LG屏幕上顯示。你可以在調整瀏覽器窗口的大小時看到區別。

5.偏移和把列往回拉

Bootstrap網格系統也支持嵌套列。你要做的就是把子行嵌入一列中。除此之外,一切都按照到目前為止討論的規則進行。列偏移也是支持的。它通過col-XX-offset-N類發揮作用。比如,col-md-offset-2會在MD和更大的設備上跳過接下來兩個網格列。

一般來說,列是按照它們在HTML代碼中出現的順序來渲染的。但是,col-XX-pull-N類和col-XX-push-N類可以用來修改列的自然順序,把列往前推或者往回拉。這有時候可以用來修改生產環節中的現有頁面。事實上,如果還在開發中,你可以輕易在源代碼中移動列並按照定義的自然順序渲染。

■ 注意:

使用Bootstrap時,會假設使用四個預定義的可視化斷點,即XS、SM、MD和LG。這些斷點在從頁面鏈接的源CSS中定義,不需要重新定義。如果想修改,只需編輯CSS文件副本。

9.3 現今Web元素的分類體系

Bootstrap是一個很大的庫,不可能在一章中講完。我強烈建議在瀏覽器中收藏getbootstrap.com鏈接,以便日後快速訪問在線文檔。總的來說,有兩種方式使用這個庫。一種是使用簡單的單個HTML元素(如按鈕和錨)並以不同的方式對它們進行樣式設置。另一種是創建專門的HTML塊,這是Bootstrap CSS和腳本代碼的預定義組合,可以變成完全不同且能工作的用戶界面。

總的來說,Bootstrap促成了現代Web用戶界面元素的分類體系的定義,包括基本元素(如輸入字段和按鈕)以及更復雜的組件,如導航欄、下拉列表、標籤條和彈框。最後,還對核心Bootstrap庫創建了一些擴展,這些在今天是難以忽略的。這當中有兩個是自動完成庫typeahead和日期選擇器組件。

9.3.1 重塑基本HTML元素的樣式

下面通過探討專門用於定製輸入字段、按鈕、導航欄和文本元素的樣式,來深入瞭解Bootstrap HTML編程。

1.輸入字段

輸入字段通常用在HTML表單中。我說“通常”是因為某些現代Web應用程序傾向於通過JavaScript把內容提交到遠程端點,並不一定要用HTML表單。如果你決定自己序列化要提交的內容,並不一定需要通過HTML表單收集內容。但是,不管你通過瀏覽器還是以編程的方式提交,HTML表單都是輸入字段的最常見容器。

以下是典型的Bootstrap輸入表單,用於登錄頁面。

<form class="form-inline" method="post"
action="@Url.Action("login", "account")">
<div class="form-group">
<div class="input-group">
<label for="username">User name</label>
<div class="input-group-addon">
<span class="glyphicon glyphicon-user"></span>
</div>
<input type="text" class="form-control" id="username" name="username"
maxlength="30" placeholder="User name">
</div>
</div>
<div class="form-group">
<div class="input-group">
<label for="password">Password</label>
<div class="input-group-addon">
<span class="glyphicon glyphicon-lock"></span>
</div>
<input type="password" class="form-control" id="password" name="password"
maxlength="30" placeholder="Password">
</div>
</div>
...
</form>

這個HTML表單可以採用兩個類:form-inline或form-horizontal。顧名思義,二者都會側重通知這個庫在一行上或者在多個水平行(標籤和輸入字段垂直排列)上優化子輸入元素的渲染。

Bootstrap HTML表單由多個分組組成。每個分組通常包含一個標籤和一個輸入字段,它可以是text、date、password、checkbox、hidden等。輸入元素應該套用form-control類並用input-lg或input-sm類設置大小。

<input type="password" class="form-control input-lg" id="password">

其他可以用在輸入字段上的所有屬性(如maxlength、placeholder、id、name和value)都正常使用和處理。

Bootstrap中有一個有趣的特性是輸入插件。輸入插件是輸入字段和按鈕、靜態文本的組合。單個輸入分組中的所有元素Bootstrap都會看作同一個HTML元素,如圖9-6所示。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-6 使用插件的Bootstrap輸入分組

以下是讓Bootstrap生成圖9-6所示的東西需要的全部標記內容。

<div class="input-group input-group-lg">
<span class="input-group-addon">@</span>
<input type="text" class="form-control" placeholder="Search for...">
<span class="input-group-btn">
<button class="btn btn-default" type="button">Action</button>
</span>
<div class="input-group-btn">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
...
</ul>
</div>

你可以使用input-group-addon類來創建文本佔位符,使用input-group-btn類向輸入字段田間按鈕或菜單。caret類應用到SPAN元素可以渲染出經典的向下三角形,表示更多內容。UL元素定義了一組下拉項。caret按鈕使用dropdown-toggle樣式來表示它可以按需顯示內容。最後,data-toggle類表示內容顯示的方式,在這裡是下拉顯示。

■ 重要:

仍然可以在應用了Bootstrap的頁面中使用輸入字段、按鈕和HTML元素。只要不向這些元素添加Bootstrap特定的類,Bootstrap就不會干涉瀏覽器的渲染。但是,整體外觀效果可能會與頁面的其他部分或者應用程序的其他頁面衝突,導致用戶不太滿意。如果選擇Bootstrap,就應該在要創建的所有頁面中使用它。

2.按鈕

在Bootstrap中,btn類會把提交按鈕、常規HTML按鈕和錨變成可點擊的方形區域。btn類的效果是純圖形的,它所做的就是添加填充、邊框、圓角和顏色。令人驚喜的是,把非文本內容添加到按鈕的標題非常簡單。

以下是使用btn類的最簡單方式。

<button class="btn">
Log in
</button>
<a href="#" class="btn" role="button">
...
</a>

btn類附帶一些輔助類可以定製按鈕的大小和顏色。默認情況下,Bootstrap按鈕會使用渲染指派給它的內容所需空間加上常規填充。btn-xs和btn-lg等類只是從默認btn移除或者添加額外填充。對於顏色,btn-primary、btn-danger、btn-alert、btn-success和btn-info樣式的按鈕採用不同顏色來表示通過這個按鈕實現的操作的重要程度。從開發者的角度來看,這是一種給頁面更一致的設計便捷  方式。

以下是定義Bootstrap按鈕的常見方式(見圖9-7)。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-7 示例Bootstrap按鈕

<button class="btn">
<span class="glyphicon glyphicon-ok"></span>
Log in
</button>

如你所見,在按鈕的標題中混用小圖片和文字非常容易。對於Bootstrap按鈕,通常使用glyphicons,這是一個特殊的內嵌字體,由渲染圖標和極小剪貼畫的庫附帶。如果不用原生Bootstrap圖標,你可以添加現有的圖標庫。一個最流行的圖標庫是FontAwesome,你可以登錄fontawesome官網瞭解到更多關於它的內容。一旦FontAwesome就緒,你可以像這樣重寫登錄按鈕。

<button class="btn">
<i class="fa fa-lg fa-ok"></i>
Log in
</button>

3.分組按鈕

通常,網頁需要顯示多個有著某種聯繫的按鈕。當然你可以單獨處理這些按鈕,按照喜歡的方式來設置它們的樣式。但是,幾年前iOS用戶界面引入了分段按鈕(segmented button)的概念。現在,如果不是必須情況下,分段按鈕成了想要的特性。分段按鈕本質上是一組單獨操作的按鈕,但渲染成單個按鈕條。最好看的效果是這個按鈕條的第一個和最後一個按鈕是圓角的,中間的按鈕是完全四方的。在Bootstrap中,可以使用以下HTML標記。

<div class="btn-group">
<button type="button" class="btn btn-success">Agree</button>
<button type="button" class="btn btn-default">Not sure</button>
<button type="button" class="btn btn-danger">Disagree</button>
</div>

每個按鈕都有自己的點擊處理器,顯式通過onclick屬性或悄悄通過jQuery添加。要創建按鈕分組,你要做的就是把一組按鈕包在一個使用btn-group樣式的DIV元素中。

分組中的按鈕大小可以通過額外的類btn-group-lg或btn-group-xs來控制。默認情況下,按鈕是水平堆疊的。要垂直堆疊它們,只需把btn-group-vertical類添加到按鈕分組。多個分組可以通過包裝在按鈕工具欄容器中並排放置。

<div>
<div class="btn-group">...</div>
<div class="btn-group">...</div>
<div class="btn-group">...</div>
</div>

從圖9-6來看,你可能覺得Bootstrap按鈕也可以用來實現下拉菜單,以下示範如何做到。

<div class="btn-group">
<button type="button" class="btn btn-default">One</button>
<button type="button" class="btn btn-default">Two</button>
<div class="btn-group">
<button type="button" class="btn dropdown-toggle" data-toggle="dropdown">
Numbers
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
</ul>
</div>
</div>

這個分組中前兩項是普通按鈕,接著是一個嵌套的下拉分組。這個按鈕分組由一個按鈕和一個附加的下拉菜單組成。有趣的是,按鈕有一個caret分段,通過視覺的方式傳遞更多選項可以看的消息。通過把dropup類添加到包裝這個列表的按鈕分組,你可以使這個列表向上顯示。

■ 重要:

在觀察Bootstrap的下拉按鈕時,你可能想到兩個常見的用戶界面元素:下拉菜單和下拉列表。按鈕分組是普通下拉菜單。下拉列表(就像你在普通HTML中通過SELECT/OPTION元素獲得的)是一個稍微不同的東西。對於選擇操作,Bootstrap沒有內置工具。在表單中使用的SELECT元素會和其他可視化元素有著明顯不同的樣式,這會是個問題。讓SELECT不同於普通菜單的是它跟蹤選中的項並把它展示給用戶和程序。

4.單選按鈕

很多用戶界面中的一個常見元素是單選按鈕。這是一組一起工作的互斥按鈕:每次只能選擇一個,選擇新的會自動移除當前選擇的按鈕。HTML為實現單選按鈕提供輸入元素的專門類型。藉助Bootstrap,你可以結合原生HTML輸入單選按鈕和分組按鈕創建更好的用戶界面。

下面演示如何創建一個單選按鈕列表用來在用戶個人資料編輯器中選擇性別。

<div class="btn-group" data-toggle="buttons">
<label class="btn btn-primary @active1">
<input type="radio" id="gender" name="gender" value="X" @checked1>
Don't show
</label>
<label class="btn btn-primary @active2">
<input type="radio" id="gender" name="gender" value="M" @checked2>
Male
</label>
<label class="btn btn-primary @active3">
<input type="radio" id="gender" name="gender" value="F" @checked3>
Female
</label>
</div>

圖9-8展示了結果。注意,按照設計,按鈕不是一樣大小的。你可以通過添加一些額外的自定義樣式來做到。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-8 Bootstrap單選按鈕

如前所述,Bootstrap的分組按鈕是並排的普通按鈕。但單選按鈕需要一些邏輯。你需要一些邏輯和分組按鈕把單選按鈕設成Bootstrap樣式。在剛才展示的代碼段中,你可以看到兩組Razor變量在用。理想情況下,圖9-8的標記內容前面會有以下代碼。

@{
var active1 = "";
var active2 = "active";
var active3 = "";
var checked1 = "";
var checked2 = "checked";
var checked3 = "";
}

變量active1、active2和active3的目的是向表示當前選擇的label元素添加active屬性。active屬性有可視化效果,會告訴Bootstrap把按鈕的樣式換成看起來像選中的樣子。與此同時,你應該把單選按鈕看作官方HTML輸入元素。單選按鈕列表通常託管在HTML表單中,在某一時刻,這個表單的內容會發送到服務器做進一步處理,但只會上傳帶有checked屬性的單選按鈕。checked1、checked2和checked3變量跟蹤每個按鈕的選中狀態,保證在頁面渲染到瀏覽器時對應的按鈕會顯示成選中或活動狀態。

5.導航欄

大多數網站都有導航欄,通常在頁面頂部。Bootstrap提供一些工具,向網頁添加標題。此外,Bootstrap導航欄非常靈活,當視口寬度改變時會摺疊或展開。在更小的視圖中,導航欄會自動摺疊成一個按鈕,需要JavaScript的支持才能展開。如果出於某些原因禁用了JavaScript,Bootstrap導航欄摺疊之後就不能展開了。

導航欄是純HTML容器,通常是一個DIV元素。但建議你把標題包裝在一個NAV元素中。

<div role="navigation">
...
</div>
<nav class="navbar navbar-default">
...
</nav>

role屬性定製了通用DIV元素,把它聲明成屏幕上的導航組件。以下是導航欄的可能結構,裡面包含兩個鏈接列表和一個搜索欄。

<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button"
class="navbar-toggle collapsed"
data-toggle="collapse"
data-target="#content">
<span class="sr-only">More</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Home</a>
</div>
<div class="collapse navbar-collapse" id="content">
<ul class="nav navbar-nav">
<li> <a href=""> Button #1 </a> </li>
...
</ul>
<form class="navbar-form navbar-left">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search for...">
</div>
<button type="submit" class="btn btn-primary">Find</button>
</form>
<ul class="nav navbar-nav navbar-right ">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
I want to <span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a href="#">Create a record</a></li>
...
</ul>
</li>
</ul>
</div>
</div>
</nav>

一個常見的導航欄由兩個部分組成:摺疊/展開基礎設施和在更小的視口上可以隱藏的實際  內容。

<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<!-- Collapse/Expand button to toggle on smaller viewports -->
</div>
<div class="collapse navbar-collapse" id="content">
<!-- Actual content being collapsed on smaller viewports -->
</div>
</div>
</nav>

內容區域通過唯一的ID來標識(在本例中,這個ID是content)。可摺疊區域通過可點擊按鈕的data-target屬性關聯到摺疊/展開基礎設施,這個按鈕實現了開關功能。接下來演示的三個SPAN元素渲染了標準的水平三橫線作為這個摺疊/展開按鈕。

<div class="navbar-header">
<button type="button"
class="navbar-toggle collapsed"
data-toggle="collapse"
data-target="#content">
<span class="sr-only">More</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>

內容區域可以包含你想要的任何東西,通常是快速訪問按鈕、下拉按鈕和搜索表單。所有按鈕通常都會渲染成UL/LI元素中的錨。

導航欄可以通過向NAV元素添加navbar-fixed-top類固定在頁面頂部。注意,如果打算把標題固定在頂部,必須相應地填充頁面的主體。換句話說,你必須把任何可見的主體內容向下移動導航欄佔據的同量像素。如果不這樣做,那些內容會被導航欄的絕對定位覆蓋。

body { padding-top: 100px; }

雖然不如頂部對齊常見,但你也可以把導航欄放在頁面底部,在這種情況下,只需向NAV元素添加navbar-fixed-bottom類就行了。

6.文本元素

Bootstrap提供三個工具來渲染結構化文本:面板、警報和方框(well)。面板由三個元素組成:標題、主體和底部。每個元素都會相應地設置樣式。以下是一個示例面板。注意,標題和底部元素是可選的。

<div class="panel panel-info">
<div class="panel-heading">
<span class="panel-title">Title</span>
</div>
<div class="panel-body">
Any content goes here
</div>
<div class="panel-footer">
Footer
</div>
</div>

這個面板可以使用為按鈕標出的相同元類設置樣式:panel-default、panel-primary、panel-info、panel-danger、panel-warning等。你也可以創建自己的元類。

警報是帶有HTML內容的普通DIV元素,除了它使用一些預定義的樣式,其配置如下所示。

<div class="alert alert-success" role="alert">
Any content goes here
</div>

另外,你可以在警報中使用不同的Bootstrap元類(成功、警告、危險、信息等)。在Bootstrap頁面中,警報通常用來顯示消息。一個有趣的特性是警報可以關閉的。

<div class="alert alert-warning alert-dismissible" role="alert" id="alert-id">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span>×</span>
</button>
<strong>Warning!</strong> This is message for you.
</div>

在這種情況下,這個警報有點大,右上角有個關閉按鈕。用戶可以通過單擊按鈕關閉這個DIV,頁面內容會浮現。另一個可以添加的好特性是計時器,它會在特定時間之後讓警報滑出來。

window.setTimeout(function () {
$("#alert-id").slideUp();
}, 4000);

■ 注意:

如果要在警報中放置鏈接,你只要把alert-link類添加到錨就能讓它的樣式和父警報的上下文信息一致。

最後,方框是由邊框和填充包圍的純文本。這是通過強調的方式展示某些文本的便捷方式。

<div class="well">
...
</div>

也可以在方框中使用調整大小的類,如well-lg和well-xs。

9.3.2 重塑列表HTML元素的樣式

作為iOS用戶界面架構師認為的一個有創造性的需求,按相關項目分組的可滾動列表在短短的幾年間蔓延設備領域並征服整個Web。jQuery Mobile首先實現分段值和可滾動列表並提供專門組建來構建它們。今天,Bootstrap也提供專門CSS類,把普通無序HTML列表和普通錨標記列表渲染成模擬iOS列表的好看區塊。

1.列表

在Bootstrap頁面中,普通列表項序列會自動變成帶邊框的表。來看以下標記內容:

<ul class="list-group">
<li class="list-group-item">First item</li>
<li class="list-group-item">Second item</li>
<li class="list-group-item">Third item</li>
<li class="list-group-item">Fourth item</li>
<li class="list-group-item">Fifth item</li>
</ul>

list-group類負責繪製內容周圍的邊框。list-group-item類負責邊距和字體。所有列表項都渲染成純文本。list-group的輸出類似於老式列表框,裡面展示了一組選項,一個或多個項會渲染成選中狀態。要把一個列表項標記成選中,需要添加active CSS類。可以把這個類添加到任意多個列 表項。

普通列表分組本質上是一個沒有用戶交互的靜態列表。列表分組的一個有趣變體是鏈表分組。關鍵區別是鏈表中的項是錨而不是純文本。

<li class="list-group-item">
<a href="...">First item</a>
</li>

要防止一個或多個項被點擊,可以使用SPAN元素而不是A元素,以下舉例。

<div class="list-group">
<span class="list-group-item list-header">Just Items</span>
<a href="..." class="list-group-item">First item</a>
<a href="..." class="list-group-item active">Second item</a>
</div>

可以使用不可點擊元素創建列表標題。標題標識列表框中的分段,就像iOS允許你做的那樣。和iOS用戶界面一樣,標記(badge)可以用來讓每個項中的文字更豐富更好看。標記是彩色氣球中的小文本,用來表示和頁面相關的某個東西的計數,如收件箱的消息。要實現這個效果,只需使用badge類標記SPAN元素,如下所示。

<a href="..." class="list-group-item">
First item <span class="badge">22</span>
</a>

在列表中使用的任何A元素的內容都可以隨意定製。它可以是純文本,也可以是HTML標記,還可以包含圖像或媒體。

<a href="#" class="list-group-item">
<p class="list-group-item-text">Some small text</p>
<h4 class="list-group-item-heading">Some bigger text here</h4>
</a>

要實現更加統一的圖形效果,可以使用預定義的樣式,如list-group-item-text和list-group-item- heading。但是,是否使用它們取決於你,因為這純粹是審美的問題。

2.媒體對象

大多數網頁的另一個常見特性是一組由文本和媒體內容(通常是圖像)組成的混合標記。對齊文本和圖像通常很無聊。Bootstrap嘗試通過幾個類讓這個過程更平滑。

<div class="media">
<div class="media-left">
<a href="#">
<img class="media-object" src="..." alt="...">
</a>
</div>
<div class="media-body">
<h4 class="media-heading">Title of the image</h4>
<span>Description of the image</span>
</div>
</div>

media-left類讓圖像緊貼容器左邊。你可以使用media-right類讓圖像緊貼右邊。但如果打算這樣做,那麼應該把最右邊的DIV放在標記中的媒體主體DIV之後。媒體內容默認的對齊方式是居上。可以通過向圖像DIV添加media-middle或media-bottom類把對齊方式改成居中或居下。

也可以在列表中使用媒體內容,創建帶有圖像和文本的列表項。可以用media類來包裝列表項並把media-list類用於整個列表。media-object類放在IMG元素上。media-body類裝飾圖像或者其他可能有的媒體對象(如視頻)旁邊的文本。示例如下:

<ul class="media-list">
<li class="media">
<div class="media-left">
<a href="#">
<img class="media-object" src="..." alt="...">
</a>
</div>
<div class="media-body">
<h4 class="media-heading">Title of the image</h4>
<span>Description of the image</span>
</div>
</li>
...
</ul>

注意,不管有沒有媒體內容,列表都很容易嵌入面板。

thumbnail不需要額外標記就可以用來展示相關圖像。以下示例佈局在中型和大型屏幕中會展示四個圖像,在小型屏幕中會展示兩個或三個。

<div class="row">
<div class="col-xs-6 col-sm-4 col-md-3">
<a href="#" class="thumbnail">
<img src="..." alt="...">
</a>
<div class="caption">
<h3>Thumbnail label</h3>
...
</div>
</div>
...
</div>

3.表格

多年來,開發者把純HTML表格用作佈局網頁內容的工具。今天,DIV元素和CSS定位屬性更靈活地實現這個目的。但這並不意味著HTML表格就沒用了。表格還是用來展示表格數據,例如,在數據網格中。

在Bootstrap中可以找到一些基本類來設置HTML表格的樣式,尤其是控制填充和行的顏色。

<table class="table table-condensed">
<tr> ... </tr>
</table>

table-condensed可以讓填充和邊距保持最低限度。還有其他類用於更復雜但很常見的效果,例如,修改行的顏色和懸停。注意,Bootstrap對於表格以及很多其他HTML構件都是單純圖形層面的。這意味著可以通過這些工具以特定方式渲染元素,但把樣式綁到數據取決於你。如果沒有更好的方式,把樣式綁到實際數據的最佳方式是通過Razor變量和專門的類,甚至內聯樣式。

9.3.3 瞭解更高級的組件

即使HTML是Web的官方語言,甚至可能在不久的將來成為移動應用程序的通用語言,但它沒有提供創建現代頁面所需的全部語法元素。本章前面講述了下拉菜單。如前所述,在Bootstrap中,你可以結合按鈕和無序的HTML錨列表來創建下拉菜單,即使在HTML5中沒有找到任何原生元素來構建下拉菜單。其他一些常見可視化元素也是如此,它們在頁面中很流行,但沒被HTML原生支持,至少沒有在最小化標記內容的抽象級別上。在本章中,我會演示如何在Bootstrap中構建模態對話框、標籤條和自定義工具提示。

1.模態對話框

模態窗口是顯示在其他一切之上的窗口並在顯示時捕獲輸入焦點。底下的元素只有在模態窗口關閉時才能重新獲得輸入焦點。模態窗口的一個好例子是瀏覽器在代碼調用window.alert JavaScript方法時顯示的消息框。但越來越多的頁面通過渲染頂層富DIV元素來強調向用戶展示的消息,或者作為不用完全刷新當前頁面就能執行任務的方式。

總的來說,模態對話框的最常見場景是在當前頁面的主體中實現輸入表單。在第12章中,我將會回到通過模態對話框實現輸入表單的話題,還會觸及提交之後的動作的實現。但在本章中,我更多會專注於在Bootstrap中顯示和填充模態對話框所需的步驟。

模態對話框由兩個元素組成:觸發器和內容。內容是由某些專門屬性裝飾普通DIV,這些屬性讓這個DIV保持隱藏直到觸發器觸發為止。觸發器通常是一個按鈕或者使用一些特殊屬性的錨。

下面舉個例子。

<button class="btn btn-primary btn-lg"
data-toggle="modal"
data-target="#dialogBox">
Launch modal
</button>
@Html.Partial("pv_rateitemmodal")

把data-toggle屬性設為modal表示這個按鈕是用來打開模態元素的。data-target元素是選擇要打開DIV元素的CSS表達式。要讓前面例子中的觸發器工作,當前DOM必須可以找到一個DOM子樹,而且其根元素的ID是dialogBox。模態內容的DIV可以放在當前頁面中,或者通過Html.Partial Razor方法作為分部視圖導入。最終的結果是一樣的,但使用分部視圖讓你的HTML視圖更簡單更易維護。

以下是模態對話框的示例內容。

<div class="modal" id="dialogBox">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"> × </button>
<h4 class="modal-title">Rate the article</h4>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"> Close</
button>
<button type="button" class="btn btn-primary" onclick="...">Vote </button>
</div>
</div>
</div>
</div>

模態對話框由三個層次的嵌套DIV元素組成。最外層DIV使用modal類設置樣式。你可以在這裡添加用於外觀的特定樣式,如fade或slide類。它的直接子元素設為modal-dialog樣式。另一層DIV是modal-content。在內容DIV中,你可以找到頭部、主體和底部。頭部和底部是可選的,但通常兩者都有,而且用頭部來給對話框添加標題和關閉按鈕,而底部通常會放置關閉對話框的按鈕。這些按鈕要麼直接關閉對話框,要麼啟動服務器端操作。

在本例中,底部有兩個按鈕:Close和Vote。由於data-dismiss屬性的作用,Close按鈕只能用來關閉對話框。但Vote按鈕通常會附加onclick處理器來執行某些JavaScript任務。

如果使用模態對話框來內聯編輯記錄,你需要一種方式把模態對話框的元素初始化為要顯示的數據。如果這個模態對話框有一些固定的內容要顯示,你可以把初始化邏輯放在生成模態對話框或者包含頁面的Razor視圖中。但如果你有一組記錄,想在用戶點擊特定記錄時顯示一個模態對話框,就必須在客戶端執行初始化來獲取JSON數據。要做到這點,可以使用JavaScript處理模態Bootstrap組件觸發的一些事件。

下面舉個例子。

$('#dialogBox).on('show.bs.modal', function (e) {
$.ajax({
url: "...",
cache: false
}).done(function(json) {
// Update the user interface
// with downloaded data
});
});

模態組件一觸發show.bs.modal事件(就在內容顯示之前),就會發起Ajax調用到某個URL來下載數據。接著,對話框的用戶界面會用新的內容更新,然後展示給用戶。

■ 注意:

如果只是尋找一個比系統警報消息框渲染起來更靈活的替代方案,你可以嘗試Toastr。Toastr是一個jQuery插件,它顯示顏色豐富的純文本並提供定位和計時器方面的選項。以下代碼演示如何使用它。

toastr.options.positionClass = "alert-center"; toastr.success("Isn't this popup much better than a plain alert()?", "Better alert!");

除了“success”,toastr庫還提供多種顯示方法,每種都採用了不同圖標和顏色。消息可以留在屏幕上直到用戶關閉它,或者關聯到一個計時器。showDuration和hideDuration等屬性表示顯示和隱藏內容所需的毫秒數。內容通常由標題和文本消息組成。

2.標籤條

標籤是一組每次只能顯示一個的視圖,可以通過頂部菜單選擇。Bootstrap支持標籤的一些變體,包括經典的標籤條和導航Pill。所需的HTML模板是類似的。

下面先看經典的標籤條。

<div class="tabbable">
<ul class="nav nav-tabs" id="myTabStrip">
<li><a class="btn btn-primary" href="#profile" data-toggle="tab">Profile</a></li>
<li><a class="btn btn-primary" href="#preferences" data-toggle="tab"> Preferences </a></li>
<li><a class="btn btn-primary" href="#friends" data-toggle="tab">Friends</a></li>
</ul>
</div>

第一個包裝UL元素的DIV定義了可點擊的標籤列表。任何時候用戶點擊任何標籤,當前內容就會隱藏,與被點擊標籤相關的內容就會顯示。LI元素的href屬性表示保存標籤內容的子DIV的路徑。把data-toggle屬性設為tab也是很重要的,因為它告訴這個組件按照標籤的方式工作,按需隱藏和顯示內容。

標籤內容在同一個頁面後面,一個接一個地排列。這些DIV是否可見由標籤條組件附帶的腳本代碼自動管理。

<div class="tab-content">
<div id="profile" class="tab-pane">
...
</div>
<div id="preferences" class="tab-pane">
...
</div>
<div id="friends" class="tab-pane">
...
</div>
</div>

在標籤的內容DIV元素中指定tab-content和tab-pane CSS類是很重要的。標籤條從Bootstrap的默認配置中獲取自己的樣式。在外部,可以使用按鈕樣式來選擇標籤的顏色,如btn-primary、btn-danger等。但是,默認的Bootstrap樣式可以在應用程序或單個頁面的範圍內重寫。一開始選中的標籤通過active類表示。

可能考慮的一個有趣的特性是添加JavaScript調用來移除邊框,它通常在點擊之後顯示在可點擊區域周圍。你需要把以下調用添加到標籤條的LI元素。

onclick="this.blur()"

標籤條水平渲染,一個標籤接一個。另一個稍微不同的視圖是導航Pill。在這種情況下,標籤文字的渲染是沒有邊框和分隔符的,只有選中的Pill有填充和不同顏色。它的行為是一樣的,只是外觀不同。

<ul class="nav nav-pills" role="tablist">
<li class="active">
<a class="btn btn-primary" href="#profile" data-toggle="tab">Profile</a>
</li>
<li> ... </li>
<li> ... </li>
</ul>

這些Pill也可以垂直堆疊。可以通過添加nav-stacked樣式來實現。

3.工具提示

工具提示自瀏覽器初期就已經可以在網頁上使用了,但一直以來都沒有改變。原生瀏覽器的工具提示自20世紀90年代至今都是一行很短的靜態文字的彈窗。

只需把一些純文本包裝在帶有title屬性的HTML元素(甚至普通的SPAN元素)中,就可以顯示工具提示了。工具提示由瀏覽器顯示並受限於瀏覽器的實現,沒有辦法改變。jQuery的出現激發了為實現好看的工具提示效果而創建各種插件。開發者的問題就變成了如何選擇最好的最合適的工具提示插件。Bootstrap的作者自行做了選擇,把一些特性整合到這個庫中。因此,今天,一旦選擇Bootstrap,你也會在這個包中找到很好的工具提示基礎設施。

在Bootstrap中,工具提示是任何把data-toggle屬性設為tooltip關鍵字的HTML元素。不必多說,HTML元素也必須有title屬性來表示要顯示的文字。

下面舉個例子。

<p>
This is a message about
<span data-toggle="tooltip" title="Some extra information">
something
</span>
incorporated in the web page ...
</p>

把data-toggle屬性設為tooltip關鍵字實現了這個效果。當用戶在敏感的元素上懸停時,就會顯示內容。但是,如果只把這段標記內容複製到使用Bootstrap的頁面,什麼都不會發生。原因是,按照設計,Bootstrap架構師決定讓工具提示成為選擇加入功能。這意味著需要一些腳本來激活自定義工具提示。注意,只要找到默認的title屬性,瀏覽器就會顯示內置的工具提示用戶界面。

在Bootstrap中,需要以下腳本代碼來啟用工具提示。你可能會在頁面的ready事件處理器中運行這段代碼。

$(document).ready(function () {
$("[data-toggle=tooltip]").tooltip();
});

可以看到,這個代碼不只啟用一個特定的工具提示。它會擴展到覆蓋頁面中出現的所有工具提示。Bootstrap工具提示支持各種常規瀏覽器工具提示中找不到的特性。首先,它允許添加一個箭頭指示器並把工具提示放在它指向的文字周圍的特定位置上,可以放在上邊、左邊、下邊或者右邊。如果選擇“auto”,框架會把它放在最適合的位置。

另一個有趣的特性是HTML內容。基本上,Bootstrap允許在title屬性中放置任何HTML內容。但是,只有在工具提示的選項中設置了html標記,才會把這些內容渲染成HTML。

$("[data-toggle=tooltip]").tooltip({
placement: 'auto',
html: true
});

此外,可以用trigger選項來指定這個工具提示如何觸發。默認情況下,當鼠標在這個元素上懸停以及這個元素獲得焦點時,就會顯示工具提示。可以改變或者添加通過點擊觸發它的選項。

$("[data-toggle=tooltip]").tooltip({
placement: 'auto',
html: true,
trigger: 'click focus hover'
});

最後,工具提示可以通過方法編程控制並在顯示或關閉時觸發事件。

4.彈框

工具提示和彈框密切相關,雖然有著不同的名字。在特定元素上懸停時,工具提示就會顯示。彈框支持更豐富的格式化選項,可以通過各種方式觸發,包括當用戶在特定HTML元素上懸停時。一般來說,彈框是在一個元素附近顯示成下拉框的DIV元素。讓彈框特別有趣的是它們可以使用實時數據填充,如果你通過JavaScript添加一些數據綁定邏輯。

首先,創建一開始要隱藏的DIV元素,然後可以配置彈框的觸發器:它可以是一個按鈕或者一個可點擊元素。這跟之前給工具提示做的很像。唯一的區別是,data-toggle屬性必須設為popover。

<div id="popover-content" class="hidden">
...
</div>

接著,添加一些腳本從指定DIV元素的內容初始化這個彈框。

$("#sensitive").popover({
html: true,
title: "More Details",
placement: 'right',
trigger: 'click',
content: function () {
return $("#popover-content").html();
}
});

在這段代碼中,#sensitive路徑表示這個彈框指向的元素。基本上,這個代碼會自動把名為popover-content的DIV元素內容附加到#sensitive元素,每當點擊該項時彈框就會顯示。彈框有默認大小。你可以通過修改Bootstrap庫中的.popover CSS類來改變它。為彈框選擇的觸發器機制決定了關閉這個內容的方式。觸發選項和工具提示的一樣:hover、click和focus。

工具提示和彈框的優劣

工具提示和彈框的主要目標是顯示一個頁面元素的更多信息。但除此之外,決定何時使用工具提示是非常主觀的。下面是一些常識性的規則。

首先,通過工具提示顯示的文本不應該對用戶決定做什麼有根本性影響。工具提示中的文本應該是補充性的。如果工具提示的文本對於幫助用戶決定如何行動很重要,你應該把這些文本直接放在用戶界面上。其次,不應該使用工具提示顯示錯誤或警告。警報框在這些情況下可能更適合。

此外,工具提示和彈框不應該分散用戶的注意力或者打擾他們。展示的信息不應該重複或重述屏幕上已經存在的信息。

9.5 小結

最終,我相信不在網站中使用Bootstrap的原因很少。使用它的一個很好的原因是,已經有一個模板讓你在頁面中使用的大多數構件都有統一的外觀。菜單、下拉列表、按鈕、複選框、標籤欄和模態對話框等東西經常會在網頁中看到,並且必須以某種(圖形)形式展現。

Bootstrap提供一些內置工具,但Web設計師可以做出同樣的東西,同時使得網站的整體外觀一致。這是不用Bootstrap的一個好理由。但同時,這是理解Bootstrap在現代Web中的能力和角色的好方式:要麼使用它,要麼你使用某個能做它所做的東西,只不過外觀不同。

使用Bootstrap,你會體驗到一個相對短的學習曲線,有很多模板(Bootstrap的變體)是免費的,還有很多隻需要一筆很小的費用。如果你是一名Web設計師或者打算僱傭一名Web設計師,應該要求最終的模板是基於Bootstrap的。

本章概覽了Bootstrap,涵蓋了它的主要特性和組件。我試著讓大家看看真實的Bootstrap及其在真實網站的使用。但我不確定是否涵蓋它的所有重要方面。我鼓勵大家直接從Bootstrap的文檔瞭解更多的組件、特性、樣式和擴展。

最後有一點要記住的,Bootstrap預示著一個響應式Web設計的時代,這個設計方法學旨在向用戶提供理想的體驗,不管屏幕大小如何。響應式Web設計肯定是個好主意,它的好在於讓Boostrap模板適用於任何類型的移動設備。但是,就像Bootstrap未能免除對更好圖形內容的需求,它也不能免除有時候要通過專門的移動網站以特定方式應對某些設備(尤其是智能手機和更老的手機)的需要。我將在第15章回到這一點。

本文截選自《全棧工程師Web開發指南》第九章部分內容。

"

計算機非人性的一部分表現是,一旦完成編譯並且順利運行,它將忠實地完成工作。

——艾薩克·阿西莫夫

Bootstrap是一個CSS和JavaScript庫,它致力於簡化現代網頁的構建,原本是Twitter開發給內部使用的。但是,“現代網頁”到底是什麼呢?

非常簡單,現代網頁是按照現在大多數用戶想要的樣子構建的網頁。HTML語言仍然是網頁的基礎和核心語言。但是,HTML標記語言的構造越來越不能快速直接地表達構成現代網頁的複雜和成熟。比如,下拉菜單、分段選項按鈕、標籤欄、可摺疊標籤和模態對話框都是大多數頁面的常見元素,卻沒有現成的HTML元素。

Bootstrap提供直接的方式,把HTML塊變成現代網站所需的更加成熟的可視化元素。

9.1 Bootstrap概覽

Bootstrap是一個模塊化的Web庫,由CSS和JavaScript文件組成。CSS文件包含了重新設計常見HTML元素的類,使它們看上去不一樣,或許更好看。JavaScript文件是一組jQuery插件,支持更加複雜的特性,這些特性無法單純通過CSS實現。

Bootstrap最初開發成一組LESS文件,你仍然能夠以LESS文件的方式獲取CSS部分。一般來說,有組成Bootstrap庫的每個模塊的LESS或CSS文件:表單、按鈕、導航欄、對話框等。在深入Bootstrap庫之前,下面先來看看LESS。

9.1.1 LESS和Bootstrap基礎

LESS文件是構建在普通CSS語法之上的一個抽象層,讓開發者可以聲明一個CSS文件最終將會如何使用。你可以把LESS看作一門編程語言,一旦編譯就會產生CSS。在LESS文件裡,可以使用變量、函數和運算符,因此極大地提高了創建和維護大型複雜CSS樣式表的流程效率。

1.變量

開發者使用LESS解決的一大問題是信息的重複。軟件開發者可能深諳“自己不要重複”(Don’t Repeat Yourself, DRY)原則並且每天踐行。DRY的最大好處是減少相同信息保存位置的個數,因而減少應該更新的位置的個數。在普通CSS裡,無法做到DRY。比如,如果特定顏色在多個CSS類裡使用(某些時候要更新),除了在每個出現的地方更新,你可能沒有更好的辦法了。

CSS類的問題在於它們在語義HTML元素的級別工作。在構建各種CSS類時,你通常需要重複小塊信息,比如顏色或寬度。你無法輕易為每個可重複的小塊信息創建一個類。即使每個可重複樣式都有一個CSS類,如顏色和寬度,當把樣式應用到語義元素(如容器)時,需要聯合多個CSS類才能實現預期效果。

考慮以下CSS例子。

.container {
color: #111;
}
.header {
background-color: #111;
}

container和header兩個CSS類都使用相同的顏色。如果那個顏色需要改變,那麼必須找出所有使用它的地方然後編輯。下面使用LESS重寫相同的特性。

@black: #111;
.container {
color: @black;
}
.header {
background-color: @black;
}

現在,這個顏色定義在一個地方,作為全局變量。從這裡來看,LESS把程序員喜歡的概念添加到CSS編碼了,如變量。但它能做的不止這些。

2.導入

可以把LESS代碼分割到多個文件,在需要的時候引用它們。假設創建一個container.less文件,它包含如下內容。

@black: #111;
.container {
background-color: @black;
}

在另一個LESS文件裡,比如main.less,可以通過導入這個文件來引用整個CSS。

@import "container";
.body { .container; }

如果container.less文件(擴展名不是必需的)放在另一個文件夾裡,你應該在調用@import時給出路徑信息。

3.混入(Mixins)

讓CSS樣式適配不同分辨率的能力是很重要的,尤其在網頁必須適配不同屏幕大小時。比如,當按鈕在平板上顯示且針對粗粒度指針(如手指)時,開發者通常會增加按鈕周圍的邊距(padding)。一般來說,如何使相同的CSS類根據某些運行時條件改變並且產生不同的顯示效果,這就是LESS混入派上用場的地方了。

以下是幾個混入示例。

.shadow(@color) {
box-shadow: 3px 3px 2px @color;
}
.text-box(@width) {
.shadow(#555);
border: solid 1px #000;
background-color: #dddd00;
padding: 2px;
width: @width;
}

可以從這裡派生出更加具體的CSS類,如下所示。

.text-box-mini {
.text-box(50px);
}
.text-box-normal {
.text-box(100px);
}
.text-box-large {
.text-box(200px);
}

這正是Bootstrap為了支持常見元素(如按鈕和輸入框)的不同風格在內部做的。

4.把LESS變成CSS

雖然LESS可以用作CSS的元語言,但LESS不是CSS。它必須進行某種處理來生成普通CSS。LESS代碼可以原樣下載並在客戶端通過JavaScript代碼處理,或者也可以在服務器上預處理,然後把普通CSS下載到客戶端。前者像在使用普通CSS文件:服務器端的更改會在下個頁面刷新時應用到客戶端。

但是,如果你有性能顧慮,而且要處理很大很複雜的CSS文件,服務器端預處理可能是個更好的選擇。服務器端預處理會在你每次修改服務器上的CSS時發生。通常,你會在構建流程的最後通過命令行使用LESS編譯器執行額外的步驟。Gulp等工具可以使用JavaScript相關的步驟來擴展構建流程。另一個流行的工具是Microsoft Web Essentials(一個Visual Studio插件),可以用來添加專門的菜單命令、處理CSS和腳本文件等Web資源。

但是,在ASP.NET MVC裡,還有另一種做法。你可以通過捆綁和壓縮機制整合整個LESS框架。在第10章裡,你將會詳細瞭解到,捆綁流程會把多個不同資源打包成單個可下載資源。比如,一個捆綁可能包含多個JavaScript和CSS文件,你可以通過向專門的終結點發送單個HTTP請求把它下載到本地機器。壓縮是應用到資源的特殊轉換。具體來說,壓縮會從文本資源移除所有不必要的字符,但不會改變預期功能。這意味著移除註釋、空白字符、換行符以及所有用於改善可讀性但只佔用空間的非功能性字符。

9.1.2 設置Bootstrap

可以從NuGet獲取Bootstrap。這種情況下,可以只取框架中所需要的部分。Bootstrap通常會用於整個網站,這樣可以從主視圖連接它,如下所示。

<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" src="@Url.Content("~/content/styles/bootstrap.min.css")">

viewport meta標籤把瀏覽器視口(Viewport)的寬度設為實際設備寬度並把放大級別設為標準。link元素只是引入Bootstrap樣式表的壓縮版本。如果打算使用更高級的Bootstrap特性,鑑於這些特性需要JavaScript,可以鏈接腳本文件以及它依賴的jQuery文件。

<script type="text/javascript"
src="@Url.Content("~/content/scripts/jquery-2.1.4.min.js")"></script>
<script type="text/javascript"
src="@Url.Content("~/content/scripts/bootstrap.min.js")"></script>

如果使用完整的Bootstrap庫,一旦鏈接了CSS和腳本文件,就已經準備好了。如果只用Bootstrap庫的部分,則必須確保需要的所有部分都正確鏈接。值得注意的是,Bootstrap庫的某些特性(比如工具提示和彈出界面)需要一些啟動JavaScript代碼,這些代碼必須添加代碼到每個頁面。

■ 注意:

Bootstrap不受老的Internet Explorer兼容模式支持。要確保頁面在Internet Explorer下能以最佳渲染方式查看,最好的辦法是在你的頁面裡添加以下meta標籤。

<meta http-equiv="X-UA-Compatible" content="IE=edge">

Bootstrap的CSS類使用了最新的CSS特性(如圓角效果),這可能不適用於老的瀏覽器。Internet Explorer 8就是部分支持Bootstrap的老瀏覽器的好樣板。

9.1.3 透析Bootstrap

Twitter Bootstrap在今天幾乎是必備的,原因是它使得向現代網站添加高級特性變得快速容易。Bootstrap的學習曲線比較短,很多基於它的模板都是免費的。但對於任何Web設計師而言,自定義基本Bootstrap模板實現獨特的效果也不是什麼難事。

Bootstrap是否適合你的項目取決於外觀的重要性。如果你的客戶需要自己的外觀,Bootstrap可能不是理想的。在這種情況下,開發團隊只收到圖形模板並使用它。此外,Bootstrap非常適合外觀重要但不是根本的快速項目。

換句話說,Bootstrap是一個很好的產品,但無法取代很好的設計。同時,它無法取代為每個設備定義得很好的用戶體驗。很容易找到一些網站提供基於Bootstrap的免費或付費模板。如果你限制自己使用Bootstrap庫的默認樣式(不改變CSS或LESS源代碼),那麼面臨的風險就是所有網站最終看起來都一樣。

要不要使用Bootstrap是一個架構決定,必須在項目早期做,後期很難更改。把Bootstrap添加到正在進行的項目或者從中刪除雖然不是不可能,但也通常有問題。最後,考慮到完整的Bootstrap庫包含100KB的CSS和30KB的腳本,這不是很大的資源,但也不是輕量級資源,尤其是使用較慢連接的較小設備。

Bootstrap的快速普及的其中一個關鍵原因是創建從不同類型設備看起來不錯的頁面成本很低。

■ 注意:

正如你將在第15章中看到的,有兩種截然不同的方式為多個設備設計網站。反應式Web設計是一種讓一套HTML頁面自動適配實際屏幕大小的方案。這是Bootstrap推廣的方案。其他方案為一些關鍵設備創建一套單獨的頁面,最突出的是智能手機。我將會在第16章講述這個話題。

9.2 反應式佈局

今天,所有網站至少都應該反應託管屏幕的寬度變化。作為開發團隊的一員,你有兩種主要方式實現這個功能。你可以從供應商那裡購買一個HTML反應式模板,堅持使用,讓實現細節透明,或者自行開發這個模板。

在後一種情況中,你會使用哪個框架呢?Bootstrap可能是人們應該考慮的第一個框架,但不是唯一的。其他同樣熱門和有效的響應式框架有Foundation、Skeleton和Gumby。任何學習Bootstrap的方案都從它提供的賦予HTML視圖響應式佈局的服務開始。

9.2.1 網格系統

Bootstrap有一個靈活的網格系統,它把水平可用空間分成12等份物理列。Bootstrap提供預定義CSS類,讓你可以通過創建邏輯列隨意佈局模板。換句話說,Bootstrap讓你可以通過一個範圍從1~12個單位的測量系統來安排模板空間。Bootstrap單位的實際大小取決於設備的實際屏幕大小。

屏幕大小實際上是視口——內容的可視化區域。在移動設備上,設備屏幕和視口一致,因為設備通常不支持可調整大小的窗口。而在臺式機上,你可以把窗口的大小調整到比最大可用空間小。在這種情況下,Bootstrap認為視口是可用渲染空間。

1.整體模板

任何Bootstrap內容要響應屏幕大小的改變都會基於行列矩陣。整體容器(這個矩陣)是一個樣式設為container的DIV元素(見圖9-1)。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-1 Bootstrap流體網格的架構

2.容器和行

最外層的容器處理任何必要的對齊,也負責填充。如果你沒有顯式定義一行,就會假設這一行佔滿整個高度。任何用戶界面內容都是放在列中的。注意,只有列允許成為行的直接子元素。Bootstrap中的任何內容通常都會根據以下架構佈局。

容器 > 行 > 列

前面代碼中的每個單詞都是你平常應用到DIV元素的Bootstrap類名。特別地,container管理頁面寬度和填充。row樣式確保內容放在同一行中,多行垂直堆疊。如果你的代碼中沒有行元素,容器中的任何內容都會水平排列,在碰到屏幕邊緣時會換到下一行。

最後,column元素表示行中的單個內容快。Bootstrap為列定義了多個實際類。要定義行中的一個列,你可以根據這個模式使用類名:col-××-N。在這個模式中,××表示設備類型前綴,可以是表9-1中的任何值。很快就會看到,每個××代碼都綁到以像素為單位的特定寬度,也叫斷點(breakpoint)。

全棧工程師Web開發指南:Bootstrap的精髓

模式中的N是一個介於1~12的數字,它表示這列內容在這個虛擬的網格中實際佔用多少列。下面來看一個例子。

<div class="container">
<div class="row">
<div class="col-xs-6 col-md-4"> First </div>
<div class="col-xs-6 col-md-4"> Second </div>
<div class="col-xs-6 col-md-4"> Third </div>
</div>
</div>

在這種情況下,你想在1行中渲染3列布局。所有列都是一樣大小,所有列在中型設備中顯示成一行。col-md-4樣式讓每列在虛擬Bootstrap網格系統裡都佔用4列寬度(一共12列)。

更小和更大的設備呢?

在XS設備上,這3列內容每個都會在渲染時佔據半個屏幕寬度。你可能會想,如果每列都佔據半個屏幕寬度,那麼3列不可能放入整個屏幕寬度。在這裡,第3列會溢出到下一行。同樣的結果會發生在SM設備上。但在LG設備上會使用MD樣式設置的規則。

原則上,流體行中的每列都可以使用多個設備的屬性來為寬度設置樣式。那些屬性對於更大的設備總是適用的,直到出現更特定的設置。鑑於此,如果你不需要按照設備區分佈局,最好一直使用XS樣式。列樣式中的N之和應該總是不超過12。如果超過了,任何超出第12列的列都會溢出到下一行。

3.容器和流體容器

到目前為止,我們只考慮把container類用於DIV元素。還有一個稍微不同的版本你可能在某些情況下會考慮到:container-fluid類。普通容器的每個斷點都是固定寬度的,只有用戶調整瀏覽器大小時跨越了斷點才會改變視口寬度。

而流體容器佔據父元素的全部寬度,通常是100%的瀏覽器可用視口。視口寬度會在每次調整大小時重新計算和更新。在使用流體容器時,用戶體驗會更平滑,但使用流體容器通常對桌面設備更有意義。

9.2.2 基於屏幕大小的渲染

為什麼要使用多列設置呢?答案通常取決於所要展示的實際內容。套用前面的例子,三列布局在中型大小的設備上可能沒問題,但列的內容可能太多而不能在更小屏幕的三分之一上渲染。這就是為什麼我把col-xs-6添加到DIV樣式。最終的效果是,Bootstrap會根據屏幕的實際大小改變最終行為。

在中型和大型設備上,你會有三列布局,在小型和更小設備上每行只有兩列。第三列在小型和更小設備上會換到下一行。如果這不是你想要的,可以考慮在小型和更小設備上隱藏第三列。下面看看怎麼做到。

1.虛擬測量和實際屏幕大小

Bootstrap中的整個網格系統和設備類型都是基於斷點的,見表9-2。如你所見,每個屏幕代碼都關聯了一個表示更小、小型、中型和大型設備預期寬度的斷點。

全棧工程師Web開發指南:Bootstrap的精髓

如果不指定col-xx-n樣式,會默認XS屏幕。對這些代碼類別的常見反應是Bootstrap不能讓你輕鬆處理這裡列出的非常小的設備,即768像素或更小的寬度。老設備落入這個範圍,它們可能需要和寬度大於768像素的更大設備不同的特定處理。

要監視Bootstrap如何改變頁面佈局,可以使用以下腳本代碼,只要把它添加到一個網頁就行了。

<script type="text/javascript">
updateSize();
$(window).resize(function() {
updateSize();
});
function currentBootstrapScreenClass() {
var screen = "LG";
var width = $(window).width();
if (width <= 768)
screen = "XS";
else if (width <= 992)
screen = "SM";
else if (width <= 1200)
screen = "MD";
return screen;
}
function updateSize() {
var info = currentBootstrapScreenClass();
$('#currentScreenWidth').text($(window).width() + "px");
$('#currentViewport').text(info);
}
</script>

顯然,這個網頁必須一些匹配一下ID的元素。

<span id="currentScreenWidth"></span>
<span id="currentViewport"></span>

效果如圖9-2所示。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-2 屏幕大小和Bootstrap類之間的關係

col-xx-n類是Bootstrap提供的讓頁面佈局適配屏幕大小的主要工具。還有更強大的工具可以針對特定屏幕大小隱藏和嵌套列。

2.多分辨率視圖

如前所述,就列布局而言,你可以把多個設置賦給容器和行。下面來看一個有趣的例子。

<div class="container">
<div class="row">
<div class="col-xs-6 col-md-4"> Column #1 <br /> Column #1 <br /></div>
<div class="col-xs-6 col-md-4"> Column #2 </div>
<div class="col-md-4"> Column #3 </div>
</div>
</div>

第一列在XS和SM模式中佔據了一半空間,在MD和LG模式中佔據了三分之一。但是,第一列的內容包含了一些BR元素,讓該列比其他列高。在MD和LG中,顯示效果跟預期的完全一樣,三列都在一行中。但在XS和SM中,第三列會在哪顯示?看看圖9-3。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-3 第三列浮在行的左側佔據任何可用的空間

在XS和SM模式中,前兩列由於它們的col-xs-6類佔據了整個屏幕。結果,第三列流到下一行。但是,在這個特例中,第一列比其他的高,這會留出右邊的空間。Bootstrap重用屏幕實際空間來放置換到下一行的列。

一般來說,每當使用col-xx-n類時候,實際上是把CSS的float屬性設為left(或right)並讓瀏覽器找出最左(或最右)可用空間來放置特定元素。注意,要向右對齊,你只需把pull-right類添加到目標元素。

3.特定大小的類

如果想強制第三列去到下一行最左呢?你要顯式停用默認對齊,恢復DIV元素的區塊性質。在純CSS中,通過使用clear:both屬性的空DIV可以實現這點。這在Bootstrap中對應clearfix類。

<div class="clearfix"></div>

圖9-4展示瞭如果盲目使用clearfix類來強制第三列在下一行開始將會得到什麼。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-4 第三列現在從下一行最左邊開始

如果調整瀏覽器的窗口大小到XS或SM模式,一切如常。但是,圖9-4只展示了MD和LG模式的樣子。如你所見,使用clearfix類會留出右邊的空間,這裡本來可以放得下第三列。理想情況下,你可能想清除DIV元素的浮動樣式,但只針對XS和SM模式。

在Bootstrap中,visible-xx類和hidden-xx類就是為此而來的。

<div class="clearfix visible-xs"></div>

現在的效果就是你想要的。使用clearfix類的DIV現在只會在XS和SM屏幕上才會出現。類似的,你可以使用hidden-xx類隱藏元素和整行。

■ 注意:

hidden-xx類本身是Bootstrap提供的一個強大的工具,可以讓你創建專門的響應式Web模板,用來在用戶調整視口時或者在較小的全屏設備上查看內容時調整這些內容。我將會在第15章詳細講述響應式Web設計的代價是隱藏不想要的內容。這個效果對於用戶來說是好的,但對於應用程序來說是不必要的,尤其是在移動設備上使用RWD。

4.靈活渲染

下面簡單看看使用hidden-xx類的具體例子。假設你有一個登錄表單,在經典的用戶名/密碼錶單週圍有很多介紹文字和一幅圖片。

<div class="container">
<h1 class="hidden-xs">WELCOME to CONTOSO Industries</h1>
<h4 class="visible-xs">WELCOME to CONTOSO</h4>
<div class="col-md-4 hidden-xs hidden-sm">
<div class="center">
<img src="~/Content/Images/contoso.png" />
</div>
</div>
</div>

圖9-5展示了這個登錄表單在LG屏幕上的樣子。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-5 在MD和LG模式中顯示的靈活登錄表單

H1元素只在SM和更大的設備上顯示。但在XS設備上,H1元素會替換成更小的H4元素。另外,圖片只會在MD和LG屏幕上顯示。你可以在調整瀏覽器窗口的大小時看到區別。

5.偏移和把列往回拉

Bootstrap網格系統也支持嵌套列。你要做的就是把子行嵌入一列中。除此之外,一切都按照到目前為止討論的規則進行。列偏移也是支持的。它通過col-XX-offset-N類發揮作用。比如,col-md-offset-2會在MD和更大的設備上跳過接下來兩個網格列。

一般來說,列是按照它們在HTML代碼中出現的順序來渲染的。但是,col-XX-pull-N類和col-XX-push-N類可以用來修改列的自然順序,把列往前推或者往回拉。這有時候可以用來修改生產環節中的現有頁面。事實上,如果還在開發中,你可以輕易在源代碼中移動列並按照定義的自然順序渲染。

■ 注意:

使用Bootstrap時,會假設使用四個預定義的可視化斷點,即XS、SM、MD和LG。這些斷點在從頁面鏈接的源CSS中定義,不需要重新定義。如果想修改,只需編輯CSS文件副本。

9.3 現今Web元素的分類體系

Bootstrap是一個很大的庫,不可能在一章中講完。我強烈建議在瀏覽器中收藏getbootstrap.com鏈接,以便日後快速訪問在線文檔。總的來說,有兩種方式使用這個庫。一種是使用簡單的單個HTML元素(如按鈕和錨)並以不同的方式對它們進行樣式設置。另一種是創建專門的HTML塊,這是Bootstrap CSS和腳本代碼的預定義組合,可以變成完全不同且能工作的用戶界面。

總的來說,Bootstrap促成了現代Web用戶界面元素的分類體系的定義,包括基本元素(如輸入字段和按鈕)以及更復雜的組件,如導航欄、下拉列表、標籤條和彈框。最後,還對核心Bootstrap庫創建了一些擴展,這些在今天是難以忽略的。這當中有兩個是自動完成庫typeahead和日期選擇器組件。

9.3.1 重塑基本HTML元素的樣式

下面通過探討專門用於定製輸入字段、按鈕、導航欄和文本元素的樣式,來深入瞭解Bootstrap HTML編程。

1.輸入字段

輸入字段通常用在HTML表單中。我說“通常”是因為某些現代Web應用程序傾向於通過JavaScript把內容提交到遠程端點,並不一定要用HTML表單。如果你決定自己序列化要提交的內容,並不一定需要通過HTML表單收集內容。但是,不管你通過瀏覽器還是以編程的方式提交,HTML表單都是輸入字段的最常見容器。

以下是典型的Bootstrap輸入表單,用於登錄頁面。

<form class="form-inline" method="post"
action="@Url.Action("login", "account")">
<div class="form-group">
<div class="input-group">
<label for="username">User name</label>
<div class="input-group-addon">
<span class="glyphicon glyphicon-user"></span>
</div>
<input type="text" class="form-control" id="username" name="username"
maxlength="30" placeholder="User name">
</div>
</div>
<div class="form-group">
<div class="input-group">
<label for="password">Password</label>
<div class="input-group-addon">
<span class="glyphicon glyphicon-lock"></span>
</div>
<input type="password" class="form-control" id="password" name="password"
maxlength="30" placeholder="Password">
</div>
</div>
...
</form>

這個HTML表單可以採用兩個類:form-inline或form-horizontal。顧名思義,二者都會側重通知這個庫在一行上或者在多個水平行(標籤和輸入字段垂直排列)上優化子輸入元素的渲染。

Bootstrap HTML表單由多個分組組成。每個分組通常包含一個標籤和一個輸入字段,它可以是text、date、password、checkbox、hidden等。輸入元素應該套用form-control類並用input-lg或input-sm類設置大小。

<input type="password" class="form-control input-lg" id="password">

其他可以用在輸入字段上的所有屬性(如maxlength、placeholder、id、name和value)都正常使用和處理。

Bootstrap中有一個有趣的特性是輸入插件。輸入插件是輸入字段和按鈕、靜態文本的組合。單個輸入分組中的所有元素Bootstrap都會看作同一個HTML元素,如圖9-6所示。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-6 使用插件的Bootstrap輸入分組

以下是讓Bootstrap生成圖9-6所示的東西需要的全部標記內容。

<div class="input-group input-group-lg">
<span class="input-group-addon">@</span>
<input type="text" class="form-control" placeholder="Search for...">
<span class="input-group-btn">
<button class="btn btn-default" type="button">Action</button>
</span>
<div class="input-group-btn">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
...
</ul>
</div>

你可以使用input-group-addon類來創建文本佔位符,使用input-group-btn類向輸入字段田間按鈕或菜單。caret類應用到SPAN元素可以渲染出經典的向下三角形,表示更多內容。UL元素定義了一組下拉項。caret按鈕使用dropdown-toggle樣式來表示它可以按需顯示內容。最後,data-toggle類表示內容顯示的方式,在這裡是下拉顯示。

■ 重要:

仍然可以在應用了Bootstrap的頁面中使用輸入字段、按鈕和HTML元素。只要不向這些元素添加Bootstrap特定的類,Bootstrap就不會干涉瀏覽器的渲染。但是,整體外觀效果可能會與頁面的其他部分或者應用程序的其他頁面衝突,導致用戶不太滿意。如果選擇Bootstrap,就應該在要創建的所有頁面中使用它。

2.按鈕

在Bootstrap中,btn類會把提交按鈕、常規HTML按鈕和錨變成可點擊的方形區域。btn類的效果是純圖形的,它所做的就是添加填充、邊框、圓角和顏色。令人驚喜的是,把非文本內容添加到按鈕的標題非常簡單。

以下是使用btn類的最簡單方式。

<button class="btn">
Log in
</button>
<a href="#" class="btn" role="button">
...
</a>

btn類附帶一些輔助類可以定製按鈕的大小和顏色。默認情況下,Bootstrap按鈕會使用渲染指派給它的內容所需空間加上常規填充。btn-xs和btn-lg等類只是從默認btn移除或者添加額外填充。對於顏色,btn-primary、btn-danger、btn-alert、btn-success和btn-info樣式的按鈕採用不同顏色來表示通過這個按鈕實現的操作的重要程度。從開發者的角度來看,這是一種給頁面更一致的設計便捷  方式。

以下是定義Bootstrap按鈕的常見方式(見圖9-7)。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-7 示例Bootstrap按鈕

<button class="btn">
<span class="glyphicon glyphicon-ok"></span>
Log in
</button>

如你所見,在按鈕的標題中混用小圖片和文字非常容易。對於Bootstrap按鈕,通常使用glyphicons,這是一個特殊的內嵌字體,由渲染圖標和極小剪貼畫的庫附帶。如果不用原生Bootstrap圖標,你可以添加現有的圖標庫。一個最流行的圖標庫是FontAwesome,你可以登錄fontawesome官網瞭解到更多關於它的內容。一旦FontAwesome就緒,你可以像這樣重寫登錄按鈕。

<button class="btn">
<i class="fa fa-lg fa-ok"></i>
Log in
</button>

3.分組按鈕

通常,網頁需要顯示多個有著某種聯繫的按鈕。當然你可以單獨處理這些按鈕,按照喜歡的方式來設置它們的樣式。但是,幾年前iOS用戶界面引入了分段按鈕(segmented button)的概念。現在,如果不是必須情況下,分段按鈕成了想要的特性。分段按鈕本質上是一組單獨操作的按鈕,但渲染成單個按鈕條。最好看的效果是這個按鈕條的第一個和最後一個按鈕是圓角的,中間的按鈕是完全四方的。在Bootstrap中,可以使用以下HTML標記。

<div class="btn-group">
<button type="button" class="btn btn-success">Agree</button>
<button type="button" class="btn btn-default">Not sure</button>
<button type="button" class="btn btn-danger">Disagree</button>
</div>

每個按鈕都有自己的點擊處理器,顯式通過onclick屬性或悄悄通過jQuery添加。要創建按鈕分組,你要做的就是把一組按鈕包在一個使用btn-group樣式的DIV元素中。

分組中的按鈕大小可以通過額外的類btn-group-lg或btn-group-xs來控制。默認情況下,按鈕是水平堆疊的。要垂直堆疊它們,只需把btn-group-vertical類添加到按鈕分組。多個分組可以通過包裝在按鈕工具欄容器中並排放置。

<div>
<div class="btn-group">...</div>
<div class="btn-group">...</div>
<div class="btn-group">...</div>
</div>

從圖9-6來看,你可能覺得Bootstrap按鈕也可以用來實現下拉菜單,以下示範如何做到。

<div class="btn-group">
<button type="button" class="btn btn-default">One</button>
<button type="button" class="btn btn-default">Two</button>
<div class="btn-group">
<button type="button" class="btn dropdown-toggle" data-toggle="dropdown">
Numbers
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
</ul>
</div>
</div>

這個分組中前兩項是普通按鈕,接著是一個嵌套的下拉分組。這個按鈕分組由一個按鈕和一個附加的下拉菜單組成。有趣的是,按鈕有一個caret分段,通過視覺的方式傳遞更多選項可以看的消息。通過把dropup類添加到包裝這個列表的按鈕分組,你可以使這個列表向上顯示。

■ 重要:

在觀察Bootstrap的下拉按鈕時,你可能想到兩個常見的用戶界面元素:下拉菜單和下拉列表。按鈕分組是普通下拉菜單。下拉列表(就像你在普通HTML中通過SELECT/OPTION元素獲得的)是一個稍微不同的東西。對於選擇操作,Bootstrap沒有內置工具。在表單中使用的SELECT元素會和其他可視化元素有著明顯不同的樣式,這會是個問題。讓SELECT不同於普通菜單的是它跟蹤選中的項並把它展示給用戶和程序。

4.單選按鈕

很多用戶界面中的一個常見元素是單選按鈕。這是一組一起工作的互斥按鈕:每次只能選擇一個,選擇新的會自動移除當前選擇的按鈕。HTML為實現單選按鈕提供輸入元素的專門類型。藉助Bootstrap,你可以結合原生HTML輸入單選按鈕和分組按鈕創建更好的用戶界面。

下面演示如何創建一個單選按鈕列表用來在用戶個人資料編輯器中選擇性別。

<div class="btn-group" data-toggle="buttons">
<label class="btn btn-primary @active1">
<input type="radio" id="gender" name="gender" value="X" @checked1>
Don't show
</label>
<label class="btn btn-primary @active2">
<input type="radio" id="gender" name="gender" value="M" @checked2>
Male
</label>
<label class="btn btn-primary @active3">
<input type="radio" id="gender" name="gender" value="F" @checked3>
Female
</label>
</div>

圖9-8展示了結果。注意,按照設計,按鈕不是一樣大小的。你可以通過添加一些額外的自定義樣式來做到。

全棧工程師Web開發指南:Bootstrap的精髓

圖9-8 Bootstrap單選按鈕

如前所述,Bootstrap的分組按鈕是並排的普通按鈕。但單選按鈕需要一些邏輯。你需要一些邏輯和分組按鈕把單選按鈕設成Bootstrap樣式。在剛才展示的代碼段中,你可以看到兩組Razor變量在用。理想情況下,圖9-8的標記內容前面會有以下代碼。

@{
var active1 = "";
var active2 = "active";
var active3 = "";
var checked1 = "";
var checked2 = "checked";
var checked3 = "";
}

變量active1、active2和active3的目的是向表示當前選擇的label元素添加active屬性。active屬性有可視化效果,會告訴Bootstrap把按鈕的樣式換成看起來像選中的樣子。與此同時,你應該把單選按鈕看作官方HTML輸入元素。單選按鈕列表通常託管在HTML表單中,在某一時刻,這個表單的內容會發送到服務器做進一步處理,但只會上傳帶有checked屬性的單選按鈕。checked1、checked2和checked3變量跟蹤每個按鈕的選中狀態,保證在頁面渲染到瀏覽器時對應的按鈕會顯示成選中或活動狀態。

5.導航欄

大多數網站都有導航欄,通常在頁面頂部。Bootstrap提供一些工具,向網頁添加標題。此外,Bootstrap導航欄非常靈活,當視口寬度改變時會摺疊或展開。在更小的視圖中,導航欄會自動摺疊成一個按鈕,需要JavaScript的支持才能展開。如果出於某些原因禁用了JavaScript,Bootstrap導航欄摺疊之後就不能展開了。

導航欄是純HTML容器,通常是一個DIV元素。但建議你把標題包裝在一個NAV元素中。

<div role="navigation">
...
</div>
<nav class="navbar navbar-default">
...
</nav>

role屬性定製了通用DIV元素,把它聲明成屏幕上的導航組件。以下是導航欄的可能結構,裡面包含兩個鏈接列表和一個搜索欄。

<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button"
class="navbar-toggle collapsed"
data-toggle="collapse"
data-target="#content">
<span class="sr-only">More</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Home</a>
</div>
<div class="collapse navbar-collapse" id="content">
<ul class="nav navbar-nav">
<li> <a href=""> Button #1 </a> </li>
...
</ul>
<form class="navbar-form navbar-left">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search for...">
</div>
<button type="submit" class="btn btn-primary">Find</button>
</form>
<ul class="nav navbar-nav navbar-right ">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
I want to <span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a href="#">Create a record</a></li>
...
</ul>
</li>
</ul>
</div>
</div>
</nav>

一個常見的導航欄由兩個部分組成:摺疊/展開基礎設施和在更小的視口上可以隱藏的實際  內容。

<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<!-- Collapse/Expand button to toggle on smaller viewports -->
</div>
<div class="collapse navbar-collapse" id="content">
<!-- Actual content being collapsed on smaller viewports -->
</div>
</div>
</nav>

內容區域通過唯一的ID來標識(在本例中,這個ID是content)。可摺疊區域通過可點擊按鈕的data-target屬性關聯到摺疊/展開基礎設施,這個按鈕實現了開關功能。接下來演示的三個SPAN元素渲染了標準的水平三橫線作為這個摺疊/展開按鈕。

<div class="navbar-header">
<button type="button"
class="navbar-toggle collapsed"
data-toggle="collapse"
data-target="#content">
<span class="sr-only">More</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>

內容區域可以包含你想要的任何東西,通常是快速訪問按鈕、下拉按鈕和搜索表單。所有按鈕通常都會渲染成UL/LI元素中的錨。

導航欄可以通過向NAV元素添加navbar-fixed-top類固定在頁面頂部。注意,如果打算把標題固定在頂部,必須相應地填充頁面的主體。換句話說,你必須把任何可見的主體內容向下移動導航欄佔據的同量像素。如果不這樣做,那些內容會被導航欄的絕對定位覆蓋。

body { padding-top: 100px; }

雖然不如頂部對齊常見,但你也可以把導航欄放在頁面底部,在這種情況下,只需向NAV元素添加navbar-fixed-bottom類就行了。

6.文本元素

Bootstrap提供三個工具來渲染結構化文本:面板、警報和方框(well)。面板由三個元素組成:標題、主體和底部。每個元素都會相應地設置樣式。以下是一個示例面板。注意,標題和底部元素是可選的。

<div class="panel panel-info">
<div class="panel-heading">
<span class="panel-title">Title</span>
</div>
<div class="panel-body">
Any content goes here
</div>
<div class="panel-footer">
Footer
</div>
</div>

這個面板可以使用為按鈕標出的相同元類設置樣式:panel-default、panel-primary、panel-info、panel-danger、panel-warning等。你也可以創建自己的元類。

警報是帶有HTML內容的普通DIV元素,除了它使用一些預定義的樣式,其配置如下所示。

<div class="alert alert-success" role="alert">
Any content goes here
</div>

另外,你可以在警報中使用不同的Bootstrap元類(成功、警告、危險、信息等)。在Bootstrap頁面中,警報通常用來顯示消息。一個有趣的特性是警報可以關閉的。

<div class="alert alert-warning alert-dismissible" role="alert" id="alert-id">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span>×</span>
</button>
<strong>Warning!</strong> This is message for you.
</div>

在這種情況下,這個警報有點大,右上角有個關閉按鈕。用戶可以通過單擊按鈕關閉這個DIV,頁面內容會浮現。另一個可以添加的好特性是計時器,它會在特定時間之後讓警報滑出來。

window.setTimeout(function () {
$("#alert-id").slideUp();
}, 4000);

■ 注意:

如果要在警報中放置鏈接,你只要把alert-link類添加到錨就能讓它的樣式和父警報的上下文信息一致。

最後,方框是由邊框和填充包圍的純文本。這是通過強調的方式展示某些文本的便捷方式。

<div class="well">
...
</div>

也可以在方框中使用調整大小的類,如well-lg和well-xs。

9.3.2 重塑列表HTML元素的樣式

作為iOS用戶界面架構師認為的一個有創造性的需求,按相關項目分組的可滾動列表在短短的幾年間蔓延設備領域並征服整個Web。jQuery Mobile首先實現分段值和可滾動列表並提供專門組建來構建它們。今天,Bootstrap也提供專門CSS類,把普通無序HTML列表和普通錨標記列表渲染成模擬iOS列表的好看區塊。

1.列表

在Bootstrap頁面中,普通列表項序列會自動變成帶邊框的表。來看以下標記內容:

<ul class="list-group">
<li class="list-group-item">First item</li>
<li class="list-group-item">Second item</li>
<li class="list-group-item">Third item</li>
<li class="list-group-item">Fourth item</li>
<li class="list-group-item">Fifth item</li>
</ul>

list-group類負責繪製內容周圍的邊框。list-group-item類負責邊距和字體。所有列表項都渲染成純文本。list-group的輸出類似於老式列表框,裡面展示了一組選項,一個或多個項會渲染成選中狀態。要把一個列表項標記成選中,需要添加active CSS類。可以把這個類添加到任意多個列 表項。

普通列表分組本質上是一個沒有用戶交互的靜態列表。列表分組的一個有趣變體是鏈表分組。關鍵區別是鏈表中的項是錨而不是純文本。

<li class="list-group-item">
<a href="...">First item</a>
</li>

要防止一個或多個項被點擊,可以使用SPAN元素而不是A元素,以下舉例。

<div class="list-group">
<span class="list-group-item list-header">Just Items</span>
<a href="..." class="list-group-item">First item</a>
<a href="..." class="list-group-item active">Second item</a>
</div>

可以使用不可點擊元素創建列表標題。標題標識列表框中的分段,就像iOS允許你做的那樣。和iOS用戶界面一樣,標記(badge)可以用來讓每個項中的文字更豐富更好看。標記是彩色氣球中的小文本,用來表示和頁面相關的某個東西的計數,如收件箱的消息。要實現這個效果,只需使用badge類標記SPAN元素,如下所示。

<a href="..." class="list-group-item">
First item <span class="badge">22</span>
</a>

在列表中使用的任何A元素的內容都可以隨意定製。它可以是純文本,也可以是HTML標記,還可以包含圖像或媒體。

<a href="#" class="list-group-item">
<p class="list-group-item-text">Some small text</p>
<h4 class="list-group-item-heading">Some bigger text here</h4>
</a>

要實現更加統一的圖形效果,可以使用預定義的樣式,如list-group-item-text和list-group-item- heading。但是,是否使用它們取決於你,因為這純粹是審美的問題。

2.媒體對象

大多數網頁的另一個常見特性是一組由文本和媒體內容(通常是圖像)組成的混合標記。對齊文本和圖像通常很無聊。Bootstrap嘗試通過幾個類讓這個過程更平滑。

<div class="media">
<div class="media-left">
<a href="#">
<img class="media-object" src="..." alt="...">
</a>
</div>
<div class="media-body">
<h4 class="media-heading">Title of the image</h4>
<span>Description of the image</span>
</div>
</div>

media-left類讓圖像緊貼容器左邊。你可以使用media-right類讓圖像緊貼右邊。但如果打算這樣做,那麼應該把最右邊的DIV放在標記中的媒體主體DIV之後。媒體內容默認的對齊方式是居上。可以通過向圖像DIV添加media-middle或media-bottom類把對齊方式改成居中或居下。

也可以在列表中使用媒體內容,創建帶有圖像和文本的列表項。可以用media類來包裝列表項並把media-list類用於整個列表。media-object類放在IMG元素上。media-body類裝飾圖像或者其他可能有的媒體對象(如視頻)旁邊的文本。示例如下:

<ul class="media-list">
<li class="media">
<div class="media-left">
<a href="#">
<img class="media-object" src="..." alt="...">
</a>
</div>
<div class="media-body">
<h4 class="media-heading">Title of the image</h4>
<span>Description of the image</span>
</div>
</li>
...
</ul>

注意,不管有沒有媒體內容,列表都很容易嵌入面板。

thumbnail不需要額外標記就可以用來展示相關圖像。以下示例佈局在中型和大型屏幕中會展示四個圖像,在小型屏幕中會展示兩個或三個。

<div class="row">
<div class="col-xs-6 col-sm-4 col-md-3">
<a href="#" class="thumbnail">
<img src="..." alt="...">
</a>
<div class="caption">
<h3>Thumbnail label</h3>
...
</div>
</div>
...
</div>

3.表格

多年來,開發者把純HTML表格用作佈局網頁內容的工具。今天,DIV元素和CSS定位屬性更靈活地實現這個目的。但這並不意味著HTML表格就沒用了。表格還是用來展示表格數據,例如,在數據網格中。

在Bootstrap中可以找到一些基本類來設置HTML表格的樣式,尤其是控制填充和行的顏色。

<table class="table table-condensed">
<tr> ... </tr>
</table>

table-condensed可以讓填充和邊距保持最低限度。還有其他類用於更復雜但很常見的效果,例如,修改行的顏色和懸停。注意,Bootstrap對於表格以及很多其他HTML構件都是單純圖形層面的。這意味著可以通過這些工具以特定方式渲染元素,但把樣式綁到數據取決於你。如果沒有更好的方式,把樣式綁到實際數據的最佳方式是通過Razor變量和專門的類,甚至內聯樣式。

9.3.3 瞭解更高級的組件

即使HTML是Web的官方語言,甚至可能在不久的將來成為移動應用程序的通用語言,但它沒有提供創建現代頁面所需的全部語法元素。本章前面講述了下拉菜單。如前所述,在Bootstrap中,你可以結合按鈕和無序的HTML錨列表來創建下拉菜單,即使在HTML5中沒有找到任何原生元素來構建下拉菜單。其他一些常見可視化元素也是如此,它們在頁面中很流行,但沒被HTML原生支持,至少沒有在最小化標記內容的抽象級別上。在本章中,我會演示如何在Bootstrap中構建模態對話框、標籤條和自定義工具提示。

1.模態對話框

模態窗口是顯示在其他一切之上的窗口並在顯示時捕獲輸入焦點。底下的元素只有在模態窗口關閉時才能重新獲得輸入焦點。模態窗口的一個好例子是瀏覽器在代碼調用window.alert JavaScript方法時顯示的消息框。但越來越多的頁面通過渲染頂層富DIV元素來強調向用戶展示的消息,或者作為不用完全刷新當前頁面就能執行任務的方式。

總的來說,模態對話框的最常見場景是在當前頁面的主體中實現輸入表單。在第12章中,我將會回到通過模態對話框實現輸入表單的話題,還會觸及提交之後的動作的實現。但在本章中,我更多會專注於在Bootstrap中顯示和填充模態對話框所需的步驟。

模態對話框由兩個元素組成:觸發器和內容。內容是由某些專門屬性裝飾普通DIV,這些屬性讓這個DIV保持隱藏直到觸發器觸發為止。觸發器通常是一個按鈕或者使用一些特殊屬性的錨。

下面舉個例子。

<button class="btn btn-primary btn-lg"
data-toggle="modal"
data-target="#dialogBox">
Launch modal
</button>
@Html.Partial("pv_rateitemmodal")

把data-toggle屬性設為modal表示這個按鈕是用來打開模態元素的。data-target元素是選擇要打開DIV元素的CSS表達式。要讓前面例子中的觸發器工作,當前DOM必須可以找到一個DOM子樹,而且其根元素的ID是dialogBox。模態內容的DIV可以放在當前頁面中,或者通過Html.Partial Razor方法作為分部視圖導入。最終的結果是一樣的,但使用分部視圖讓你的HTML視圖更簡單更易維護。

以下是模態對話框的示例內容。

<div class="modal" id="dialogBox">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"> × </button>
<h4 class="modal-title">Rate the article</h4>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"> Close</
button>
<button type="button" class="btn btn-primary" onclick="...">Vote </button>
</div>
</div>
</div>
</div>

模態對話框由三個層次的嵌套DIV元素組成。最外層DIV使用modal類設置樣式。你可以在這裡添加用於外觀的特定樣式,如fade或slide類。它的直接子元素設為modal-dialog樣式。另一層DIV是modal-content。在內容DIV中,你可以找到頭部、主體和底部。頭部和底部是可選的,但通常兩者都有,而且用頭部來給對話框添加標題和關閉按鈕,而底部通常會放置關閉對話框的按鈕。這些按鈕要麼直接關閉對話框,要麼啟動服務器端操作。

在本例中,底部有兩個按鈕:Close和Vote。由於data-dismiss屬性的作用,Close按鈕只能用來關閉對話框。但Vote按鈕通常會附加onclick處理器來執行某些JavaScript任務。

如果使用模態對話框來內聯編輯記錄,你需要一種方式把模態對話框的元素初始化為要顯示的數據。如果這個模態對話框有一些固定的內容要顯示,你可以把初始化邏輯放在生成模態對話框或者包含頁面的Razor視圖中。但如果你有一組記錄,想在用戶點擊特定記錄時顯示一個模態對話框,就必須在客戶端執行初始化來獲取JSON數據。要做到這點,可以使用JavaScript處理模態Bootstrap組件觸發的一些事件。

下面舉個例子。

$('#dialogBox).on('show.bs.modal', function (e) {
$.ajax({
url: "...",
cache: false
}).done(function(json) {
// Update the user interface
// with downloaded data
});
});

模態組件一觸發show.bs.modal事件(就在內容顯示之前),就會發起Ajax調用到某個URL來下載數據。接著,對話框的用戶界面會用新的內容更新,然後展示給用戶。

■ 注意:

如果只是尋找一個比系統警報消息框渲染起來更靈活的替代方案,你可以嘗試Toastr。Toastr是一個jQuery插件,它顯示顏色豐富的純文本並提供定位和計時器方面的選項。以下代碼演示如何使用它。

toastr.options.positionClass = "alert-center"; toastr.success("Isn't this popup much better than a plain alert()?", "Better alert!");

除了“success”,toastr庫還提供多種顯示方法,每種都採用了不同圖標和顏色。消息可以留在屏幕上直到用戶關閉它,或者關聯到一個計時器。showDuration和hideDuration等屬性表示顯示和隱藏內容所需的毫秒數。內容通常由標題和文本消息組成。

2.標籤條

標籤是一組每次只能顯示一個的視圖,可以通過頂部菜單選擇。Bootstrap支持標籤的一些變體,包括經典的標籤條和導航Pill。所需的HTML模板是類似的。

下面先看經典的標籤條。

<div class="tabbable">
<ul class="nav nav-tabs" id="myTabStrip">
<li><a class="btn btn-primary" href="#profile" data-toggle="tab">Profile</a></li>
<li><a class="btn btn-primary" href="#preferences" data-toggle="tab"> Preferences </a></li>
<li><a class="btn btn-primary" href="#friends" data-toggle="tab">Friends</a></li>
</ul>
</div>

第一個包裝UL元素的DIV定義了可點擊的標籤列表。任何時候用戶點擊任何標籤,當前內容就會隱藏,與被點擊標籤相關的內容就會顯示。LI元素的href屬性表示保存標籤內容的子DIV的路徑。把data-toggle屬性設為tab也是很重要的,因為它告訴這個組件按照標籤的方式工作,按需隱藏和顯示內容。

標籤內容在同一個頁面後面,一個接一個地排列。這些DIV是否可見由標籤條組件附帶的腳本代碼自動管理。

<div class="tab-content">
<div id="profile" class="tab-pane">
...
</div>
<div id="preferences" class="tab-pane">
...
</div>
<div id="friends" class="tab-pane">
...
</div>
</div>

在標籤的內容DIV元素中指定tab-content和tab-pane CSS類是很重要的。標籤條從Bootstrap的默認配置中獲取自己的樣式。在外部,可以使用按鈕樣式來選擇標籤的顏色,如btn-primary、btn-danger等。但是,默認的Bootstrap樣式可以在應用程序或單個頁面的範圍內重寫。一開始選中的標籤通過active類表示。

可能考慮的一個有趣的特性是添加JavaScript調用來移除邊框,它通常在點擊之後顯示在可點擊區域周圍。你需要把以下調用添加到標籤條的LI元素。

onclick="this.blur()"

標籤條水平渲染,一個標籤接一個。另一個稍微不同的視圖是導航Pill。在這種情況下,標籤文字的渲染是沒有邊框和分隔符的,只有選中的Pill有填充和不同顏色。它的行為是一樣的,只是外觀不同。

<ul class="nav nav-pills" role="tablist">
<li class="active">
<a class="btn btn-primary" href="#profile" data-toggle="tab">Profile</a>
</li>
<li> ... </li>
<li> ... </li>
</ul>

這些Pill也可以垂直堆疊。可以通過添加nav-stacked樣式來實現。

3.工具提示

工具提示自瀏覽器初期就已經可以在網頁上使用了,但一直以來都沒有改變。原生瀏覽器的工具提示自20世紀90年代至今都是一行很短的靜態文字的彈窗。

只需把一些純文本包裝在帶有title屬性的HTML元素(甚至普通的SPAN元素)中,就可以顯示工具提示了。工具提示由瀏覽器顯示並受限於瀏覽器的實現,沒有辦法改變。jQuery的出現激發了為實現好看的工具提示效果而創建各種插件。開發者的問題就變成了如何選擇最好的最合適的工具提示插件。Bootstrap的作者自行做了選擇,把一些特性整合到這個庫中。因此,今天,一旦選擇Bootstrap,你也會在這個包中找到很好的工具提示基礎設施。

在Bootstrap中,工具提示是任何把data-toggle屬性設為tooltip關鍵字的HTML元素。不必多說,HTML元素也必須有title屬性來表示要顯示的文字。

下面舉個例子。

<p>
This is a message about
<span data-toggle="tooltip" title="Some extra information">
something
</span>
incorporated in the web page ...
</p>

把data-toggle屬性設為tooltip關鍵字實現了這個效果。當用戶在敏感的元素上懸停時,就會顯示內容。但是,如果只把這段標記內容複製到使用Bootstrap的頁面,什麼都不會發生。原因是,按照設計,Bootstrap架構師決定讓工具提示成為選擇加入功能。這意味著需要一些腳本來激活自定義工具提示。注意,只要找到默認的title屬性,瀏覽器就會顯示內置的工具提示用戶界面。

在Bootstrap中,需要以下腳本代碼來啟用工具提示。你可能會在頁面的ready事件處理器中運行這段代碼。

$(document).ready(function () {
$("[data-toggle=tooltip]").tooltip();
});

可以看到,這個代碼不只啟用一個特定的工具提示。它會擴展到覆蓋頁面中出現的所有工具提示。Bootstrap工具提示支持各種常規瀏覽器工具提示中找不到的特性。首先,它允許添加一個箭頭指示器並把工具提示放在它指向的文字周圍的特定位置上,可以放在上邊、左邊、下邊或者右邊。如果選擇“auto”,框架會把它放在最適合的位置。

另一個有趣的特性是HTML內容。基本上,Bootstrap允許在title屬性中放置任何HTML內容。但是,只有在工具提示的選項中設置了html標記,才會把這些內容渲染成HTML。

$("[data-toggle=tooltip]").tooltip({
placement: 'auto',
html: true
});

此外,可以用trigger選項來指定這個工具提示如何觸發。默認情況下,當鼠標在這個元素上懸停以及這個元素獲得焦點時,就會顯示工具提示。可以改變或者添加通過點擊觸發它的選項。

$("[data-toggle=tooltip]").tooltip({
placement: 'auto',
html: true,
trigger: 'click focus hover'
});

最後,工具提示可以通過方法編程控制並在顯示或關閉時觸發事件。

4.彈框

工具提示和彈框密切相關,雖然有著不同的名字。在特定元素上懸停時,工具提示就會顯示。彈框支持更豐富的格式化選項,可以通過各種方式觸發,包括當用戶在特定HTML元素上懸停時。一般來說,彈框是在一個元素附近顯示成下拉框的DIV元素。讓彈框特別有趣的是它們可以使用實時數據填充,如果你通過JavaScript添加一些數據綁定邏輯。

首先,創建一開始要隱藏的DIV元素,然後可以配置彈框的觸發器:它可以是一個按鈕或者一個可點擊元素。這跟之前給工具提示做的很像。唯一的區別是,data-toggle屬性必須設為popover。

<div id="popover-content" class="hidden">
...
</div>

接著,添加一些腳本從指定DIV元素的內容初始化這個彈框。

$("#sensitive").popover({
html: true,
title: "More Details",
placement: 'right',
trigger: 'click',
content: function () {
return $("#popover-content").html();
}
});

在這段代碼中,#sensitive路徑表示這個彈框指向的元素。基本上,這個代碼會自動把名為popover-content的DIV元素內容附加到#sensitive元素,每當點擊該項時彈框就會顯示。彈框有默認大小。你可以通過修改Bootstrap庫中的.popover CSS類來改變它。為彈框選擇的觸發器機制決定了關閉這個內容的方式。觸發選項和工具提示的一樣:hover、click和focus。

工具提示和彈框的優劣

工具提示和彈框的主要目標是顯示一個頁面元素的更多信息。但除此之外,決定何時使用工具提示是非常主觀的。下面是一些常識性的規則。

首先,通過工具提示顯示的文本不應該對用戶決定做什麼有根本性影響。工具提示中的文本應該是補充性的。如果工具提示的文本對於幫助用戶決定如何行動很重要,你應該把這些文本直接放在用戶界面上。其次,不應該使用工具提示顯示錯誤或警告。警報框在這些情況下可能更適合。

此外,工具提示和彈框不應該分散用戶的注意力或者打擾他們。展示的信息不應該重複或重述屏幕上已經存在的信息。

9.5 小結

最終,我相信不在網站中使用Bootstrap的原因很少。使用它的一個很好的原因是,已經有一個模板讓你在頁面中使用的大多數構件都有統一的外觀。菜單、下拉列表、按鈕、複選框、標籤欄和模態對話框等東西經常會在網頁中看到,並且必須以某種(圖形)形式展現。

Bootstrap提供一些內置工具,但Web設計師可以做出同樣的東西,同時使得網站的整體外觀一致。這是不用Bootstrap的一個好理由。但同時,這是理解Bootstrap在現代Web中的能力和角色的好方式:要麼使用它,要麼你使用某個能做它所做的東西,只不過外觀不同。

使用Bootstrap,你會體驗到一個相對短的學習曲線,有很多模板(Bootstrap的變體)是免費的,還有很多隻需要一筆很小的費用。如果你是一名Web設計師或者打算僱傭一名Web設計師,應該要求最終的模板是基於Bootstrap的。

本章概覽了Bootstrap,涵蓋了它的主要特性和組件。我試著讓大家看看真實的Bootstrap及其在真實網站的使用。但我不確定是否涵蓋它的所有重要方面。我鼓勵大家直接從Bootstrap的文檔瞭解更多的組件、特性、樣式和擴展。

最後有一點要記住的,Bootstrap預示著一個響應式Web設計的時代,這個設計方法學旨在向用戶提供理想的體驗,不管屏幕大小如何。響應式Web設計肯定是個好主意,它的好在於讓Boostrap模板適用於任何類型的移動設備。但是,就像Bootstrap未能免除對更好圖形內容的需求,它也不能免除有時候要通過專門的移動網站以特定方式應對某些設備(尤其是智能手機和更老的手機)的需要。我將在第15章回到這一點。

本文截選自《全棧工程師Web開發指南》第九章部分內容。

全棧工程師Web開發指南:Bootstrap的精髓

作者:[意]迪諾·埃斯波西託(Dino Esposito)

譯者:李永倫

本書通過介紹一種實用的、問題驅動的,關注用戶的方法,介紹了規劃、設計和構建動態的Web強有力的方法,給出了目前進行Web開發的一套有效解決方案。本書引導讀者選擇和實現特定的技術,闡釋了重要的用戶體驗主題,並探討了對移動友好的技術和反應式設計技術等內容。除此之外,本書還介紹了ASP.NET MVC、SignalR、Bootstrap、AJAX、JSON和JQuery等技術的相關內容。

通過閱讀本書,讀者將學到如何從DDD方法以及現代的UX設計方法中獲益,進而能夠快速構建出解決當前問題並且有出色用戶體驗的Web解決方案。

"

相關推薦

推薦中...