LESS 是一個流行的樣式表語言,它提供了 CSS3 也不曾實現的多種功能,讓您編寫 CSS 更加方便,更加直觀。LESS 已經被普遍使用在多種框架中 ( 例如:BootStrap)。本文將介紹 LESS 產生的背景、優點、演化與 CSS 之間的轉化,及其典型的應用場景,並將其與其餘樣式表語言進行比較。相信前端開發工程師會喜歡 LESS,靈活運用 LESS 以提升開發效率。javascript
LESS 提供了多種方式能平滑的將寫好的代碼轉化成標準 CSS 代碼,在不少流行的框架和工具盒中已經能常常看到 LESS 的身影了(例如 Twitter 提供的 bootstrap 庫就使用了 LESS)。那麼,LESS 是從何而來呢?它和 SASS 等樣式表語言又有何區別呢?css
根 據維基百科上的介紹,其實 LESS 是 Alexis Sellier 受 SASS 的影響建立的開源項目。當時 SASS 採用了縮進做爲分隔符來區分代碼塊,而不是 CSS 中廣爲使用的括號。爲了讓 CSS 現有用戶使用起來更爲方便,Alexis 開發了 LESS 並提供了相似的功能。在一開始,LESS 的解釋器也一樣是由 Ruby 編寫,後來才轉而採用了 JavaScript. LESS 代碼既能夠運行在客戶端,也能夠運行在服務器端。在客戶端只要把 LESS 代碼和相應的 JavaScript 解釋器在同一頁面引用便可;而在服務器端,LESS 能夠運行在 Node.js 上,也能夠運行在 Rhino 這樣的 JavaScript 引擎上。html
說一點題外話,其實如今的 SASS 已經有了兩套語法規則:一個依舊是用縮進做爲分隔符來區分代碼塊的;另外一套規則和 CSS 同樣採用了大括弧做爲風格符。後一種語法規則又名 SCSS,在 SASS 3 以後的版本都支持這種語法規則。SCSS 和 LESS 已經愈來愈像了,它倆之間更詳細的對比能夠參考 此連接。前端
我 們知道 LESS 擁有四大特性:變量、混入、嵌套、函數。這些特性在其餘文章中已經有所介紹,這裏就不復述了。其實,LESS 還擁有一些頗有趣的特性有助於咱們的開發,例如模式匹配、條件表達式、命名空間和做用域,以及 JavaScript 賦值等等。讓咱們來逐一看看這些特性吧。java
相信你們對 LESS 四大特性中的混入 (mixin) 依然印象深入吧,您用它可以定義一堆屬性,而後輕鬆的在多個樣式集中重用。甚至在定義混入時加入參數使得這些屬性根據調用的參數不一樣而生成不一樣的屬性。那 麼,讓咱們更進一步,來了解一下 LESS 對混入的更高級支持:模式匹配和條件表達式。node
首先,讓咱們來回顧一下普通的帶參數的混入方式:git
.border-radius (@radius: 3px) { border-radius: @radius; -moz-border-radius: @radius; -webkit-border-radius: @radius; } .button { .border-radius(6px); } .button2 { .border-radius(); }
.button { border-radius: 6px; -moz-border-radius: 6px; -webkit-border-radius: 6px; } .button2 { border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; }
從上面這個例子能夠看出,在混入咱們能夠定義參數,同時也能夠爲這個參數指定一個缺省值。這樣咱們在調用這個混入時若是指定了參數 .border-radius(6px)
,LESS 就會用 6px
來替換,若是不指定參數來調用 .border-radius()
,LESS 就會用缺省的 3px
來替換。如今,咱們更近一步,不只僅經過參數值來更改最終結果,而是經過傳入不一樣的參數個數來匹配不一樣的混入。github
Html代碼 web
.mixin (@a) { color: @a; width: 10px; } .mixin (@a, @b) { color: fade(@a, @b); } .header{ .mixin(red); } .footer{ .mixin(blue, 50%); }
.header { color: #ff0000; width: 10px; } .footer { color: rgba(0, 0, 255, 0.5); }
這個例子有些像 Java 語言中的方法調用有些相似,LESS 能夠根據調用參數的個數來選擇正確的混入來帶入。如今,咱們瞭解到經過傳入參數的值,以及傳入不一樣的參數個數可以選擇不一樣的混入及改變它的最終代碼。這兩 個例子的模式匹配都是很是容易理解的,讓咱們換個思路,上面的例子中參數都是由變量構成的,其實在 LESS 中定義參數是能夠用常量的!模式匹配時匹配的方式也會發生相應的變化,讓咱們看個實例。npm
Html代碼
.mixin (dark, @color) { color: darken(@color, 10%); } .mixin (light, @color) { color: lighten(@color, 10%); } .mixin (@zzz, @color) { display: block; weight: @zzz; } .header{ .mixin(dark, red); } .footer{ .mixin(light, blue); } .body{ .mixin(none, blue); }
清單 6. 常量參數生成的 CSS 代碼
Html代碼
最後,咱們把清單 1 中的代碼作略微改動,增長一個無參的混入和一個常量參數的混入,您猜猜看最終的匹配結果會發生什麼變化麼?
Html代碼
.border-radius (@radius: 3px) { border-radius: @radius; -moz-border-radius: @radius; -webkit-border-radius: @radius; } .border-radius (7px) { border-radius: 7px; -moz-border-radius: 7px; } .border-radius () { border-radius: 4px; -moz-border-radius: 4px; -webkit-border-radius: 4px; } .button { .border-radius(6px); } .button2 { .border-radius(7px); } .button3{ .border-radius(); }
下面的結果可能會出乎您的意料,無參的混入是可以匹配任何調用,而常量參數很是嚴格,必須保證參數的值 (7px)
和調用的值 (7px)
一致纔會匹配。
.button { border-radius: 6px; -moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 4px; -moz-border-radius: 4px; -webkit-border-radius: 4px; } .button2 { border-radius: 7px; -moz-border-radius: 7px; -webkit-border-radius: 7px; border-radius: 7px; -moz-border-radius: 7px; border-radius: 4px; -moz-border-radius: 4px; -webkit-border-radius: 4px; } .button3 { border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 4px; -moz-border-radius: 4px; -webkit-border-radius: 4px; }
有了模式匹配以後是方便了不少,咱們能根據不一樣的需求來匹配不一樣的混入,但更進一步的就是利用條件表達式來更加準確,更加嚴格的來限制混入的匹配,實現的方式就是利用了 when
這個關鍵詞。
Html代碼
.mixin (@a) when (@a >= 10) { black; } .mixin (@a) when (@a < 10) { white; } .class1 { .mixin(12) } .class2 { .mixin(6) }
Html代碼
.class1 { black; } .class2 { white; }
利用 When 以及 <, >, =, <=, >= 是十分簡單和方便的。LESS 並無停留在這裏,並且提供了不少類型檢查函數來輔助條件表達式,例如 iscolor
、isnumber
、isstring
、iskeyword
、isurl
等等。
Html代碼
.mixin (@a) when (iscolor(@a)) { black; } .mixin (@a) when (isnumber(@a)) { white; } .class1 { .mixin(red) } .class2 { .mixin(6) }
Html代碼
.class1 { black; } .class2 { white; }
另外,LESS 的條件表達式一樣支持 AND 和 OR 以及 NOT 來組合條件表達式,這樣能夠組織成更爲強大的條件表達式。須要特別指出的一點是,OR 在 LESS 中並非用 or 關鍵字,而是用 , 來表示 or 的邏輯關係。
Html代碼
.smaller (@a, @b) when (@a > @b) { black; } .math (@a) when (@a > 10) and (@a < 20) { red; } .math (@a) when (@a < 10),(@a > 20) { blue; } .math (@a) when not (@a = 10) { yellow; } .math (@a) when (@a = 10) { green; } .testSmall {.smaller(30, 10) } .testMath1 {.math(15)} .testMath2 {.math(7)} .testMath3 {.math(10)}
Html代碼
.testSmall { black; } .testMath1 { red; yellow; } .testMath2 { blue; yellow; } .testMath3 { green; }
LESS 所帶來的變量,混入這些特性其實很大程度上避免了傳統 CSS 中的大量代碼重複。變量可以避免一個屬性屢次重複,混入可以避免屬性集的重複。並且使用起來更加靈活,維護起來也方便了許多,只要修改一處定義而無需修改 多處引用的地方。如今,讓咱們更進一步,當我定義好了變量和混入以後,怎麼能更好的控制和運用它們呢,怎麼避免和其餘地方定義的變量及混入衝突?一個顯而 易見的想法就是像其餘語言同樣引入命名空間和做用域了。首先咱們來看一個 LESS 的做用域的例子。
Html代碼
@var: red; #page { @var: white; #header { color: @var; } } #footer { color: @var; }
在這個例子裏,能夠看到 header 中的 @var
會首先在當前做用域尋找,而後再逐層往父做用域中尋找,一直到頂層的全局做用域中爲止。因此 header 的 @var
在父做用域中找到以後就中止了尋找,最終的值爲 white。而 footer 中的 @var
在當前做用域沒找到定義以後就尋找到了全局做用域,最終的結果就是全局做用域中的定義值 red。
Html代碼
#page #header { color: #ffffff; // white } #footer { color: #ff0000; // red }
瞭解了做用域以後讓咱們再來看一下命名空間,咱們能夠用命名空間把變量和混入封裝起來,避免和其餘地方的定義衝突,引用起來也十分方便,只要在前面加上相應的命名空間就能夠了。
@var-color: white; #bundle { @var-color: black; .button () { display: block; border: 1px solid black; @var-color; } .tab() { color: red } .citation() { color: black} .oops {weight: 10px} } #header { color: @var-color; #bundle > .button; #bundle > .oops; }
這裏能夠看出,咱們利用嵌套規則在 #bundle
中創建了一個命名空間,在裏面封裝的變量以及屬性集合都不會暴露到外部空間中,例如 .tab(), .citation()
都沒有暴露在最終的 CSS 代碼中。而值得注意的一點是 .oops 卻被暴露在了最終的 CSS 代碼中,這種結果可能並非咱們想要的。其實一樣的例子咱們能夠在混入的例子中也能夠發現,即無參的混入 .tab()
是和普通的屬性集 .oops
不一樣的。無參的混入是不會暴露在最終的 CSS 代碼中,而普通的屬性集則會如今出來。咱們在定義命名空間和混入時要當心處理這樣的差異,避免帶來潛在的問題。
#bundle .oops { weight: 10px; } #header { color: #ffffff; display: block; border: 1px solid black; #000000; weight: 10px; }
如 果能在 CSS 中使用一些 JavaScript 方法無疑是十分使人興奮的,而 LESS 真正逐步加入這項功能,目前已經能使用字符串及數字的經常使用函數了,想要在 LESS 中運用 JavaScript 賦值只須要用反引號(`)來包含所要進行的操做便可。讓咱們看看實例吧。
.eval { js: `1 + 1`; js: `(1 + 1 == 2 ? true : false)`; js: `"hello".toUpperCase() + '!'`; title: `process.title`; } .scope { @foo: 42; var: `this.foo.toJS()`; } .escape-interpol { @world: "world"; width: ~`"hello" + " " + @{world}`; } .arrays { @ary: 1, 2, 3; @ary2: 1 2 3; ary: `@{ary}.join(', ')`; ary: `@{ary2}.join(', ')`; }
咱們能夠看到,在 eval 中咱們能夠用 JavaScript 作數字運算,布爾表達式;對字符串作大小寫轉化,串聯字符串等操做。甚至最後可以獲取到 JavaScript 的運行環境(process.title
)。一樣能夠看到 LESS 的做用域和變量也一樣在 JavaScript 賦值中使用。而最後的例子中,咱們看到 JavaScript 賦值一樣運用於數組操做當中。其實 LESS 的 JavaScript 賦值還有支持其餘一些方式,不過目前還沒有公佈出來。
.eval { js: 2; js: true; js: "HELLO!"; title: "/Users/Admin/Downloads/LESS/Less.app/Contents/Resources/engines/bin/node"; } .scope { var: 42; } .escape-interpol { width: hello world; } .arrays { ary: "1, 2, 3"; ary: "1, 2, 3"; }
在 LESS 開發中,咱們能夠用 LESS 提供的 JavaScript 腳原本在運行時解析,將 LESS 文件實時翻譯成對應的 CSS 語法。以下面這個例子:
<link rel="stylesheet/less" type="text/css" href="helloworld.less">
<script src="less.js" type="text/javascript"></script>
<div class="helloworld">Hello World!</div>
從上 面的示例能夠看出,在 helloworld.less 引入以後咱們還添加了一個 JavaScript 文件,這個文件就是 LESS 的解釋器,能夠在 LESS 的官方網站上下載此文件。須要注意的是,要注意 LESS 文件和 LESS 解釋器的引入順序,確保全部的 LESS 文件都在 LESS 解釋器以前。
看到這裏也許有人會說,實時解析的話方便卻是方便,能夠性能上不就有損耗了麼?比起普通 CSS 來講多了一道解釋的手續。也許還有的人對寫好的 LESS 文件不太放心,但願能看到解析以後的 CSS 文件來檢查下是不是本身但願的內容。這兩個問題其實都是可以解決的,LESS 提供了服務端的方案,使用 npm 安裝 LESS 以後就可以將您全部的 LESS 文件批量轉化成 CSS 文件,而後您拿到 CSS 文件就能夠爲所欲爲了,檢查生成的內容是否有誤,也能夠直接在 HTML 中引用,不再用添加 LESS 的 JavaScript 文件來解析它了。關於這部分的詳細安裝信息,能夠直接參考 LESS 官網上的介紹,這裏就不復述了。
不過,對於 Mac 用戶來講還有一個更方便的工具可使用,它就是 less.app. 這是一個第三方提供的工具,使用起來十分方便,咱們能夠在下圖所示的界面上添加 LESS 文件所在的目錄,此工具就會在右側列出目錄中包含的全部 LESS 文件。最酷的是,今後您就不用再操心惦記着要把 LESS 文件編譯成 CSS 文件了,這個工具會在您每次修改完保存 LESS 文件時本身執行編譯,自動生成 CSS 文件。這樣,您就能夠隨時查看 LESS 代碼的最終效果,檢查目標 CSS 是否符合您的須要了,實在是太方便了!
更值爲稱道的是,LESS.app 仍是個免費軟件,接受捐贈:)
經過上面的簡單介紹,但願你們瞭解到了 LESS 的主要功能,相信 LESS 會讓前端攻城師的工做更爲輕鬆,更加靈活。更多的細節能夠參考 LESS 官方網站。
原文:http://www.ibm.com/developerworks/cn/web/1207_shenyi_lesscss/