?
LESS 是一個流行的樣式表語言,它提供了 CSS3 也未曾實(shí)現(xiàn)的多種功能,讓您編寫 CSS 更加方便,更加直觀。LESS 已經(jīng)被廣泛使用在多種框架中 ( 例如:BootStrap)。本文將介紹 LESS 產(chǎn)生的背景、優(yōu)勢、演化與 CSS 之間的轉(zhuǎn)化,及其典型的應(yīng)用場景,并將其與其他樣式表語言進(jìn)行比較。相信前端開發(fā)工程師會喜歡 LESS,靈活運(yùn)用 LESS 以提高開發(fā)效率。
?
LESS 背景介紹
LESS 提供了多種方式能平滑的將寫好的代碼轉(zhuǎn)化成標(biāo)準(zhǔn) CSS 代碼,在很多流行的框架和工具盒中已經(jīng)能經(jīng)??吹?LESS 的身影了(例如 Twitter 提供的 bootstrap 庫就使用了 LESS)。那么,LESS 是從何而來呢?它和 SASS 等樣式表語言又有何區(qū)別呢?
?
圖 1.LESS 的官網(wǎng)介紹
根 據(jù)維基百科上的介紹,其實(shí) LESS 是 Alexis Sellier 受 SASS 的影響創(chuàng)建的開源項(xiàng)目。當(dāng)時 SASS 采用了縮進(jìn)作為分隔符來區(qū)分代碼塊,而不是 CSS 中廣為使用的括號。為了讓 CSS 現(xiàn)有用戶使用起來更為方便,Alexis 開發(fā)了 LESS 并提供了類似的功能。在一開始,LESS 的解釋器也同樣是由 Ruby 編寫,后來才轉(zhuǎn)而采用了 JavaScript. LESS 代碼既可以運(yùn)行在客戶端,也可以運(yùn)行在服務(wù)器端。在客戶端只要把 LESS 代碼和相應(yīng)的 JavaScript 解釋器在同一頁面引用即可;而在服務(wù)器端,LESS 可以運(yùn)行在 Node.js 上,也可以運(yùn)行在 Rhino 這樣的 JavaScript 引擎上。
?
說一點(diǎn)題外話,其實(shí)現(xiàn)在的 SASS 已經(jīng)有了兩套語法規(guī)則:一個依舊是用縮進(jìn)作為分隔符來區(qū)分代碼塊的;另一套規(guī)則和 CSS 一樣采用了大括弧作為風(fēng)格符。后一種語法規(guī)則又名 SCSS,在 SASS 3 之后的版本都支持這種語法規(guī)則。SCSS 和 LESS 已經(jīng)越來越像了,它倆之間更詳細(xì)的對比可以參考 此鏈接 。
?
LESS 高級特性
我 們知道 LESS 擁有四大特性:變量、混入、嵌套、函數(shù)。這些特性在其他文章中已經(jīng)有所介紹,這里就不復(fù)述了。其實(shí),LESS 還擁有一些很有趣的特性有助于我們的開發(fā),例如模式匹配、條件表達(dá)式、命名空間和作用域,以及 JavaScript 賦值等等。讓我們來逐一看看這些特性吧。
?
模式匹配:
相信大家對 LESS 四大特性中的混入 (mixin) 依然印象深刻吧,您用它能夠定義一堆屬性,然后輕松的在多個樣式集中重用。甚至在定義混入時加入?yún)?shù)使得這些屬性根據(jù)調(diào)用的參數(shù)不同而生成不同的屬性。那 么,讓我們更進(jìn)一步,來了解一下 LESS 對混入的更高級支持:模式匹配和條件表達(dá)式。
首先,讓我們來回顧一下普通的帶參數(shù)的混入方式:
?
清單 1. 帶參數(shù)(及參數(shù)缺省值)的混入
?
.border-radius (@radius: 3px) { border-radius: @radius; -moz-border-radius: @radius; -webkit-border-radius: @radius; } .button { .border-radius(6px); } .button2 { .border-radius(); }
?
?
清單 2. 混入生成的 CSS 代碼
?
.button { border-radius: 6px; -moz-border-radius: 6px; -webkit-border-radius: 6px; } .button2 { border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; }?
?
從上面這個例子可以看出,在混入我們可以定義參數(shù),同時也可以為這個參數(shù)指定一個缺省值。這樣我們在調(diào)用這個混入時如果指定了參數(shù)
.border-radius(6px)
,LESS 就會用
6px
來替換,如果不指定參數(shù)來調(diào)用
.border-radius()
,LESS 就會用缺省的
3px
來替換?,F(xiàn)在,我們更近一步,不僅僅通過參數(shù)值來更改最終結(jié)果,而是通過傳入不同的參數(shù)個數(shù)來匹配不同的混入。
?
清單 3. 利用不同的參數(shù)個數(shù)來匹配不同的混入
?
.mixin (@a) { color: @a; width: 10px; } .mixin (@a, @b) { color: fade(@a, @b); } .header{ .mixin(red); } .footer{ .mixin(blue, 50%); }
?
?
清單 4. 不同參數(shù)個數(shù)調(diào)用后生成的 CSS 代碼
?
.header { color: #ff0000; width: 10px; } .footer { color: rgba(0, 0, 255, 0.5); }?
?
這個例子有些像 Java 語言中的方法調(diào)用有些類似,LESS 可以根據(jù)調(diào)用參數(shù)的個數(shù)來選擇正確的混入來帶入。現(xiàn)在,我們了解到通過傳入?yún)?shù)的值,以及傳入不同的參數(shù)個數(shù)能夠選擇不同的混入及改變它的最終代碼。這兩 個例子的模式匹配都是非常容易理解的,讓我們換個思路,上面的例子中參數(shù)都是由變量構(gòu)成的,其實(shí)在 LESS 中定義參數(shù)是可以用常量的!模式匹配時匹配的方式也會發(fā)生相應(yīng)的變化,讓我們看個實(shí)例。
?
清單 5. 用常量參數(shù)來控制混入的模式匹配
?
.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. 常量參數(shù)生成的 CSS 代碼
?
.header { color: #cc0000; display: block; weight: dark; } .footer { color: #3333ff; display: block; weight: light; } .body { display: block; weight: none; }?
?
通過這個例子我們可以看出,當(dāng)我們定義的是變量參數(shù)時,因?yàn)?LESS 中對變量并沒有類型的概念,所以它只會根據(jù)參數(shù)的個數(shù)來選擇相應(yīng)的混入來替換。而定義常量參數(shù)就不同了,這時候不僅參數(shù)的個數(shù)要對應(yīng)的上,而且常量參數(shù)的 值和調(diào)用時的值也要一樣才會匹配的上。值得注意的是我們在 body 中的調(diào)用,它調(diào)用時指定的第一個參數(shù) none 并不能匹配上前兩個混入,而第三個混入
.mixin (@zzz, @color)
就不同了,由于它的兩個參數(shù)都是變量,所以它接受任何值,因此它對三個調(diào)用都能匹配成功,因此我們在最終的 CSS 代碼中看到每次調(diào)用的結(jié)果中都包含了第三個混入的屬性。
?
最后,我們把清單 1 中的代碼做略微改動,增加一個無參的混入和一個常量參數(shù)的混入,您猜猜看最終的匹配結(jié)果會發(fā)生什么變化么?
?
清單 7. 無參和常量參數(shù)的模式匹配
?
.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(); }?
?
下面的結(jié)果可能會出乎您的意料,無參的混入是能夠匹配任何調(diào)用,而常量參數(shù)非常嚴(yán)格,必須保證參數(shù)的值
(7px)
和調(diào)用的值
(7px)
一致才會匹配。
?
清單 8. 加入了無參混入后生成的 CSS 代碼
?
.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; }
?
?
條件表達(dá)式
有了模式匹配之后是方便了很多,我們能根據(jù)不同的需求來匹配不同的混入,但更進(jìn)一步的就是利用條件表達(dá)式來更加準(zhǔn)確,更加嚴(yán)格的來限制混入的匹配,實(shí)現(xiàn)的方式就是利用了
when
這個關(guān)鍵詞。
?
清單 9. 利用條件表達(dá)式來控制模式匹配
?
.mixin (@a) when (@a >= 10) { background-color: black; } .mixin (@a) when (@a < 10) { background-color: white; } .class1 { .mixin(12) } .class2 { .mixin(6) }
?
?
清單 10. 條件表達(dá)式生成的 CSS 代碼
?
.class1 { background-color: black; } .class2 { background-color: white; }
?
?
利用 When 以及 <, >, =, <=, >= 是十分簡單和方便的。LESS 并沒有停留在這里,而且提供了很多類型檢查函數(shù)來輔助條件表達(dá)式,例如
iscolor
、
isnumber
、
isstring
、
iskeyword
、
isurl
等等。
?
清單 11. 條件表達(dá)式中支持的類型檢查函數(shù)
?
.mixin (@a) when (iscolor(@a)) { background-color: black; } .mixin (@a) when (isnumber(@a)) { background-color: white; } .class1 { .mixin(red) } .class2 { .mixin(6) }
?
?
清單 12. 類型檢查匹配后生成的 CSS 代碼
?
.class1 { background-color: black; } .class2 { background-color: white; }
?
?
另外,LESS 的條件表達(dá)式同樣支持 AND 和 OR 以及 NOT 來組合條件表達(dá)式,這樣可以組織成更為強(qiáng)大的條件表達(dá)式。需要特別指出的一點(diǎn)是,OR 在 LESS 中并不是用 or 關(guān)鍵字,而是用 , 來表示 or 的邏輯關(guān)系。
?
清單 13. AND,OR,NOT 條件表達(dá)式
?
.smaller (@a, @b) when (@a > @b) { background-color: black; } .math (@a) when (@a > 10) and (@a < 20) { background-color: red; } .math (@a) when (@a < 10),(@a > 20) { background-color: blue; } .math (@a) when not (@a = 10) { background-color: yellow; } .math (@a) when (@a = 10) { background-color: green; } .testSmall {.smaller(30, 10) } .testMath1 {.math(15)} .testMath2 {.math(7)} .testMath3 {.math(10)}
?
?
清單 14. AND,OR,NOT 條件表達(dá)式生成的 CSS 代碼
?
.testSmall { background-color: black; } .testMath1 { background-color: red; background-color: yellow; } .testMath2 { background-color: blue; background-color: yellow; } .testMath3 { background-color: green; }
?
?
命名空間和作用域
LESS 所帶來的變量,混入這些特性其實(shí)很大程度上避免了傳統(tǒng) CSS 中的大量代碼重復(fù)。變量能夠避免一個屬性多次重復(fù),混入能夠避免屬性集的重復(fù)。而且使用起來更加靈活,維護(hù)起來也方便了許多,只要修改一處定義而無需修改 多處引用的地方。現(xiàn)在,讓我們更進(jìn)一步,當(dāng)我定義好了變量和混入之后,怎么能更好的控制和運(yùn)用它們呢,怎么避免和其他地方定義的變量及混入沖突?一個顯而 易見的想法就是像其他語言一樣引入命名空間和作用域了。首先我們來看一個 LESS 的作用域的例子。
?
清單 15. 變量的作用域
?
@var: red; #page { @var: white; #header { color: @var; } } #footer { color: @var; }?
?
在這個例子里,可以看到 header 中的
@var
會首先在當(dāng)前作用域?qū)ふ?,然后再逐層往父作用域中尋找,一直到頂層的全局作用域中為止。所?header 的
@var
在父作用域中找到之后就停止了尋找,最終的值為 white。而 footer 中的
@var
在當(dāng)前作用域沒找到定義之后就尋找到了全局作用域,最終的結(jié)果就是全局作用域中的定義值 red。
?
清單 16. 變量作用域例子生成的 CSS 代碼
?
#page #header { color: #ffffff; // white } #footer { color: #ff0000; // red }?
?
了解了作用域之后讓我們再來看一下命名空間,我們可以用命名空間把變量和混入封裝起來,避免和其他地方的定義沖突,引用起來也十分方便,只要在前面加上相應(yīng)的命名空間就可以了。
?
清單 17. 命名空間的例子
@var-color: white; #bundle { @var-color: black; .button () { display: block; border: 1px solid black; background-color: @var-color; } .tab() { color: red } .citation() { color: black} .oops {weight: 10px} } #header { color: @var-color; #bundle > .button; #bundle > .oops; }
?
這里可以看出,我們利用嵌套規(guī)則在
#bundle
中建立了一個命名空間,在里面封裝的變量以及屬性集合都不會暴露到外部空間中,例如
.tab(), .citation()
都沒有暴露在最終的 CSS 代碼中。而值得注意的一點(diǎn)是 .oops 卻被暴露在了最終的 CSS 代碼中,這種結(jié)果可能并不是我們想要的。其實(shí)同樣的例子我們可以在混入的例子中也可以發(fā)現(xiàn),即無參的混入
.tab()
是和普通的屬性集
.oops
不同的。無參的混入是不會暴露在最終的 CSS 代碼中,而普通的屬性集則會現(xiàn)在出來。我們在定義命名空間和混入時要小心處理這樣的差別,避免帶來潛在的問題。
?
清單 18. 命名空間例子生成的 CSS 代碼
#bundle .oops { weight: 10px; } #header { color: #ffffff; display: block; border: 1px solid black; background-color: #000000; weight: 10px; }
?
JavaScript 賦值 (JavaScript Evaluation)
如 果能在 CSS 中使用一些 JavaScript 方法無疑是十分令人興奮的,而 LESS 真正逐步加入這項(xiàng)功能,目前已經(jīng)能使用字符串及數(shù)字的常用函數(shù)了,想要在 LESS 中運(yùn)用 JavaScript 賦值只需要用反引號(`)來包含所要進(jìn)行的操作即可。讓我們看看實(shí)例吧。
?
清單 19. 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 做數(shù)字運(yùn)算,布爾表達(dá)式;對字符串做大小寫轉(zhuǎn)化,串聯(lián)字符串等操作。甚至最后能夠獲取到 JavaScript 的運(yùn)行環(huán)境(
process.title
)。同樣可以看到 LESS 的作用域和變量也同樣在 JavaScript 賦值中使用。而最后的例子中,我們看到 JavaScript 賦值同樣運(yùn)用于數(shù)組操作當(dāng)中。其實(shí) LESS 的 JavaScript 賦值還有支持其他一些方式,不過目前尚未公布出來。
?
清單 20. JavaScript 賦值生成的 CSS 代碼
.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 開發(fā)的實(shí)用工具 – LESS.app
在 LESS 開發(fā)中,我們可以用 LESS 提供的 JavaScript 腳本來在運(yùn)行時解析,將 LESS 文件實(shí)時翻譯成對應(yīng)的 CSS 語法。如下面這個例子:
?
清單 21. helloworld.html
<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 的官方網(wǎng)站上下載此文件。需要注意的是,要注意 LESS 文件和 LESS 解釋器的引入順序,確保所有的 LESS 文件都在 LESS 解釋器之前。
?
看到這里也許有人會說,實(shí)時解析的話方便倒是方便,可以性能上不就有損耗了么?比起普通 CSS 來說多了一道解釋的手續(xù)。也許還有的人對寫好的 LESS 文件不太放心,希望能看到解析之后的 CSS 文件來檢查下是否是自己希望的內(nèi)容。這兩個問題其實(shí)都是能夠解決的,LESS 提供了服務(wù)端的方案,使用 npm 安裝 LESS 之后就能夠?qū)⒛械?LESS 文件批量轉(zhuǎn)化成 CSS 文件,然后您拿到 CSS 文件就可以隨心所欲了,檢查生成的內(nèi)容是否有誤,也可以直接在 HTML 中引用,再也不用添加 LESS 的 JavaScript 文件來解析它了。關(guān)于這部分的詳細(xì)安裝信息,可以直接參考 LESS 官網(wǎng)上的介紹,這里就不復(fù)述了。
?
不過,對于 Mac 用戶來說還有一個更方便的工具可以使用,它就是 less.app. 這是一個第三方提供的工具,使用起來十分方便,我們可以在下圖所示的界面上添加 LESS 文件所在的目錄,此工具就會在右側(cè)列出目錄中包含的所有 LESS 文件。最酷的是,從此您就不用再操心惦記著要把 LESS 文件編譯成 CSS 文件了,這個工具會在您每次修改完保存 LESS 文件時自己執(zhí)行編譯,自動生成 CSS 文件。這樣,您就可以隨時查看 LESS 代碼的最終效果,檢查目標(biāo) CSS 是否符合您的需要了,實(shí)在是太方便了!
?
圖 2. 導(dǎo)入 LESS 文件夾的界面,左側(cè)可添加存放在多個不同路徑的文件夾。
?
圖 3. 編譯結(jié)果界面,在此可手動批量編譯所有 LESS 文件。
更值為稱道的是,LESS.app 還是個免費(fèi)軟件,接受捐贈:)
?
總結(jié)
通過上面的簡單介紹,希望大家了解到了 LESS 的主要功能,相信 LESS 會讓前端攻城師的工作更為輕松,更加靈活。更多的細(xì)節(jié)可以參考 LESS 官方網(wǎng)站。
?
參考資料
學(xué)習(xí)
- “ LESS CSS 框架簡介 ”(developerWorks,2012 年 7 月):LESS 是動態(tài)的樣式表語言,通過簡潔明了的語法定義,使編寫 CSS 的工作變得非常簡單。本文將通過實(shí)例,為大家介紹這一框架。
- LESS 官方網(wǎng)站 : 包括官方參考文檔庫,示例代碼等相關(guān)資料。
- 維基百科上的 LESS 條目 包括了 LESS 的歷史,功能介紹,與其他樣式語言的對比等資料。
- LESS.app 官方網(wǎng)站 LESS.app 的官方網(wǎng)站,提供了 LESS.app 的下載,視頻介紹,相關(guān)問題回答等資料。
- twitter 提供的 bootstrap 由 Twitter 共享出的 CSS 工具包,使開發(fā)者能夠輕松的創(chuàng)建出漂亮的界面。其中很多地方都使用了 LESS。
- SASS 官方網(wǎng)站 包含了 SASS 和 SCSS 的下載,幫助文檔,以及在線教程等資料。
- developerWorks Web development 專區(qū) :通過專門關(guān)于 Web 技術(shù)的文章和教程,擴(kuò)展您在網(wǎng)站開發(fā)方面的技能。
- developerWorks Ajax 資源中心 :這是有關(guān) Ajax 編程模型信息的一站式中心,包括很多文檔、教程、論壇、blog、wiki 和新聞。任何 Ajax 的新信息都能在這里找到。
- developerWorks Web 2.0 資源中心 ,這是有關(guān) Web 2.0 相關(guān)信息的一站式中心,包括大量 Web 2.0 技術(shù)文章、教程、下載和相關(guān)技術(shù)資源。您還可以通過 Web 2.0 新手入門 欄目,迅速了解 Web 2.0 的相關(guān)概念。
- 查看 HTML5 專題 ,了解更多和 HTML5 相關(guān)的知識和動向。
討論
- 加入 developerWorks 中文社區(qū) 。查看開發(fā)人員推動的博客、論壇、組和維基,并與其他 developerWorks 用戶交流。
?
原文: http://www.ibm.com/developerworks/cn/web/1207_shenyi_lesscss/
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
