1. 程式人生 > >less 新手入門(一) 變數、extend 擴充套件

less 新手入門(一) 變數、extend 擴充套件

變數

1.定義

使用 @ 符號來定義變數 ,在Less中開頭是 @ 則是變數,關於變數的命名方法,大家可以參考js中命名的規則,畢竟是做前端的,有著統一的習慣有助於我們統一風格。個人推薦變數名的命名規則使用駝峰命名法。第一個單詞首寫字母小寫,從第二個開始,單詞首寫字母大寫。如boxAaa,boxBbbb,boxContainer,……,當然也是可是使用香腸命名法用下劃線“_”來命名。如,box_main,border_bottom,……

2.使用

在樣式屬性值中使用時,直接用 @variable 即可呼叫變數;在其他地方,包括選擇器名稱、屬性名稱、URL和@import語句使用時,變數必須以插值的形式使用,
例如:

@variable: 200px; //定義變數作為樣式屬性值使用
@classname: .nav_a; //變數值不可用中劃線,此變數作為插值用於選擇器名稱


@{classname}{ //作為插值 必須加 {}
    width: @variable; //作為屬性值直接呼叫
}

輸出:

.nav_a {
  width: 200px;
}

3. 變數特點:

變數是懶載入的,不要求一定在使用之前宣告。

4. 在存在多個同名變數時,變數如何獲取值?

和css規則類似,在同時定義一個變數兩次時,會在使用變數的地方,從當前範圍向上搜尋,使用變數最後定義內的屬性值。

@var: 0;
.class1 {
  @var: 1;
  .class {
    @var: 2;
    three: @var;
    @var: 3;
  }
  one: @var;
}

編譯輸出

.class1 .class {
  three: 3;
}
.class {
  one: 1;
}

5. 變數的其它使用技巧:初始值

在定義變數時可以給變數賦一個初始值,後期在使用中通過重新定義或函式 來覆蓋原本的初始值

Extend 擴充套件

:extend是一個偽類,使用它的選擇器,將和它引用的選擇器一起使用它引用的選擇器的樣式,如:先定義一個擴充套件的選擇器,我們就叫它 .a,然後定義一個選擇器 .b(用來擴充套件),在 .a內使用 :extend 擴充套件,程式碼如下

.a{
    &:extend(.b);  //這裡的 & 為 父選擇符,代表的 父選擇符 .a 擴充套件 .b
    font-size: 12px;
}
.b{
    font-weight: bold;
}

輸出:

.a {
  font-size: 12px;
}
.b,
.a {
  font-weight: bold;  //這裡 a 擴充套件也引用了 b 的樣式
}

注意:如果這裡的 .b 內沒有定義任何樣式,那麼編譯後的css中, 不會有 .b 的任何輸出,相應的 .a 也不會擴充套件到任何樣式

1. :extend 語法

:extend()可以附加到選擇器後面,也可以放到樣式規則中,它看起來就像是一個選擇器的偽類,在使用的時候我們可以選擇性的加上 關鍵字 all

語法示例:

.a:extend(.b){}   //方法一:附加到選擇器後
.a{
    &:extend(.b)    // 方法二:寫在樣式規則中
}

all關鍵字的使用詳解 見 第7條

2. :extend() 直接使用在選擇器後

每個選擇器可以使用多個 :extend() 語句, 但是所使用的 :extend() 語句必須放在選擇器末尾,下面詳細描述:

  • 在選擇器之後:extend :pre:hover:extend(div pre)。
  • 選擇器和擴充套件之間允許有空格: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必須在選擇器末尾。

如果規則集包含多個選擇器,則它們中的任何一個選擇器都可以具有extend關鍵字。在一個規則集中擴充套件的多個選擇器:

.a,
.b:extend(.bag),
.c:extend(.bucket) {
  // 這裡啊a,b,c  3個選擇器都可以使用 :extend
}

3. :extend()在樣式規則中使用

把 :extend() 放到多個選擇器共用的樣式規則集中,是把樣式擴充套件到每個選擇器的最佳選擇。

下面來個對比:

  • 直接把: extend() 放到樣式規則中,
.a,
.c,
.d{
    &:extend(.b);
}
.b{
    font-size: 12rem;
}

輸出:

.b,
.a,
.c,
.d {
  font-size: 12rem;
}

如果把 :extend 放在選擇器後,那麼需要單獨對 .a , .c , .d單獨處理,會增加程式碼量,後期維護也很繁瑣

.a:extend(.b){}
.c:extend(.b){}
.d:extend(.b){}

4. 擴充套件 巢狀選擇器

將:extend() 直接放在選擇器後,可以擴充套件巢狀選擇器樣式規則,示例:

.my-table{
   .my-tr{
        font-size: 50px;
    }
}

.mt-other-table:extend(.my-table .my-tr){}

5. :extend中選擇符的精確匹配

預設情況下,:extend() 中查詢選擇器的原則是精準匹配,就算是 選擇器 在開始使用(例如 .class .a)也沒用;或者是兩個選擇符表示式韓式一樣,那在匹配過程中也沒有意義,:extend()中選擇器只能匹配到 具有相同形式的選擇器。唯一例外的是屬性選擇器中的 引號 ,Less知道它們具有相同的含義並匹配它們。

示例:

**.a.class,
.class.a,
.class>.a{
    color: blue;
}
.test:extend(.class) {}**

編譯下,命令列中報錯了… 沒有匹配到 .class

$ lessc refer.less > refer.css
extend ' .class' has no matches

選擇器前面的符號是很重要的, 雖然 *.class{} 和.class{}是一樣的,但是在:extend(.class)中無法匹配到 *.class

*.class {
  color: blue;
}
.noStar:extend(.class) {} // 不會匹配到 *.class 

多個偽類在 :extend() 中的順序也很重要,選擇器link:hover:visited和link:visited:hover匹配相同的一組元素,但 :extend() 將它們視為不同。

link:hover:visited {
  color: blue;
}
//此時無法匹配到link:hover:visited
.selector:extend(link:visited:hover) {}  

6. 使用 n 的選擇器 、使用屬性篩選的選擇器

1n+3和n+3相當,但:extend不會匹配他們:

:nth-child(1n+3) {
  color: blue;
}
.child:extend(n+3) {} // 無法匹配

在屬性選擇器中的引用型別無關緊要。以下所有都是相同的。

[title=identifier] {
  color: blue;
}
[title='identifier'] {
  color: blue;
}
[title="identifier"] {
  color: blue;
}

.noQuote:extend([title=identifier]) {}
.singleQuote:extend([title='identifier']) {}
.doubleQuote:extend([title="identifier"]) {}

7. :extend() 中關鍵字 all的使用

在使用extend時,在末尾新增 all 關鍵字,它會告訴Less作為另一個選擇器的一部分匹配該選擇器。選擇器將被複制,只有選擇器的匹配部分將被替換為擴充套件,從而建立一個新的選擇器。

例:

.a.b.test,
.test.c {
  color: orange;
}
.test {
  &:hover {
    color: green;
  }
}

.replacement:extend(.test all) {}

輸出:

.a.b.test,
.test.c,
.a.b.replacement,
.replacement.c {
  color: orange;
}
.test:hover,
.replacement:hover {
  color: green;
}

8. 選擇器插值與extend

:extend不能將選擇器與變數相匹配。如果選擇器包含變數,擴充套件將忽略它;
變數無法與選擇器匹配:

@variable: .bucket; //定義變數
@{variable} { // 變數插值
  color: blue;
}
//沒有做任何工作,此時無法匹配到 .selector
.some-class:extend(.bucket) {} 

輸出:僅僅只輸出了 .selector 的樣式規則

.bucket {
  color: blue;
}

但是,將 :extend 擴充套件直接寫在 變數選擇器後,可正常使用,將上例程式碼改為如下:

.bucket{
    color: blue;
}
//此時有中劃線,將 . 移至變數插值前,否則會報錯
@variable: some-class; 
// 在變數選擇器後使用 :extend ,正常編譯
[email protected]{variable}:extend(.bucket){}  

正常編譯:

.bucket,
.some-class {
  color: blue;
}

9. 作用範圍 / extend 在 @media 中的使用

  1. 在 media 媒體宣告中寫入的 extend 只匹配同一媒體宣告中的選擇器:
@media print {
  .screenClass:extend(.selector) {} // extend inside media
  .selector { // 這會被匹配到 - 以為和extend在同一個media內
    color: black;
  }
}
.selector { // 規則集在上一個樣式中 - extend 將忽略這
  color: red;
}
@media screen {
  .selector {  // r規則集在另一個樣式中 - extend 將忽略這
    color: blue;
  }
}

輸出:

@media print {
  .selector,
  .screenClass { /*  ruleset inside the same media was extended */
    color: black;
  }
}
.selector { /* ruleset on top of style sheet was ignored */
  color: red;
}
@media screen {
  .selector { /* ruleset inside another media was ignored */
    color: blue;
  }
}
  1. 在媒體宣告中寫入的 extend ,不匹配其巢狀宣告中的選擇器:
@media screen {
  .screenClass:extend(.selector) {} // extend inside media
  @media (min-width: 1023px) {
    .selector {  // css在media內部巢狀 - extend 將忽略它
      color: blue;
    }
  }
}

輸出:

@media screen and (min-width: 1023px) {
/* ruleset inside another nested media was ignored */
  .selector { 
    color: blue;
  }
}
  1. 頂級 :extend 將匹配所有內容,包括巢狀媒體中的選擇器
@media screen {
  .selector {  /* ruleset inside nested media - top level extend works */
    color: blue;
  }
  @media (min-width: 1023px) {
    .selector {  /* ruleset inside nested media - top level extend works */
      color: blue;
    }
  }
}

.topLevel:extend(.selector) {} /* 定層級 :extend 匹配所有 */

輸出:

@media screen {
  .selector,
  .topLevel { /* ruleset inside media was extended */
    color: blue;
  }
}
@media screen and (min-width: 1023px) {
  .selector,
  .topLevel { /* ruleset inside nested media was extended */
    color: blue;
  }
}

10. 重複檢測 - Duplication Detection

在使用:extend 時,less目前沒有檢測重複的 功能

.alert-info,
.widget {
  /* declarations */
}

.alert:extend(.alert-info, .widget) {}

輸出:

.alert-info,
.widget,
.alert,
.alert {
  /* declarations */
}

11. Extend案例擴充套件

1.典型用例
典型的用例是避免在html新增 基本選擇器類別 。
例如,如果你有

.animal {
  background-color: black;
  color: white;
}

然後你想要一種重寫 background-color 的class類 ,這時你有兩個方法,第一種方法是:改變你的HTML,新增另一個選擇器類 bear

<a class="animal bear">Bear</a>

.animal {
  background-color: black;
  color: white;
}
.bear {
  background-color: brown;
}

第二種方法是:簡化html同時使用less的 :extend,例如
<a class="bear">Bear</a>

.animal {
  background-color: black;
  color: white;
}
.bear {
  &:extend(.animal);
  background-color: brown;
}
  1. 減少css大小

mixin將所有屬性複製到一個選擇器中,這會導致不必要的重複。因此,您可以使用 :extend 而不是mixin將選擇器移到您希望使用的屬性,這樣會大大減少生成的css。當使用mixin時:

.my-inline-block() {
  display: inline-block;
  font-size: 0;
}
.thing1 {
  .my-inline-block;
}
.thing2 {
  .my-inline-block;
}

輸出:

.thing1 {
  display: inline-block;
  font-size: 0;
}
.thing2 {
  display: inline-block;
  font-size: 0;
}

改寫使用 :extend( )

.my-inline-block {
  display: inline-block;
  font-size: 0;
}
.thing1 {
  &:extend(.my-inline-block);
}
.thing2 {
  &:extend(.my-inline-block);
}

輸出:

.my-inline-block,
.thing1,
.thing2 {
  display: inline-block;
  font-size: 0;
}
  1. 結合樣式 / 更高階的混合

另一個用例是mixin的替代方案——因為mixin只能與簡單的選擇器一起使用,如果您在html上有兩個不同的塊,但是它們需要應用相同的樣式到,那麼您可以使用 :extend 來關聯兩個區域。

li.list > a {
  // list styles
}
button.list-style {
  &:extend(li.list > a); // use the same list styles
}