Less(v3.9.0)使用詳解—extend(擴充套件)

白夜追胸發表於2019-04-27

該系列:

Less(v3.9.0)使用詳解——基本使用

Less(v3.9.0)使用詳解——變數

Less(v3.9.0)使用詳解——巢狀和父選擇器&

Less(v3.9.0)使用詳解——extend(巢狀)

其他待更新...

Extend(擴充套件)

:extend(selector1,[selector2,...]),就像css中的偽類,不過可以傳遞至少1個選擇器,:之前的選擇器,將與()中的選擇器共用一份樣式

nav ul {
  &:extend(.inline);
  background: blue;
}
.inline {
  color: red;
}

//當不需要引用選擇器時,也可以不用&
nav ul:extend(.inline){
  background: blue;
}
.inline {
  color: red;
}
複製程式碼

編譯為

nav ul {
  background: blue;
}
.inline,
nav ul {
  color: red;
}
複製程式碼

extend能包含多個選擇器,用逗號隔開

.e:extend(.f) {}
.e:extend(.g) {}

// 等同於下面
.e:extend(.f, .g) {}
複製程式碼

extend必須放在選擇器末尾,注意這個pre:hover:extend(div pre):extend(.bucket tr)是允許的,等同於pre:hover:extend(div pre, .bucket tr)

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

.a,
.b:extend(.bag),
.c:extend(.bucket) {
  width:100px;
}
.bag{
  color:white;
}
.bucker{
  heigth:100px;
}
複製程式碼

編譯為

.a,
.b,
.c {
  width: 100px;
}
.bag,
.b {
  color: white;
}
.bucker {
  heigth: 100px;
}
複製程式碼

如何規則集的extend一樣,可以省略前面的

pre:hover:extend(div pre),
.some-class:extend(div pre) {}
複製程式碼

可以省略第一個extend

pre:hover,
.some-class {
  &:extend(div pre);
}
複製程式碼

extend同樣適用於巢狀規則

.bucket {
  tr { 
    color: blue;
  }
}
.some-class:extend(.bucket tr) {} 
複製程式碼

編譯為

.bucket tr,
.some-class {
  color: blue;
}
複製程式碼

:extend中選擇符是精確匹配的

.a.class,
.class.a,
.class > .a {
  color: blue;
}
.test:extend(.class) {} // this will NOT match the any selectors above
複製程式碼

因為找不到匹配.class,所以編譯為

.a.class,
.class.a,
.class > .a {
  color: blue;
}
複製程式碼

注意即使*.class和.class在css中匹配的是一樣的,但extend不會匹配它

*.class {
  color: blue;
}
.noStar:extend(.class) {} // this will NOT match the *.class selector
複製程式碼

注意偽選擇器的順序也有會影響匹配的

link:hover:visited {
  color: blue;
}
.selector:extend(link:visited:hover) {}
複製程式碼

不會匹配到

nth表示式也會影響匹配,1n+3和n+3是不一樣的.

:nth-child(1n+3) {
  color: blue;
}
.child:extend(:nth-child(n+3)) {}
複製程式碼

編譯為

:nth-child(1n+3) {
  color: blue;
}
複製程式碼

不過extend倒是不在意單/雙引號

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

.noQuote:extend([title=identifier]) {}
.singleQuote:extend([title='identifier']) {}
.doubleQuote:extend([title="identifier"]) {}
複製程式碼

編譯為

[title=identifier],
.noQuote,
.singleQuote,
.doubleQuote {
  color: blue;
}

[title='identifier'],
.noQuote,
.singleQuote,
.doubleQuote {
  color: blue;
}

[title="identifier"],
.noQuote,
.singleQuote,
.doubleQuote {
  color: blue;
}
複製程式碼

extend包含all時,會把()裡的選擇器匹配,然後用:extend之前的選擇器建立新的選擇器

.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;
}
複製程式碼

可以發現到除了舊的選擇器組合外,又有了新的組合,即.test被.replacement取代出現的新的選擇器

extend()引數不支援變數,但:支援變數

@variable: .bucket;
@{variable} { // interpolated selector
  color: blue;
}
.some-class:extend(.bucket) {} // does nothing, no match is found
複製程式碼
.bucket {
  color: blue;
}
.some-class:extend(@{variable}) {} // interpolated selector matches nothing
@variable: .bucket;
複製程式碼

以上兩個都只能編譯為

.bucket {
  color: blue;
}
複製程式碼

然而

.bucket {
  color: blue;
}
@{variable}:extend(.bucket) {}
@variable: .selector;
複製程式碼

就能識別

.bucket, .selector {
  color: blue;
}
複製程式碼

@media中的extend只能匹配處於同個media規則的選擇器

@media print {
  .screenClass:extend(.selector) {} // extend inside media
  .selector { // this will be matched - it is in the same media
    color: black;
  }
}
.selector { // ruleset on top of style sheet - extend ignores it
  color: red;
}
@media screen {
  .selector {  // ruleset inside another media - extend ignores it
    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;
  }
}
複製程式碼

注意即使是巢狀的也不行

@media screen {
  .screenClass:extend(.selector) {} // extend inside media
  @media (min-width: 1023px) {
    .selector {  // ruleset inside nested media - extend ignores it
      color: blue;
    }
  }
}
複製程式碼

編譯成

@media screen and (min-width: 1023px) {
  .selector { /* ruleset inside another nested media was ignored */
    color: blue;
  }
}
複製程式碼

不過最頂級的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) {} /* top level extend matches everything */
複製程式碼

編譯成

@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;
  }
}
複製程式碼

使用場景

  1. 避免新增一個基類

    不使用的情況下

    <a class="animal bear">Bear</a>
    .animal {
      background-color: black;
      color: white;
    }
    .bear {
      background-color: brown;
    }
    複製程式碼

    使用後可以簡化html,個人覺得見仁見智,不使用的情況語義更好理解

    <a class="bear">Bear</a>
    .animal {
      background-color: black;
      color: white;
    }
    .bear {
      &:extend(.animal);
      background-color: brown;
    }
    複製程式碼
  2. 減少css體積,mixin將所有屬性複製到一個選擇器中,這會導致不必要的重複。因此,您可以使用 :extend 而不是mixin將選擇器移到您希望使用的屬性,這樣會大大減少生成的css。

    使用mixin:

    .my-inline-block() {
      display: inline-block;
      font-size: 0;
    }
    .thing1 {
      .my-inline-block;
    }
    .thing2 {
      .my-inline-block;
    }
    複製程式碼

    Outputs

    .thing1 {
      display: inline-block;
      font-size: 0;
    }
    .thing2 {
      display: inline-block;
      font-size: 0;
    }
    複製程式碼

    使用extends

    .my-inline-block {
      display: inline-block;
      font-size: 0;
    }
    .thing1 {
      &:extend(.my-inline-block);
    }
    .thing2 {
      &:extend(.my-inline-block);
    }
    複製程式碼

    Outputs

    .my-inline-block,
    .thing1,
    .thing2 {
      display: inline-block;
      font-size: 0;
    }
    複製程式碼
  3. 關聯某個樣式,由於mixin只能使用簡單的選擇器,如果介面有兩個不同的塊但使用相同的樣式,在用不了minxin的情況可以這樣使用

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

相關文章