學習Less-看這篇就夠了

前言

CSS的短板

    做爲前端學習者的咱們 或多或少都要學些 CSS ,它做爲前端開發的三大基石之一,時刻引領着 Web 的發展潮向。 而 CSS 做爲一門標記性語言,可能 給初學者第一印象 就是簡單易懂,毫無邏輯,不像編程該有的樣子。在語法更新時,每當新屬性提出,瀏覽器的兼容又會立刻變成絆腳石,能夠說 CSS 短板不容忽視。javascript

    問題的誕生每每伴隨着技術的興起, 在 Web 發展的這幾年, 爲了讓 CSS 富有邏輯性,短板不那麼嚴重,涌現出了 一些神奇的預處理語言。 它們讓 CSS 完全變成一門 可使用 變量 、循環 、繼承 、自定義方法等多種特性的標記語言,邏輯性得以大大加強。css

預處理語言的誕生

其中 就我所知的有三門語言:Sass、Less 、Stylus 。html

  1. Sass 誕生於 2007 年,Ruby 編寫,其語法功能都十分全面,能夠說 它徹底把 CSS 變成了一門編程語言。另外 在國內外都很受歡迎,而且它的項目團隊非常強大 ,是一款十分優秀的預處理語言。
  2. Stylus 誕生於 2010 年,來自 Node.js 社區,語法功能也和 Sass 不相伯仲,是一門十分獨特的創新型語言。
  3. Less 誕生於 2009 年,受Sass的影響建立的一個開源項目。 它擴充了 CSS 語言,增長了諸如變量、混合(mixin)、函數等功能,讓 CSS 更易維護、方便製做主題、擴充(引用於官網)。

選擇預處理語言

這是一個十分糾結的問題。前端

在我看來,這就比如 找女友,有人喜歡 賢惠安靜的,就有人喜歡 活潑愛鬧的,各有各的愛好,可晚上閉燈後 其實都差很少,因此你不用太過糾結。固然了 ,首先 你要有女友。java

在網上討論看來,Sass 與 Stylus 相比於 Less 功能更爲豐富,但對於學習成本以及適應時間 ,Less 稍勝一籌,這也是我選擇 Less 的緣由。程序員

Less 沒有去掉任何 CSS 的功能,而是在現有的語法上,增添了許多額外的功能特性,因此學習 Less 是一件很是舒服的事情。web

若是你以前沒有接觸過預處理語言,糾結應該學哪個,不如先看看 下面 Less 的介紹,我相信你會愛上它的。ajax

使用 Less 的前奏

使用 Less 有兩種方式npm

  1. 在頁面中 引入 Less.js 可在官網下載 或使用CDN
<script src="//cdnjs.cloudflare.com/ajax/libs/less.js/2.7.2/less.min.js"></script>

須要注意的是,link 標籤必定要在 Less.js 以前引入,而且 link 標籤的 rel 屬性要設置爲stylesheet/less。編程

<link rel="stylesheet/less" href="style.less">
       <script src="less.min.js"></script>
  1. 在命令行 使用npm安裝
npm install -g less

具體使用命令

$ lessc styles.less > styles.css

假如還有問題,官網已經有了明確的步驟。

若是你也是 Webpack 的使用者,還須要配合 less-loader 進行處理,具體可見個人這篇文章:Webpack飛行手冊,裏面詳細說明了 less 的處理方式。

若是你在本地環境,可使用第一種方式,很是簡單;但在生產環境中,性能很是重要,最好使用第二種方式。

正文

下面我將簡介 Less 的功能特性。

變量

咱們經常在 CSS 中 看到同一個值重複屢次,這樣難易於代碼維護。 理想狀態,應是下面這樣:

const bgColor="skyblue";
$(".post-content").css("background-color",bgColor);
$("#wrap").css("background-color",bgColor);
$(".arctive").css("background-color",bgColor);

只要咱們修改 bgColor這一個變量, 整個頁面的背景顏色都會隨之改變。

而 Less 中的變量十分強大,可化萬物,值得一提的是,其變量是常量 ,因此只能定義一次,不能重複使用。 值變量

/* Less */
      @color: #999;
      @bgColor: skyblue;//不要添加引號
      @width: 50%;
      #wrap {
        color: @color;
        width: @width;
      }
    
      /* 生成後的 CSS */
      #wrap {
        color: #999;
        width: 50%;
      }

@ 開頭 定義變量,而且使用時 直接 鍵入 @名稱。

在平時工做中,咱們就能夠把 經常使用的變量 封裝到一個文件中,這樣利於代碼組織維護。

@lightPrimaryColor: #c5cae9;
      @textPrimaryColor: #fff;
      @accentColor: rgb(99, 137, 185);
      @primaryTextColor: #646464;
      @secondaryTextColor: #000;
      @dividerColor: #b6b6b6;
      @borderColor: #dadada;

選擇器變量

讓 選擇器 變成 動態

/* Less */
      @mySelector: #wrap;
      @Wrap: wrap;
      @{mySelector}{ //變量名 必須使用大括號包裹
        color: #999;
        width: 50%;
      }
      .@{Wrap}{
        color:#ccc;
      }
      #@{Wrap}{
        color:#666;
      }
    
      /* 生成的 CSS */
      #wrap{
        color: #999;
        width: 50%;
      }
      .wrap{
        color:#ccc;
      }
      #wrap{
        color:#666;
      }

屬性變量

可減小代碼書寫量

/* Less */
      @borderStyle: border-style;
      @Soild:solid;
      #wrap{
        @{borderStyle}: @Soild;//變量名 必須使用大括號包裹
      }
    
      /* 生成的 CSS */
      #wrap{
        border-style:solid;
      }

url 變量

項目結構改變時,修改其變量便可。

/* Less */
      @images: "../img";//須要加引號
      body {
        background: url("@{images}/dog.png");//變量名 必須使用大括號包裹
      }
    
      /* 生成的 CSS */
      body {
        background: url("../img/dog.png");
      }

聲明變量

有點相似於 下面的 混合方法 - 結構: @name: { 屬性: 值 ;}; - 使用:@name();

/* Less */
      @background: {background:red;};
      #main{
          @background();
      }
      @Rules:{
          width: 200px;
          height: 200px;
          border: solid 1px red;
      };
      #con{
        @Rules();
      }
    
      /* 生成的 CSS */
      #main{
        background:red;
      }
      #con{
        width: 200px;
        height: 200px;
        border: solid 1px red;
      }

變量運算

不得不提的是,Less 的變量運算徹底超出個人指望,十分強大。 - 加減法時 以第一個數據的單位爲基準 - 乘除法時 注意單位必定要統一

/* Less */
      @width:300px;
      @color:#222;
      #wrap{
        width:@width-20;
        height:@width-20*5;
        margin:(@width-20)*5;
        color:@color*2;
        background-color:@color + #111;
      }
    
      /* 生成的 CSS */
      #wrap{
        width:280px;
        height:200px;
        margin:1400px;
        color:#444;
        background-color:#333;
      }

變量做用域

一句話理解就是:就近原則,不要跟我提閉包。

藉助官網的Demo

/* Less */
      @var: @a;
      @a: 100%;
      #wrap {
        width: @var;
        @a: 9%;
      }
    
      /* 生成的 CSS */
      #wrap {
        width: 9%;
      }

用變量去定義變量

/* Less */
      @fnord:  "I am fnord.";
      @var:    "fnord";
      #wrap::after{
        content: @@var; //將@var替換爲其值 content:@fnord;
      }
      /* 生成的 CSS */
      #wrap::after{
        content: "I am fnord.";
      }

嵌套

& 的妙用

& :表明的上一層選擇器的名字,此例即是header

/* Less */
      #header{
        &:after{
          content:"Less is more!";
        }
        .title{
          font-weight:bold;
        }
        &_content{//理解方式:直接把 & 替換成 #header
          margin:20px;
        }
      }
      /* 生成的 CSS */
      #header::after{
        content:"Less is more!";
      }
      #header .title{ //嵌套了
        font-weight:bold;
      }
      #header_content{//沒有嵌套!
          margin:20px;
      }

媒體查詢

在以往的工做中,咱們使用 媒體查詢,都要把一個元素 分開寫

#wrap{
        width:500px;
      }
      @media screen and (max-width:768px){
        #wrap{
          width:100px;
        }
      }

Less 提供了一個十分便捷的方式

/* Less */
      #main{
          //something...
    
          @media screen{
              @media (max-width:768px){
                width:100px;
              }
          }
          @media tv {
            width:2000px;
          }
      }
      /* 生成的 CSS */
      @media screen and (maxwidth:768px){
        #main{
            width:100px; 
        }
      }
      @media tv{
        #main{
          width:2000px;
        }
      }

惟一的缺點就是 每個元素都會編譯出本身 @media 聲明,並不會合併。

實戰技巧

能夠藉助 Less 在元素中,去定義本身的私有樣式。

/* Less */
      #main{
        // something..
        &.show{
          display:block;
        }
      }
      .show{
        display:none;
      }
const main = document.getElementById("main");
      main.classList.add("show");

結果:

#main.show{
        display:block;
      }
      .show{
        display:none; //會被覆蓋。
      }

混合方法

無參數方法

方法猶如 聲明的集合,使用時 直接鍵入名稱便可。

/* Less */
      .card { // 等價於 .card()
          background: #f6f6f6;
          -webkit-box-shadow: 0 1px 2px rgba(151, 151, 151, .58);
          box-shadow: 0 1px 2px rgba(151, 151, 151, .58);
      }
      #wrap{
        .card;//等價於.card();
      }
      /* 生成的 CSS */
      #wrap{
        background: #f6f6f6;
        -webkit-box-shadow: 0 1px 2px rgba(151, 151, 151, .58);
        box-shadow: 0 1px 2px rgba(151, 151, 151, .58);
      }

其中 .card.card() 是等價的。 我的建議,爲了不 代碼混淆,應寫成 :

.card(){
        //something...
      }
      #wrap{
        .card();
      }
要點:
  `.` 與 `#` 皆可做爲 方法前綴。
  方法後寫不寫 `()` 看我的習慣。

默認參數方法

Less 可使用默認參數,若是 沒有傳參數,那麼將使用默認參數。

@arguments 猶如 JS 中的 arguments 指代的是 所有參數。

傳的參數中 必須帶着單位。

/* Less */
      .border(@a:10px,@b:50px,@c:30px,@color:#000){
          border:solid 1px @color;
          box-shadow: @arguments;//指代的是 所有參數
      }
      #main{
          .border(0px,5px,30px,red);//必須帶着單位
      }
      #wrap{
          .border(0px);
      }
      #content{
        .border;//等價於 .border()
      }
    
      /* 生成的 CSS */
      #main{
          border:solid 1px red;
          box-shadow:0px,5px,30px,red;
      }
      #wrap{
          border:solid 1px #000;
          box-shadow: 0px 50px 30px #000;
      }
      #content{
          border:solid 1px #000;
          box-shadow: 10px 50px 30px #000;
      }

方法的匹配模式

與 面向對象中的多態 很類似

/* Less */
      .triangle(top,@width:20px,@color:#000){
          border-color:transparent  transparent @color transparent ;
      }
      .triangle(right,@width:20px,@color:#000){
          border-color:transparent @color transparent  transparent ;
      }
    
      .triangle(bottom,@width:20px,@color:#000){
          border-color:@color transparent  transparent  transparent ;
      }
      .triangle(left,@width:20px,@color:#000){
          border-color:transparent  transparent  transparent @color;
      }
      .triangle(@_,@width:20px,@color:#000){
          border-style: solid;
          border-width: @width;
      }
      #main{
          .triangle(left, 50px, #999)
      }
      /* 生成的 CSS */
      #main{
        border-color:transparent  transparent  transparent #999;
        border-style: solid;
        border-width: 50px;
      }

要點

- 第一個參數 `left` 要會找到方法中匹配程度最高的,若是匹配程度相同,將所有選擇,並存在着樣式覆蓋替換。

  - 若是匹配的參數 是變量,則將會匹配,如 `@_` 。

方法的命名空間

讓方法更加規範

/* Less */
      #card(){
          background: #723232;
          .d(@w:300px){
              width: @w;
              
              #a(@h:300px){
                  height: @h;//可使用上一層傳進來的方法
                  width: @w;
              }
          }
      }
      #wrap{
          #card > .d > #a(100px); // 父元素不能加 括號
      }
      #main{
          #card .d();
      }
      #con{
          //不得單獨使用命名空間的方法
          //.d() 若是前面沒有引入命名空間 #card ,將會報錯
          
          #card; // 等價於 #card();
          .d(20px); //必須先引入 #card
      }
      /* 生成的 CSS */
      #wrap{
        height:100px;
        width:300px;
      }
      #main{
        width:300px;
      }
      #con{
        width:20px;
      }

要點

- 在 CSS 中`>` 選擇器,選擇的是 兒子元素,就是 必須與父元素 有直接血源的元素。
  - 在引入命令空間時,如使用 `>` 選擇器,父元素不能加 括號。
  - 不得單獨使用命名空間的方法 必須先引入命名空間,才能使用 其中方法。
  - 子方法 可使用上一層傳進來的方法

方法的條件篩選

Less 沒有 if else,但是它有 when

/* Less */
    #card{
        
        // and 運算符 ,至關於 與運算 &&,必須條件所有符合纔會執行
        .border(@width,@color,@style) when (@width>100px) and(@color=#999){
            border:@style @color @width;
        }
    
        // not 運算符,至關於 非運算 !,條件爲 不符合纔會執行
        .background(@color) when not (@color>=#222){
            background:@color;
        }
    
        // , 逗號分隔符:至關於 或運算 ||,只要有一個符合條件就會執行
        .font(@size:20px) when (@size>50px) , (@size<100px){
            font-size: @size;
        }
    }
    #main{
        #card>.border(200px,#999,solid);
        #card .background(#111);
        #card > .font(40px);
    }
    /* 生成後的 CSS */
    #main{
      border:solid #999 200px;
      background:#111;
      font-size:40px;
    }

要點

- 比較運算有: > >= = =< <。
  - = 表明的是等於
  - 除去關鍵字 true 之外的值都被視爲 false:

數量不定的參數

若是你但願你的方法接受數量不定的參數,你可使用... ,猶如 ES6 的擴展運算符。

/* Less */
      .boxShadow(...){
          box-shadow: @arguments;
      }
      .textShadow(@a,...){
          text-shadow: @arguments;
      }
      #main{
          .boxShadow(1px,4px,30px,red);
          .textShadow(1px,4px,30px,red);
      }
    
      /* 生成後的 CSS */
      #main{
        box-shadow: 1px 4px 30px red;
        text-shadow: 1px 4px 30px red;
      }

方法使用important!

使用方法 很是簡單,在方法名後 加上關鍵字便可。

/* Less */
      .border{
          border: solid 1px red;
          margin: 50px;
      }
      #main{
          .border() !important;
      }
      /* 生成後的 CSS */
      #main {
          border: solid 1px red !important;
          margin: 50px !important;
      }

循環方法

Less 並無提供 for 循環功能,但這也難不倒 聰明的程序員,使用遞歸去實現。

下面是官網中的一個 Demo,模擬了生成柵格系統。

/* Less */
      .generate-columns(4);
    
      .generate-columns(@n, @i: 1) when (@i =< @n) {
        .column-@{i} {
          width: (@i * 100% / @n);
        }
        .generate-columns(@n, (@i + 1));
      }
      /* 生成後的 CSS */
      .column-1 {
        width: 25%;
      }
      .column-2 {
        width: 50%;
      }
      .column-3 {
        width: 75%;
      }
      .column-4 {
        width: 100%;
      }
  1. 屬性拼接方法

+_ 表明的是 空格;+ 表明的是 逗號。

- 逗號
/* Less */
      .boxShadow() {
          box-shadow+: inset 0 0 10px #555;
      }
      .main {
        .boxShadow();
        box-shadow+: 0 0 20px black;
      }
      /* 生成後的 CSS */
      .main {
        box-shadow: inset 0 0 10px #555, 0 0 20px black;
      }
- 空格
/* Less */
      .Animation() {
        transform+_: scale(2);
      }
      .main {
        .Animation();
        transform+_: rotate(15deg);
      }
    
      /* 生成的 CSS */
      .main {
        transform: scale(2) rotate(15deg);
      }
  1. 實戰技巧

    下面是官網中的一個很是讚的 Demo

/* Less */
      .average(@x, @y) {
        @average: ((@x + @y) / 2);
      }
    
      div {
        .average(16px, 50px); // 調用 方法
        padding: @average;    // 使用返回值
      }
    
      /* 生成的 CSS */
      div {
        padding: 33px;
      }

能夠說 Less 是一門優雅編程語言。

繼承

extend 是 Less 的一個僞類。它可繼承 所匹配聲明中的所有樣式。 extend 關鍵字的使用

/* Less */
      .animation{
          transition: all .3s ease-out;
          .hide{
            transform:scale(0);
          }
      }
      #main{
          &:extend(.animation);
      }
      #con{
          &:extend(.animation .hide);
      }
    
      /* 生成後的 CSS */
      .animation,#main{
        transition: all .3s ease-out;
      }
      .animation .hide , #con{
          transform:scale(0);
      }

all 全局搜索替換

使用選擇器匹配到的 所有聲明。
/* Less */
      #main{
        width: 200px;
      }
      #main {
        &:after {
          content:"Less is good!";
        }
      }
      #wrap:extend(#main all) {}
    
      /* 生成的 CSS */
      #main,#wrap{
        width: 200px;
      }
      #main:after, #wrap:after {
          content: "Less is good!";
      }

減小代碼的重複性

從表面 看來,extend 與 方法 最大的差異,就是 extend 是同個選擇器共用同一個聲明,而 方法 是使用本身的聲明,這無疑 增長了代碼的重複性。

方法示例 與上面的 extend 進行對比:

/* Less */
      .Method{
        width: 200px;
        &:after {
            content:"Less is good!";
        }
      }
      #main{
        .Method;
      }
      #wrap{
        .Method;
      }
    
      /* 生成的 CSS */
      #main{
        width: 200px;
        &:after{
          content:"Less is good!";
        }  
      }
      #wrap{
        width: 200px;
        &:after{
          content:"Less is good!";
        }  
      }

要點

翻譯官網

  • 選擇器和擴展之間 是容許有空格的:pre:hover :extend(div pre).

  • 能夠有多個擴展: pre:hover:extend(div pre):extend(.bucket tr) - 注意這與 pre:hover:extend(div pre, .bucket tr)同樣。

  • 這是不能夠的,擴展必須在最後 : pre:hover:extend(div pre).nth-child(odd)。

  • 若是一個規則集包含多個選擇器,全部選擇器均可以使用extend關鍵字。

導入

1. 導入 less 文件 可省略後綴
```less
import "main"; 
//等價於
import "main.less";
```

2. `@import` 的位置可隨意放置
```less
#main{
  font-size:15px;
}
@import "style";
```
  1. reference

    Less 中 最強大的特性 使用 引入的 Less 文件,但不會 編譯它。

    /* Less */
    @import (reference) "bootstrap.less"; 
    
    #wrap:extend(.navbar all){}

    翻譯官網:

    使用@import (reference)導入外部文件,但不會添加 把導入的文件 編譯到最終輸出中,只引用。

  2. once

    @import語句的默認行爲。這代表相同的文件只會被導入一次,而隨後的導入文件的重複代碼都不會解析。

    @import (once) "foo.less";
    @import (once) "foo.less"; // this statement will be ignored
  3. multiple

    使用@import (multiple)容許導入多個同名文件。

    /* Less */
    
    // file: foo.less
    .a {
      color: green;
    }
    // file: main.less
    @import (multiple) "foo.less";
    @import (multiple) "foo.less";
    
    /* 生成後的 CSS */
    .a {
      color: green;
    }
    .a {
      color: green;
    }

函數

  1. 判斷類型

    • isnumber

    判斷給定的值 是否 是一個數字。

    isnumber(#ff0);     // false
    isnumber(blue);     // false
    isnumber("string"); // false
    isnumber(1234);     // true
    isnumber(56px);     // true
    isnumber(7.8%);     // true
    isnumber(keyword);  // false
    isnumber(url(...)); // false
    • iscolor

    判斷給定的值 是否 是一個顏色。

    • isurl

    判斷給定的值 是否 是一個 url 。

  2. 顏色操做

    • saturate

    增長必定數值的顏色飽和度。

    • lighten

    增長必定數值的顏色亮度。

    • darken

    下降必定數值的顏色亮度。

    • fade

    給顏色設定必定數值的透明度。

    • mix

    根據比例混合兩種顏色。

  3. 數學函數

    • ceil

    向上取整。

    • floor

    向下取整。

    • percentage

    將浮點數轉換爲百分比字符串。

    • round

    四捨五入。

    • sqrt

    計算一個數的平方根。

    • abs

    計算數字的絕對值,原樣保持單位。

    • pow

    計算一個數的乘方。

因爲 文章 篇幅有限,因此 只能介紹一些 使用效率高的函數。

若是你想了解更多,能夠去官網的函數連接

其餘

  1. 註釋

    • /* */ CSS原生註釋,會被編譯在 CSS 文件中。
    • /   / Less提供的一種註釋,不會被編譯在 CSS 文件中。
  2. 避免編譯

/* Less */
      #main{
        width:~'calc(300px-30px)';
      }
    
      /* 生成後的 CSS */
      #main{
        width:calc(300px-30px);
      }
結構: `~' 值 '`
  1. 使用 JS

    由於 Less 是由 JS 編寫,因此 Less 有一得天獨厚的特性:代碼中使用 Javascript 。

/* Less */
      @content:`"aaa".toUpperCase()`;
      #randomColor{
        @randomColor: ~"rgb(`Math.round(Math.random() * 256)`,`Math.round(Math.random() * 256)`,`Math.round(Math.random() * 256)`)";
      }
      #wrap{
        width: ~"`Math.round(Math.random() * 100)`px";
        &:after{
            content:@content;
        }
        height: ~"`window.innerHeight`px";
        alert:~"`alert(1)`";
        #randomColor();
        background-color: @randomColor;
      }
      /* 生成後的 CSS */
    
      // 彈出 1
      #wrap{
        width: 隨機值(0~100)px;
        height: 743px;//由電腦而異
        background: 隨機顏色;
      }
      #wrap::after{
        content:"AAA";
      }

    前幾個月 , 有個 CSS in JS 的概念很是火,如今 看來 JS in CSS 也不曾不可。 我以爲徹底能夠根據 Less 這個特性來造個輪子,JS來控制 CSS ,造成 動態屬性,若是成功 極可能會改變 如今前端的打開姿式。

結束語

    從我學習 Web 以來,無數前輩告訴我,Web 有三大基石,JS 控制行爲,HTML 控制結構,CSS 控制樣式。我一直再想 爲何要分爲 3 個語言?爲何不能合成一個語言?或者說 就沒有更合適的嗎?在這幾年的 Web 發展中,頁面從 MVC 到 如今的 MVVC,結構正在發生着改變,但 其根本 不過是造了一個又一個 完美的輪子。咱們爲何就不能打破傳統呢?讓 前端的 三大基石 變成一座大山呢 ?     請試想一下,那該是個怎樣的世界。


我叫 Simon , 來自北方,以上即是 Less 的特性總結,但願本文能對你有所幫助。

(完)

相關文章
相關標籤/搜索