文章出處

一、前言                             

  說到前端構建怎能缺少CSS預處理器呢!其實CSS的預處理器有很多啦,比較出名的有Scss、Sass、Stylus和Less。(最近還聽說出現了Autoprefixer等CSS后處理器,可參考@一絲的PPT)

  眾多CSS預處理器中Less的語法最接近原生CSS,因此相對來說更容易上手,假如有JS、C#等編程經驗的話,其實上述的幾種預處理器的學習成本也不會特別高。下面是我們這陣子的學習筆記,以便日后查閱。

  最好的入門教程——官網地址:http://lesscss.org/

  最佳實踐之一——Bootstrap

  由于內容較多,特設目錄一坨:

  二、搭建學習環境

  三、內聯樣式和外聯樣式

  四、語法

    1. 注釋

    2. 變量(Variable)

        列表類型

    3. 嵌套(Nested)

    4. 父選擇器引用(ParentSelector)

  5. 導入指令(Import)

    6. 繼承(Extend)

   6.1. 父選擇器必須嚴格匹配,除了屬性選擇器中屬性值引號不必匹配外,或添加all關鍵字外。

   6.2. 父選擇器不支持變量形式

   6.3. media query影響繼承的作用域

    6.3.1. media query內的extend操作,僅能繼承當前塊的其他選擇器樣式。

    6.3.2. 非media query內的extend操作,將會繼承所有media query中匹配的選擇器樣式。

   6.4. 增強的mixin定義mixin時僅能使用類選擇器和ID選擇器,而extend操作可對應所有的選擇器,因此當沒有動態入參而又需要類選擇器和ID選擇器以外的選擇器時,可使用extend來實現mixin的功能。

    7. 混合(Mixin)

  7.1. 類選擇器、ID選擇器自動被定義為mixin,而且具有命名空間;

  7.2. 顯示定義不帶參數和帶參數的樣式庫(mixin庫),不會輸出到最終輸出中,僅供調用;

  7.3. mixin的中內置兩個特殊的對象@arguments和@reset。@argumentsk代表mixin的所有入參,而@reset代表mixin的...入參數組。

  7.4. mixin的重載可定義多個同名mixin,調用時只要參數數量匹配則會執行相應的mixin。

    8. 選擇、循環作業控制

  五、運算符

  六、函數

   1. default函數

     2. escape函數

     3. 顏色處理函數

  七、通過Lessc將Less引入開發環境

  八、實戰一下

  九、與Grunt結合  

  十、總結

二、搭建學習環境                          

  搭建Less的學習環境非常簡單,只需在</body>標簽前通過<script type="text/javascript" src="less.js"></script>引入處理器即可實現瀏覽器端中將less預編譯為css樣式。更有效的方式是通過如下代碼監測less樣式,自動編譯為css樣式,從而減少我們修改less代碼后需按F5后才看到實際效果的繁瑣步驟。

<script>less = { env: 'development'};</script>
<script src="less.js"></script>
<script>less.watch();</script>

 

三、內聯樣式和外聯樣式                      

  基于我們現在使用的是瀏覽器端進行預編譯,因此Less可用于內聯樣式和外聯樣式當中。

內聯樣式如下:

<style type="text/less">
  // less 代碼
</style>

外聯樣式引入如下:

<link rel="stylesheet/less" type="text/css" href="文件.less"/>

 

四、語法                              

  1. 注釋

// 單行注釋,不會作為最終輸出
/* 
    多行注釋,以原生CSS的/*注釋....*/形式作為最終輸出
 */

  2. 變量(Variable)

     Less中的變量有以下規則:

  1. 以@作為變量的起始標識,變量名由字母、數字、_和-組成
  2. 沒有先定義后使用的規定;
  3. 以最后定義的值為最終值
  4. 可用于rule值rule屬性rule屬性部件選擇器選擇器部件字符串拼接
  5. 定義時 "@變量名: 變量值;" 的形式;引用時采用 "@變量名" 或 "@{變量名}" 的形式;
  6. 存在作用域,局部作用域優先級高于全局作用域

   Less源碼:

  @color: color;
  @dialog: .dialog;
  @suffix: fix;
  // 空格將被忽略,若要保留空格則需要使用單引號或雙引號
  @hi: 'hello ';
  @dear: there  ;
      
  .dialog{
    // 用于 rule屬性部件,必須使用"@{變量名}" 的形式
     background-@{color}: #888;
     // 用于 rule屬性,必須使用"@{變量名}" 的形式
     @{color}: blue;
  }
  // 用于 選擇器,必須使用"@{變量名}" 的形式
  @{dialog}{
     width: 200px;
  }
  @{dialog}::after{
     content: ': @{hi}@{dear}!';    // 用于 字符串拼接,必須使用"@{變量名}" 的形式
  }
  @h: 1000px;
  // 用于 選擇器部件,必須使用"@{變量名}" 的形式
  .ie-@{suffix}{
    @h: 30px; // 存在作用域,局部作用域優先級高于全局作用域。
     height: @h; // 用于 屬性值,兩種形式均可使用
     line-height: 30px;
  }
      
  // 1. 以@作為變量的起始標識,變量名由字母、數字、_和-組成
  // 2. 沒有先定義后使用的規定;
  @dialog-border-color: #666;
  @dialog-border-width: 10px;
  @dialog-border-width: 1px; // 3. 以最后定義的值為最終值;

    最終輸出:

.dialog {
  background-color: #888;
  color: blue;
}
.dialog {
  width: 200px;
}
.dialog::after {
  content: ': hello there!';
}
.ie-fix {
  height: 30px;
  line-height: 30px;
}

    列表類型

    less變量除了支持#FFF,12px,12,test等單值類型外,還支持列表類型,通過內置函數extract通過索引獲取列表元素,通過內置函數length獲取列表的元素個數

@colors: #FFF, #0F0, #F0F;
.skin{
  color: extract(@colors, 0);
  height: 12px * length(@colors);
}

   最終輸出:

.skin{
  color: #FFF;
  height: 36px;
}

  3. 嵌套(Nested)

  Less源碼:

.main{
  padding: 10px;
   > div {
     width: 100px;
   }
   .aside {
     width: 200px;
   }
  }
    

  最終輸出:

.main {
  padding: 10px;
}
.main > div {
  width: 100px;
}
.main .aside {
  width: 200px;
}

  4. 父選擇器引用(ParentSelector)

  1. 采用&引用完整的父選擇器
  2. 可通過追加和預追加的方式加工&,從而生成新的選擇器
  3. 通過&::after等方式添加偽元素、偽類樣式規則集合
  4. 同一個選擇器可使用多個&
  5. 通過在選擇器后添加 "空格&"的方式,可將當前選擇器排列到最前面
  6. &指向組選擇器時,會生成新的組選擇器

  Less源碼:

 /* 
  * 采用&引用完整的父選擇器
  * 可通過追加和預追加的方式加工&,從而生成新的選擇器
  * 通過&::after等方式添加偽元素樣式規則集合
  * 同一個選擇器可使用多個&
  * 通過在選擇器后添加 "空格&"的方式,可將當前選擇器排列到最前面
  */
@bg: #aaa;
#ps1 .btn{
  background-color: @bg;
   border-radius: 5px;
   &:hover{
     background-color: lighten(@bg, 30%);
      cursor: pointer;
   }
   &-msg, &-eof{
     color: blue;
   }
   .no-borderradius &{
     background-image: url('img/btn-bg.png');
   }
}
/*
 * &指向組選擇器時,會生成新的組選擇器
 */
#dummy1, .dummy1{
  &:hover{
     color: red;
    }
   & + &{
     font-size: 12px;
   }
}

      最終輸出:

/* 
 * 采用&引用完整的父選擇器
 * 可通過追加和預追加的方式加工&,從而生成新的選擇器
 * 通過&::after等方式添加偽元素樣式規則集合
 * 同一個選擇器可使用多個&
 * 通過在選擇器后添加 "空格&"的方式,可將當前選擇器排列到最前面
 */
#ps1 .btn {
  background-color: #aaaaaa;
  border-radius: 5px;
}
#ps1 .btn:hover {
  background-color: #f6f6f6;
  cursor: pointer;
}
#ps1 .btn-msg,
#ps1 .btn-eof {
  color: blue;
}
.no-borderradius #ps1 .btn {
  background-image: url('img/btn-bg.png');
}
/*
 * &指向組選擇器時,會生成新的組選擇器
 */
#dummy1:hover,
.dummy1:hover {
  color: red;
}
#dummy1 + #dummy1,
#dummy1 + .dummy1,
.dummy1 + #dummy1,
.dummy1 + .dummy1 {
  font-size: 12px;
}

5. 導入指令(Import)

  less樣式文件可通過 @import '文件路徑'; 引入外部的less文件。

  注意:

  1. 不帶擴展名或帶非.less的擴展名均被視為less文件;
  2. @import可出現在任何位置,而不像css的@import那樣只能放在文件第一行。

  另外@import還提供了6個可選配置項(分別為reference,inline,less,css,once,multiple),用來改變引入文件的特性。語法為:  @import (reference) '文件路徑'; 。下面為各配置項的具體說明:

1. @import (reference) "文件路徑"; 
  將引入的文件作為樣式庫使用,因此文件中樣式不會被直接編譯為css樣式規則。當前樣式文件通過extendmixins的方式引用樣式庫的內容。
2. @import (inline) "文件路徑"; 
  用于引入與less不兼容的css文件,通過inline配置告知編譯器不對引入的文件進行編譯處理,直接輸出到最終輸出。注意:引入的文件和當前文件會被編譯為一個樣式樣式
3. @import (less) "文件路徑"; 
  默認使用該配置項,表示引入的文件為less文件。
4. @import (css) "文件路徑"; 
  表示當前操作為CSS中的@import操作。當前文件會輸出一個樣式文件,而被引入的文件自身為一個獨立的樣式文件
5. @import (once) "文件路徑"; 
  默認使用該配置項,表示對同一個資源僅引入一次。
6. @import (multiple) "文件路徑"; 
  表示對同一資源可引入多次。

  6. 繼承(Extend)

  有兩種語法形式, <selector>:extend(<parentSelector>){} 和 <selector>{ &:extend(<parentSelector>); } 

   Less源碼:

.animal{
  color: #fff;
}
/* 語法1:<selector>:extend(<parentSelector>){} */
.bear:extend(.animal){
  width: 100px;
  height: 100px;
}
/* 語法2:<selector>{ &:extend(<parentSelector>); } */
.deer{
  &:extend(.animal);
  width: 50px;
  height: 50px;
}

   最終輸出:

.animal,
.bear,
.deer {
  color: #fff;
}
/* 語法1:<selector>:extend(<parentSelector>){} */
.bear {
  width: 100px;
  height: 100px;
}
/* 語法2:<selector>{ &:extend(<parentSelector>); } */
.deer {
  width: 50px;
  height: 50px;
}

注意事項:

  6.1. 父選擇器必須嚴格匹配,除了屬性選擇器中屬性值引號不必匹配外,或添加all關鍵字外。
  Less源碼:
*.parent{
  height: 100px;
   .hair{
     color: #f27;
   }
   [name=eyes]{
     color: #768;
   }
}
// 匹配失敗
.son:extend(.parent){}
.son:extend(.hair){}
          
// 匹配成功
.son:extend(*.parent [name='eyes']){}
.son:extend(*.parent [name="eyes"]){}
// all關鍵字會匹配所有包含parentSelector內容的選擇器,并以selector替換parentSelector來生成新的選擇器
// 下面的內容會生成 *.son,*.son .hair,*.son [name=eyes]三個新的選擇器
.son:extend(.parent all){}

  最終輸出:

*.parent,
*.son {
  height: 100px;
}
*.parent .hair,
*.son .hair {
  color: #f27;
}
*.parent [name=eyes],
.son,
.son,
*.son [name=eyes] {
  color: #768;
}

 6.2. 父選擇器不支持變量形式

 Less源碼:

@p1: .parent1;
@p2: .parent2;
.parent1{
  height: 100px;
}
@{p2}{
  height: 200px;
}
// 匹配失敗
// 形式1,不支持以變量作入參
.son1:extend(@{p1}){}
// 形式2,不支持以變量作為選擇器的規則集合
.son1:extend(.parent2){}
          
// 匹配成功
.son2:extend(.parent1){}
@s3: son3;
.@{s3}:extend(.parent1){}     

  最終輸出:

.parent1,
.son2,
.son3 {
  height: 100px;
}
.parent2 {
  height: 200px;
}

6.3. media query影響繼承的作用域

  6.3.1. media query內的extend操作,僅能繼承當前塊的其他選擇器樣式。

      注意:不能extend當前media query塊內部的子media query塊中的選擇器樣式;但可以extend父media query塊的選擇器樣式。

    Less源碼:

.parent1{
  height: 200px;
}
@media screen{
  .parent1{
    height: 100px;
  }    
   // 無法繼承子media query塊的選擇器樣式
   .son1:extend(.parent2){}
   @media (min-width: 1023px){
     // 繼承父media query塊的選擇器樣式
      .son2:extend(.parent1){}
      .parent2{
        width: 200px;
      }
   }
}   

    最終輸出:

.parent1 {
  height: 200px;
}
@media screen {
  .parent1 {
    height: 100px;
  }
}
@media screen and (min-width: 1023px) {
  .parent2 {
    width: 200px;
  }
}

  6.3.2. 非media query內的extend操作,將會繼承所有media query中匹配的選擇器樣式。

   Less源碼:

@media screen{
  .parent{
     height: 100px;
   }
   @media (min-width: 1023px){
     .parent{
         width: 200px;
       }
   }
}
.son:extend(.parent){}

  最終輸出:

@media screen {
  .parent,
  .son {
    height: 100px;
  }
}
@media screen and (min-width: 1023px) {
  .parent,
  .son {
    width: 200px;
  }
}

 6.4. 增強的mixin定義mixin時僅能使用類選擇器和ID選擇器,而extend操作可對應所有的選擇器,因此當沒有動態入參而又需要類選擇器和ID選擇器以外的選擇器時,可使用extend來實現mixin的功能。

7. 混合(Mixin)

  Mixin相當于macro,會將樣式規則內聯到調用的位置中。而Less中的mixin有以下的注意點:

  7.1. 類選擇器、ID選擇器自動被定義為mixin,而且具有命名空間;
  Less源碼:
.animal{
  .human{
     #fsjohnhuang{
        .hair{
            color: #000;
          }
       }    
    }    
}    
.front-end-monkey{
  // 或者.animal.human#fsjohnhuang.hair();
  // 或者.animal>.human>#fsjohnhuang>.hair;
   // 或者.animal>.human>#fsjohnhuang>.hair();
   // 即可調用mixin
   .animal.human#fsjohnhuang.hair;
}

  最終輸出:

.animal .human #fsjohnhuang .hair {
  color: #000;
}
.front-end-monkey {
  color: #000;
}

  7.2. 顯示定義不帶參數和帶參數的樣式庫(mixin庫),不會輸出到最終輸出中,僅供調用;

  Less源碼:

// 定義不帶參數的mixin
.animal(){
  color: #000;
}
// 定義帶參數的mixin
// 注意:由于,和;均可用于作為參數分隔符,但由于如background、border等樣式屬性支持屬性值組,而,則作為屬性值組元素分隔符,因此推薦使用;作為參數分隔符
.dog(@type; @age){
  height: @type * @age * 12px;
}
// 定義帶參數默認值的mixin
.cat(@type; @age:1){
  height: @type * @age * 5px;
}
          
// 調用才會出現在最終輸出
.chihuahua{
  .dog(1;2);
} 

  最終輸出:

.chihuahua {
  height: 24px;
}

  7.3. mixin內置兩個特殊的對象 @arguments 和 @reset 。@arguments代表mixin的所有入參,而@reset代表mixin的...入參數組。

  Less源碼:

.dog(@type;@age;@rest...){
  height: @type * @age * 12px;
  border: @rest;
}
.cat(@solid;@w;@color){
  border: @arguments;
}
          
.chihuahua{
  .dog(1;2;solid;1px;red);    
}
.mimi{
  .cat(solid;2px;blue);    
}

  最終輸出:

.chihuahua {
  height: 24px;
  border: solid 1px red;
}
.mimi {
  border: solid 2px blue;
}

  7.4. mixin的重載可定義多個同名mixin,調用時只要參數數量匹配則會執行相應的mixin。

  Less源碼:

.dog(@name){
  &::after{
    content: @name;
   }
}
.dog(@name;@age){
  height: @age * 4px;
}
.dog(@name;@age;@width:20px){
  height: @age * 12px;
  width: @width;
}
// 僅匹配到 .dog(@name){
.one-dog{
  .dog('chihuahua');
}    
// 匹配到.dog(@name;@age) 和 .dog(@name;@age;@width:20px)
 .two-three-dog{
   .dog('two-three-dog', 2);
}
          
// 參數的模式匹配
// 當第一參數值為mimi時調用該mixin
.cat(mimi, @age){
  height: @age * 22px;    
}
// 當第一參數值為mini時調用該mixin
.cat(mini, @age){
  height: @age * 12px;    
}
// 不管第一參數值為啥均調用該mixin
.cat(@any, @age){
  color: #f3c;
}
.mycat{
  .cat(mini, 1);
}

  最終輸出:

.one-dog::after {
  content: 'chihuahua';
}
.two-three-dog {
  height: 8px;
  height: 24px;
  width: 20px;
}
.mycat {
  height: 12px;
  color: #f3c;
}

 8. 選擇、循環作業控制

     Less中通過混合(Mixin)后的when關鍵字來提供選擇的作業控制,通過遞歸來實現循環的作業控制。

  Less源碼:

// 條件匹配
// true值匹配,僅實參為true時才匹配成功
.truth(@a) when (@a){
  &::after{
  content: @a;
  }
}
// 匹配成功
.truth1{
  .truth(true);
}
// 匹配失敗
.truth2{
  .truth(#fff);
}
          
/* 類型判斷函數
 * iscolor
 * isnumber
 * isstring
 * iskeyword
 * isurl
 */
.bear(@color) when (iscolor(@color)){
  color: @color;
}
/* 單位判斷函數
 * ispixel
 * ispercentage
 * isem
 * isunit
 */
.bear(@height) when (ispixel(@height)){
  height: @height;
}
// =,>,>=,<=,< 關系運算符
.rich(@h) when (@h > 1000){
  height: @h;    
}
// and、not、or(使用,號表示) 邏輯運算符
.huge(@h, @w) when (@h > 180) and (@w > 180){
  height: @h;
  width: @w;
}
// 使用& when()實現if語句
@debug: true;
& when (@debug){
  div{
    border: solid 1px red;
    }
}
          
// 通過遞歸實現循環
.generate-columns(4);
.generate-columns(@n, @i: 1) when (@i =< @n) {
  .column-@{i} {
    width: (@i * 100% / @n);
  }
   .generate-columns(@n, (@i + 1));
}

  最終輸出:

.truth1::after {
  content: true;
}
/* 類型判斷函數
 * iscolor
 * isnumber
 * isstring
 * iskeyword
 * isurl
 */
/* 單位判斷函數
 * ispixel
 * ispercentage
 * isem
 * isunit
 */
div {
  border: solid 1px red;
}
.column-1 {
  width: 25%;
}
.column-2 {
  width: 50%;
}
.column-3 {
  width: 75%;
}
.column-4 {
  width: 100%;
}

 

五、運算符                            

  Less還支持+、-、*、/運算符。但對單位不一致的運算數進行運算要注意以下兩點:

  1. 運算數與運算符間必須用空格分隔;

  2. 以第一個運算數的單位作為運算結果的單位;

    Less源碼:

// 運算數與運算符間沒有空格
@fail: 1px +2em;
.fail{
  height: @fail;
}

@success1: 1px + 2em;
.success1{
  height: @success1;
}

@success2: 2px + 1em;
.success2{
  height: @success2;
}

    最終輸出:

.fail{
  height: 1px 2em;
}

.success1{
  height: 3px;
}

.success2{
  height: 3em;
}

 

六、函數                              

  Less為我們提供了一個功能強大的內置函數庫,其中絕大部分為顏色處理函數。下面著重介紹Misc Function中的default函數、String Function中的escape函數和顏色處理函數。

  1. default函數

     示例:

// for teenager
.person(@age) when (@age <= 19) and (@age >=13){
  height: @age * 10px;
}
// for child
.person(@age) when (@age <13){
  height: @age * 6px;
}
// for adult
.person(@age) when (default()){
  height: 180px;
}

.son{
  .person(10);
}
.daughter{
  person(17);
}
.father{
 .person(27);
}

    最終輸出:

.son{
  height: 60px;
}
.daughter{
  height: 170px;
}
.father{
  height: 180px;
}

    雖然上述示例邏輯上不合理。但可以看出default函數用于條件控制當中,充當else或switch語句中default的角色。

    通過官網提供的綜合示例我們可以更好理解它的用法:

// Less源碼
.x {
  .m(red)                                    {case-1: darkred}
  .m(blue)                                   {case-2: darkblue}
  .m(@x) when (iscolor(@x)) and (default())  {default-color: @x}
  .m('foo')                                  {case-1: I am 'foo'}
  .m('bar')                                  {case-2: I am 'bar'}
  .m(@x) when (isstring(@x)) and (default()) {default-string: and I am the default}

  &-blue  {.m(blue)}
  &-green {.m(green)}
  &-foo   {.m('foo')}
  &-baz   {.m('baz')}
}

// 最終輸出
.x-blue {
  case-2: #00008b;
}
.x-green {
  default-color: #008000;
}
.x-foo {
  case-1: I am 'foo';
}
.x-baz {
  default-string: and I am the default;
}

   注意:

     1. default函數必須在條件控制語句當中使用;

     2. default函數可實現比else更復雜的功能,如下:

// Less源碼
.mixin(@value) when (ispixel(@value)) {width: @value}
.mixin(@value) when not(default())    {padding: (@value / 5)}

div-1 {
  .mixin(100px);
}

div-2 {
  /* ... */
  .mixin(100%);
}

// 最終輸出:
div-1 {
  width: 100px;
  padding: 20px;
}
div-2 {
  /* ... */
}

  2. escape函數

    顧名思義就是對字符串中的特定字符進行編碼,該函數將對\<space\>#^(){}|:><;][ 和 =字符進行編碼。

  3. 顏色處理函數

    顏色處理函數又分為四大類:顏色定義函數(Color Definition)、顏色通道值獲取函數(Color Channel)、顏色通道值修改函數(Color Operation Function)、混色函數(Color Blending)。

    這里僅僅介紹常用的lighten和darken函數。

     lighten(color, amount) ,color為顏色,amount為增加的亮度值,取值范圍為0-100%。

     darken(color, amount) ,color為顏色,amount為減少的亮度值,取值范圍為0-100%。

 

七、通過Lessc將Less引入開發環境                 

   到這里我想大家已經對Less有一定程度的了解,并希望在將其加入你的開發工具包中。但通過less.js將Less解析器引入到瀏覽器肯定是不適合開發的,而cli工具lessc更適合開發環境中使用。在使用之前我們先要通過npm來安裝less。

npm install -g less

  然后我們就可以通過 lessc [option option=parameter ...] <source> [destination] 的命令格式來調用lessc了!

  lessc的option選項較多,我將主要的選項分為lessc命令信息相關sourcemap相關@import指令相關插件相關四類。

  1. lessc命令信息相關

     lessc -h ,獲取lessc命令的幫助信息;

     lessc -v ,獲取lessc命令的版本號。

  2. sourcemap相關

     由于在瀏覽器直接查看和操作的是CSS樣式規則,而我們開發時使用的Less代碼,這會導致難以找到CSS樣式規則所對應的Less代碼從而增大調試難度。而sourcemap就是為了解決這一痛點而提出的技術解決方案,其原理就是通過一個map文件來保存兩個文件中代碼的對應關系,然后支持sourcemap的瀏覽器的devTools中就會根據這些對應關系來定位相應的Less代碼。(Chrome和FF均支持sourcemap,IE11及以下均不支持)

     若對sourcemap不太了解的可以參考《前端構建:Source Maps詳解》

      --source-map ,生成與生成的css同名的sourcemap文件(例如生成的css文件為main.css,那么sourcemap文件就是main.css.map),且與css文件位于同一目錄下;

      --source-map=<sourcemap文件路徑> ,自定義sourcemap文件的路徑;

       --source-map-rootpath=<sourcemap文件中sources屬性值的路徑前綴> ,假如main.less文件位于src/less下,而生成的css和sourcemap文件位于bin/style下,那么就需要修改sourcemap文件中用于指向less文件路徑的sources屬性值,瀏覽器才能通過sourcemap文件查找到less文件。上述例子的命令為:

                     lessc --source-map --source-map-rootpath=../../src/less/main.less src/less/main.less bin/style/main.css 

       --source-map-map-inline ,以data URI Scheme的形式將sourcemap文件內容內嵌到css文件中。

       --source-map-url=<css文件中指向sourcemap文件的url> ,默認情況下css文件的最后一行會插入如 /*# sourceMappingURL=main.css.map */ 的內容來指向sourcemap文件,而該選項則可修改sourceMappingURL的值。

  3. @import指令相關

       --include-path=<path>[;<path>]* ,通過@import指令引入外部less或css等文件時存在引入的文件路徑到底是以哪個目錄作為參考的問題,我們可以通過該選項來指定參考目錄,當存在多個參考目錄時,使用;號分隔。

       --relative-urls 或 -ru ,用于保持樣式庫中的圖片等資源的相對路徑。示例:

# main.less
@import "files/backgrounds.less";
# files/backgrounds.less
.icon-1 {
  background-image: url('images/lamp-post.png');
}

      不使用該選項時:

.icon-1 {
  background-image: url('images/lamp-post.png');
}

      使用該選項時:

.icon-1 {
  background-image: url('files/images/lamp-post.png');
}

  4. 插件相關

      lessc以插件的形式來增強其功能,下面僅介紹clean-css插件,其他插件請參考http://lesscss.org/usage/#plugins-list-of-less-plugins

      clean-css插件用于壓縮css文件(less-plugin-clean-css@github

      首先通過npm安裝插件 npm install -g less-plugin-clean-css ,然后通過--clean-css選項來啟動CSS壓縮功能。

        如: lessc file.less --clean-css="--s1 --advanced --compatibility=ie8"  

 

八、實戰一下                          

 先假定我們開發環境的目錄結構如下(灰色表示文件由構建工具生成):

  sample

    |-- build.bat     構建工具

    |-- lib              第三方依賴庫

    |     |-- less     

    |            |-- base.less 

    |            |-- img

    |                  |-- nav.png

    |-- src              源碼

    |     |-- less

    |     |      |-- main.less

    |     |-- index.html

    |-- bin              編譯后的文件

    |     |-- style

    |             |-- main.css

    |             |-- main.css.map

    |     |-- index.html

    |-- dist              發布文件

    |-- lib

    |  |-- less

    |          |-- img

    |                |-- nav.png

    |-- app

      |-- style

      |   |--main.css

      |-- index.html

  index.html文件內容:

<html>
<head>
    <title></title>
    <link rel="stylesheet" type="text/css" href="style/main.css"/>    
</head>
<body>
    <div class="nav">
    </div>
</body>
</html>

  樣式庫base.less文件內容:

.base-nav{
    height: 50px;
    background-image: url(img/nav.png);
}
.base-debug{
    border: solid 5px red;
}

   main.less文件內容:

@import (reference) "base.less";
@env:release; //編譯模式:release或debug

/* 導航欄 */
.nav:extend(.base-nav){
    // 編譯模式為debug時采用該樣式
    & when (@env=debug){
        .base-debug();
    }
}

   我們一般將工程代碼級別的產出分為源碼可執行代碼 可發布代碼 三種,而可執行代碼和可發布代碼的構建需求是不同的,因此構建方式也有所區別,也就是lessc使用的選項也會不同。下面將針對不同的產出物來介紹lessc的使用。

   1. 可執行代碼

     我將可執行代碼部分再細分為release和debug兩種編譯模式,可以看到通過變量@env來實現不同模式下采用不同的樣式規則。默認采用release模式編譯源碼。

lessc --include-path=lib/less --relative-urls --source-map --source-map-rootpath=../../src/less/main.less src/less/main.less bin/style/main.css

     在執行lessc命令時通過選項--modify-var="env=debug"即可以debug模式編譯源碼。

lessc --include-path=lib/less --relative-urls --source-map --source-map-rootpath=../../src/less/ --modify-var="env=debug" src/less/main.less bin/style/main.css

     可以看到上述編譯過程中均會生成sourcemap文件以便調試使用。

   2. 可發布代碼

     對于發布的內容我們會對其進行壓縮處理

lessc --include-path=lib/less --clean-css="advanced" --relative-urls src/less/main.less dist/app/style/main.css

     由于sourcemap文件僅在開發階段有用,因此生成發布代碼時就不要生成了。

   完整的構建文件build.bat如下:

@echo off
cls
goto :%1

:bin
echo Building......
::remove subitems of bin
rd /S /Q bin
::copy html files
xcopy /y src\*.html bin\
::compile less to css
cmd /C lessc --include-path=lib/less --relative-urls --source-map --source-map-rootpath=../../src/less/main.less src/less/main.less bin/style/main.css
echo Building is over!
goto :over

:debug
echo Building......
::remove subitems of bin
rd /S /Q bin
::copy html files
xcopy /y src\*.html bin\
::compile less to css
cmd /C lessc --include-path=lib/less --relative-urls --source-map --source-map-rootpath=../../src/less/ --modify-var="env=debug" src/less/main.less bin/style/main.css
echo Building is over!
goto :over

:dist
echo Deploying......
::remove subitems of dist
rd /S /Q dist
::copy lib
xcopy /y lib\less\img dist\lib\less\img\
::copy html files
xcopy /y src\*.html dist\app\
::compile less to css
cmd /C lessc --include-path=lib/less --clean-css="advanced" --relative-urls src/less/main.less dist/app/style/main.css
echo Deploying is over!

:over
View Code

    然后在CMD中輸入 build bin  、 build debug  或  build dist  即可構建工程了!

 sample@github

 

九、與Grunt結合                          

  我們沿用第八節的工程目錄結構來演示。

  首先我們要將npm的package.json添加到工程中,然后安裝grunt及其插件(grunt-contrib-less,less-plugin-clean-css,grunt-contrib-clean,grunt-contrib-copy),現在我們的工程結構應該是這樣的。

 sample-grunt

    |-- package.json

    |-- Gruntfile.js

    |-- node_modules   

    |-- lib              第三方依賴庫

    |     |-- less     

    |            |-- base.less 

    |            |-- img

    |                  |-- nav.png

    |-- src              源碼

    |     |-- less

    |     |      |-- main.less

    |     |-- index.html

    |-- bin              編譯后的文件

    |     |-- style

    |             |-- main.css

    |             |-- main.css.map

    |     |-- index.html

    |-- dist              發布文件

    |-- lib

    |  |-- less

    |          |-- img

    |                |-- nav.png

    |-- app

      |-- style

      |   |--main.css

      |-- index.html

   其中用于將Less編譯為CSS的插件為grunt-contrib-less, 下面我們對應第八章的內容來介紹該插件的選項。

   sourcemap相關:

   {Boolean} sourceMap,對應lessc中屬性值為true/false的--source-map選項;

   {String} sourceMapFilename,對應lessc中屬性值為String的--source-map選項;

   {String} sourceMapRootPath,對應lessc的--source-map-rootpath選項;

   {String} sourceMapURL,對應lessc的--source-map-url選項;

   {Boolean} outputSourceFiles,,對應lessc的--source-map-map-inline選項;

   @import指令相關:

 {Array|String} paths,對應lessc的--include-path選項;

   {Boolean} relativeUrls,對應lessc的--relative-urls選項;

   插件相關:

  {Array} plugins,數組元素為插件實例。

   Gruntfile.js內容如下:

'use strict'

var lessBinDebugOpts = {
        sourceMap: true,
        sourceMapRootpath: '../../'
    },
    debug = {env: 'debug'}

module.exports = function(grunt){
    grunt.initConfig({
        clean: {
            options:{
                force: true
            },
            bin: ['bin'],
            dist: ['dist']
        },
        copy: {
            bin: {
                files: [
                    {expand: true, cwd: 'src/', src: '*.html', dest: 'bin/'}
                ]
            },
            dist: {
                files:[
                    {expand: true, cwd: 'lib/', src: '**', dest: 'dist/lib/'},
                    {expand: true, cwd: 'src/', src: '*.html', dest: 'dist/app'}
                ]
            }    
        },
        less: {
            options:{
                paths: 'lib/less',
                relativeUrls: true
            },
            bin:{
                options: (delete lessBinDebugOpts.modifyVars, lessBinDebugOpts),
                files: {
                    'bin/style/main.css': 'src/less/main.less'
                }
            },
            debug:{
                options: (lessBinDebugOpts.modifyVars = debug, lessBinDebugOpts),
                files: {
                    'bin/style/main.css': 'src/less/main.less'
                }
            },
            dist:{
                options:{
                    plugins: [new (require('less-plugin-clean-css'))({advanced: true})]
                },
                files: {
                    'dist/app/style/main.css': 'src/less/main.less'
                }
            }
        }
    })

    grunt.loadNpmTasks('grunt-contrib-less')
    grunt.loadNpmTasks('grunt-contrib-copy')
    grunt.loadNpmTasks('grunt-contrib-clean')

    var task = function(){
        var name = this.name
            , tasks = ['clean', 'copy', 'less']
            , targets = tasks.map(function(v, i, m){
                var target = name === 'debug' && v !== 'less' ? 'bin' : name
                return v + ':' + target
            })
        grunt.task.run(targets)
    }
    grunt.registerTask('bin', task)
    grunt.registerTask('debug', task)
    grunt.registerTask('dist', task)
}
View Code

   sample-grunt@github

 

十、總結                              

  到這里我只能和大家說一聲,“辛苦了各位,終于看完了耶!”。但正如標題所說,此刻無論是對less的使用,還是將其融入我們的開發工作流,我們均是入了個門而已。那應該如何進階呢?那就是

;; 定義進階過程
(defn becomeGeek [progress]
    (.log js/console "實踐->總結->參考最佳實踐")
    (if (> 100 progress) 
        (becomeGeek (+ 1 progress))
    ))

;; 努力吧騷年!
(becomeGeek 1)

   尊重原創,轉載請注明來自:http://www.cnblogs.com/fsjohnhuang/p/4187675.html ^_^肥仔John!

 


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 AutoPoster 的頭像
    AutoPoster

    互聯網 - 大數據

    AutoPoster 發表在 痞客邦 留言(0) 人氣()