CSS 徹底改變了 Web 頁面的設計,但 CSS 仍然是靜態的,而且在其句法發展方面受到限制。這些限制是有目的且合乎情理的,鼓勵廣泛加以實現。但開發人員和設計人員常常發現 CSS 使用起來很單調乏味。許多 Web 框架包含一些工具,這些工具使得人們更容易使用更靈活的特性創作 CSS,然後將結果編譯成靜態 CSS,以便部署到站點。最近的一些專案更側重於建立旨在編譯到 CSS 中的語言。Alexis Sellier 的開源專案 LESS 是這類語言中最受歡迎的一種語言。
LESS 在現有 CSS 語法之上新增了一些開發人員熟悉的特性,比如變數、mixins、運算子和函式。可以使瀏覽器中的 JavaScript 或通過伺服器端 JavaScript 工具集的預處理將 LESS 編譯到 CSS 中。LESS 在其他各種工具集中也得到了廣泛應用,包括 JavaScript 的流行 Bootstrap 專案。在本文中,我要介紹的是 LESS(尤其是 1.4 版本),LESS 是為現代網站編寫可讀性的、可維護的 CSS 的一種方式。參見 下載部分,獲取本文的示例程式碼。
入門
下載最新版 LESS(撰寫本文之時是 1.4;參見 參考資料)。然後準備學習其語言。全球資訊網聯盟 (W3C) 在其維基中提供了一些用於學習 CSS 的資料。我基本上遵循該教程的順序,因此,如有需要的話,您可以一前一後學習基本的 CSS 和 LESS。
清單 1 再現了 W3C 教程的第一個示例:
清單 1. 基本 CSS 示例 (listing1.css)
1 2 3 4 5 |
p { color: red; font-size: 12px; background-color: green; } |
清單 2 中的 HTML 將 清單 1 中的 CSS 投入使用:
清單 2. 引用清單 1 的基本 CSS 示例的 HTML (listing2.html)
1 2 3 4 5 6 |
<head> <link rel="stylesheet" type="text/css" href="listing1.css"> </head> <body> <p>This is a paragraph</p> </body> |
圖 1 顯示了 Mac OS X 上 Safari 瀏覽器中顯示的 listing2.html:
圖 1. 使用清單 1 中的 CSS 的瀏覽器輸出
刪除魔法值
看到 清單 1 的開發人員很可能立刻注意到那些違反開發者本能的內容,即硬編碼到 CSS 中的值,這些值有時被揶揄為 “魔法值 (magic value)”。LESS 中最重要的特性之一是變數。清單 3 是使用變數的一個 LESS 基本示例版本:
清單 3. 使用 LESS 中的變數的基本 CSS 示例 (listing3.css)
1 2 3 4 5 6 7 8 9 |
@main-text-color: red; @main-text-size: 12px; @main-text-bg: green; p { color: @main-text-color; font-size: @main-text-size; background-color: @main-text-bg; } |
清單 3 不是語法正確的 CSS,因此您不能在 HTML 中將 listing1.css
替換為 listing3.less
。您還必須更新主機 HTML 來呼叫 JavaScript 編譯器,如清單 4 所示:
清單 4. 引用基本 CSS 示例 LESS 版本的 HTML (listing4.html)
1 2 3 4 5 6 7 |
<head> <link rel="stylesheet/less" type="text/css" href="listing3.less"> </head> <body> <p>This is a paragraph</p> <script src="less.js" type="text/javascript"></script> </body> |
請注意,在 清單 4 中,我將 script
標記放在頁面 body
的結尾處。傳統上,大多數開發人員將 script
標記放在 head
中。但將它們放在 body
中是合法的,這利用了這樣一個事實(引用自 HTML 4 規範),即 “script
元素按照載入文件的順序進行求值”。如今許多站點在臨近結束時都有一些指令碼,因此主要內容的載入不會因為任何指令碼處理而延遲。
伺服器端編譯
到目前為止,我已經向您展示:開發和部署 LESS 便於快速使用瀏覽器,但卻是有代價的。每次頁面載入時,編譯用的 JavaScript 都執行於使用者的瀏覽器之上,這耗盡了計算資源並減緩了頁面載入。如果在瀏覽器中載入 清單 4 ,並檢查 JavaScript 控制檯,則會看到一條訊息:“less: css generated in 36ms”。36 毫秒的時間並不算長,但它代表著額外的不必要計算和時間。快速頁面載入在 Web 上很重要。
在轉入生產模式之後,使用一個伺服器端 JavaScript 工具將 LESS 編譯到 CSS 中。Node.js 是一個流行選項,被記錄在 LESS 站點上。我喜歡使用 Mozilla 的獨立 JavaScript 專案 Rhino。要使用 Rhino 和 LESS,請下載並安裝 Rhino(參見 參考資料)。將 js.jar 放在一個方便進行構建的位置。您需要一個特殊版本的 less.js,該版本可在 GitHub 完整下載的 LESS 中下載中找到(參見 參考資料)。本文中使用的版本是 less.js-master/dist/less-rhino-1.4.0.js。將 less-rhino-1.4.0.js 放在儲存 Rhino JAR 的地方。下面準備將 LESS 程式碼編譯到 CSS 中。
要編譯 listing3.less,請切換到 listing3.less 所在的目錄並執行以下命令:
1 |
java -jar js.jar less-rhino-1.4.0.js listing3.less > listing3.css |
編譯操作會將生成的 CSS 放在 listing3.css 檔案中。該檔案的內容如下:
1 2 3 4 5 |
p { color: #ff0000; font-size: 12px; background-color: #008000; } |
在 listing3.css 中,LESS 變數被替換,顏色名稱被替換為 RGB 形式(比如 red
被替換為 #ff0000
)。現在您可以按照常用方法將 listing3.css 部署到一臺伺服器中。
LESS 替代註釋語法
LESS 的一個小小的增強是,編寫單行註釋的方式變得簡單了。清單 5 顯示了來自 W3C CSS 教程的一個標準註釋示例:
清單 5. 使用註釋的 CSS 示例 (listing 5.css)
1 2 3 4 5 |
p { color: red; /* This is a comment */ font-size: 12px; } |
清單 6 中的 LESS 程式碼等同於 清單 5 :
清單 6. 與使用簡化註釋的清單 5 等同的 LESS 程式碼 (listing6.less)
1 2 3 4 5 |
p { color: red; // This is a comment font-size: 12px; } |
清單 6 使用的語法對於程式設計師來說很常見,而且鍵入起來稍微容易一些。但鑑於處理 LESS 的方式,這種註釋並不出現在生成的 CSS 中。如果您想為瀏覽器檢視器保留註釋(例如用於版權宣告),則必須使用標準的 CSS 註釋語法。
W3C 教程其餘內容專注於 CSS 選擇器語法和常見屬性的細節。此時,我要將重心轉向 LESS 的更廣泛使用,這是大多數 Web 開發人員在實踐過程中越來越多遇見的情形。
建立響應式設計
在 2010 年,許多 Web 設計人員開始倡導一種稱為 響應式設計 的頁面設計方法。從一開始,就需要構建靈活的 Web 頁面,在從小型手機到比常用桌上型電腦更大的顯示裝置中檢視它們。
響應式設計的核心是 CSS3 媒體查詢,該查詢是一種根據使用者顯示器的性質(特別是尺寸)來呼叫 CSS 規則的標準方式。LESS 使我們能夠更容易地展現使用媒體查詢來實現響應式設計的 CSS。出於演示之目的,我將 developerWorks 博主 Bob Leah 的優秀響應式設計 示例 的一個 LESS 版本組合起來。在文章的程式碼包(參見 下載)中,它是 responsive.less。
運算子
responsive.less 中的一項關鍵技術是使用變數設定基本的方框大小,然後根據可視區的大小調整方框。我使用 LESS 運算子來進行縮放。例如,清單 7 中的程式碼段使用乘法運算子來縮放橫幅影像:
清單 7. LESS 中乘法的使用
1 2 3 4 |
#banner img { max-width: (@bannerwidth * @scale); max-height: (@mainheight * @scale); } |
在 清單 7 中,@bannerwidth
和 @mainheight
是根據 @scale
因子縮減的預設值。最新的 LESS 版本要求您將包含運算子的所有表示式放在圓括號中,以避免語法混淆。
巢狀規則
LESS 最有用的功能之一是巢狀 CSS 規則。巢狀規則有助於您以簡單易懂的方式組織程式碼。在清單 8(responsive.less 中的一段經過修改的摘錄片段)中,我在媒體查詢內巢狀了通用的 CSS 規則:
清單 8. LESS 中巢狀規則的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@media (min-width: 401px) and (max-width: 800px) { @scale: 0.75 #banner { width: (@bannerwidth * @scale); } #banner img { max-width: (@bannerwidth * @scale); max-height: (@mainheight * @scale); } #main { width: (@mainwidth * @scale - @extrabuffer); } #main-content { width: (@maincontentwidth * @scale * 0.75 - @extrabuffer); float: left; } } |
清單 8 中的巢狀規則等同於清單 9 中多個獨立的 CSS 規則:
清單 9. 等同於清單 8,但無巢狀規則
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
@scale: 0.75 @media (min-width: 401px) and (max-width: 800px) and #banner { width: (@bannerwidth * @scale); } @media (min-width: 401px) and (max-width: 800px) and #banner img { { max-width: (@bannerwidth * @scale); max-height: (@mainheight * @scale); } @media (min-width: 401px) and (max-width: 800px) and #main { width: (@mainwidth * @scale - @extrabuffer); } @media (min-width: 401px) and (max-width: 800px) and #main-content { width: (@maincontentwidth * @scale * 0.75 - @extrabuffer); float: left; } |
清單 9 中的版本沒有提供這些密切相關規則的自然分組,而且還因為反覆指定媒體查詢而違反了 DRY(不要重複自己)原則。
mixins
LESS 減少重複的另一種方式是讓您指定可新增到其他規則中的一組規則。在 responsive.less 中,我使用了此 mixin 技術來跨兩個不同的媒體查詢表達常見規則,如清單 10 所示:
清單 10. LESS 中 mixins 的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
.media-body (@scale: 0.75) { #banner { width: (@bannerwidth * @scale); } #banner img { max-width: (@bannerwidth * @scale); max-height: (@mainheight * @scale); } #main { width: (@mainwidth * @scale - @extrabuffer); } #main-content { width: (@maincontentwidth * @scale * 0.75 - @extrabuffer); float: left; } #widget-container { width: (@widgetoutwidth * @scale * 0.75 - @extrabuffer); float: right; } .widget-content { width: (@widgetinwidth * @scale * 0.75 - @extrabuffer); } } //Rules for viewing from 401px to 800px @media (min-width: 401px) and (max-width: 800px) { .media-body; } //Rules for viewing smaller than 400px @media (max-width: 400px) { .media-body(0.3); //Extra manipulation of some rules #main-content { padding: 0px; } #widget-container { width: padding: 0px; } .widget-content { margin: 5px; } .widget-text { display: none; } } |
Mixins 可以接受引數,比如 清單 10 中方框大小的比例因子。預設的比例因子是 0.75
。清單 10 在可視區中使用從 401px 到 800px 的預設大小。為了在小於 400px 的尺寸下進行檢視,比例因子被更改為 0.3
,並且在該區域新增了一些額外規則。
圖 2 顯示了 responsive.html 的瀏覽器顯示,它使用了 responsive.less。我減小了瀏覽器的寬度,以滿足小於 400px 的寬度的媒體查詢,這樣一來您就可以看到頁面在小型移動裝置上是什麼樣子。
圖 2. responsive.html 的低寬度瀏覽器輸出
在我 Mac 上的 Safari 中,當瀏覽器寬度接近 500px 時,小於 400px 的寬度的媒體查詢被觸發。該行為引出了一個重要觀點。媒體查詢基於視區 這一概念。視區是可視瀏覽器空間的數量,用 CSS 畫素進行定義,並通過裝置和瀏覽器進行確定。CSS 畫素不同於裝置畫素;例如,如果使用者縮放瀏覽器檢視,那麼畫素模型之間的關係就會發生變化(參見 參考資料)。此外,裝置和瀏覽器設定的視區大小不同於實際顯示的視窗大小。在 圖 2 中就是如此:視窗大約是 500px,但 CSS 將其作為 400px 寬的視區加以處理。這一現象強調了這樣一個事實:與所有 Web 開發技術一樣,響應式設計需要完善的跨裝置測試。
結束語
我是一名軟體架構師兼開發人員,但絕不是一名 Web 設計人員。憑藉 LESS,我可以利用我的程式設計技能快速開發更便於理解和維護的 CSS。變數和 mixins 使我能夠快速做出調整,檢視其效果,無需在整個 CSS 檔案內四處移動,查詢我需要進行相關更改的內容。
響應式設計是經濟適用的可管理移動 Web 設計中的一項公認的關鍵技術。它在針對列印等可訪問性和其他演示模式的設計中也很有用。由於為應對媒體查詢而應用的多種樣式處理起來很繁瑣,所以 LESS 簡化和組織 CSS 程式碼的功能愈發有價值。