less學習筆記3-語言特性(extend)

extend這一部分真的看得我不知道要怎么說明好,難怪less中文網這一部分完全沒有翻譯。看著一部分的時候感覺無從下口啊,好些地方都覺得好違和,講不清楚的感覺,所以文中用到extend的地方均使用英文的extend。在第三次閱讀的時候,突然才發現extend有一些Java中繼承的感覺,所以最后就決定將extend翻譯成繼承,有稍微了解過Java繼承的簡單概念的小伙伴,應該很容易就理解extend的作用和原理。也自行定義了兩個選擇器A和B,選擇器A和B的引入方便文中解釋的理解,也方便我的表達,所以要先記住選擇器A和B的定義再看下面的內容會好理解很多,當然最好的就是結合英文原文一起學習,如果有更好的理解也歡迎多多提出。還是有部分解釋講解的不夠清晰,爭取全部學習結束后再次整理下。


繼承(Extend)

Extend可以理解成一種less的偽類,形式為A:extend(B),其作用:使用這個偽類選擇器(A)可以將符合其條件的選擇器(B)的樣式規則引用給自身用,即A會擁有B的樣式規則。

(A:extend(B))下面會用A泛指使用extend偽類的選擇器,用B泛指extend偽類所去匹配的選擇器。

發布于v1.4.0

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

上面設置的規則中,:extend 這個偽類會把“使用extend的選擇器”(nav ul)擁有 .inline 的規則。如果.inline這個選擇器不存在,那么A選擇器的聲明代碼塊將會保持原樣,但是extend語句將無效(因為extend不是css)

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

編譯為:

nav ul{
    background: blue;
}
.inline,nav ul{
    color: red;
}

注意到 nav ul:extend(.inline) 選擇器編譯成nav ul的過程 - 在編譯之前,選擇器中的extend偽類的那個語句會被移除,其余的語句保持原樣。如果extend中的B選擇器沒有樣式,那么extend在編譯過程中會被移除(但是extend有可能會影響其他的選擇器)。

Extend語法

Extend要么接在選擇器后面要么放置在規則中。看起來很像是偽類選擇器,并且擁有一個可選的參數 all

.a:extend(.b){ ... }
//上面的代碼與下面的代碼編譯出來的一致
.a{
    &:extend(.b);
}

.c:extend(.d all){
    //包含了".d"的所有實例,例如:" .x.d"或者".d.x"
}
.c:extend(.d){
    //只包含一個實例,選擇器只會被編譯成 ".d"的實例
}

Extend中可以包含一個或者多個類,用逗號分隔

.e:extend(.f){...}
.e:extend(.g){...}
//上面和下面代碼的編譯結果一樣
.e:extend(.f,.g){...}

Extend使用方式

Extend的使用方式就像使用普通的偽類一樣,一個選擇器可以包含多個Extend,但是所有Extend都要放置在這個選擇器的末端。

  • Extend置于選擇器后面: pre:hover:extend(div pre)
  • 選擇器和Extend之間允許間隔空格:pre:hover :extend(div pre)
  • 允許多個Extend: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關鍵詞。下面為多個選擇器擁有一個規則的情況:

.big-division,
.big-bag:extend(bag),
.big-bucket:extend(bucket){
  ...
}

在規則中的Extend

Extend可以通過使用&:extend(selector)這個語法將extend放置在規則內部。將Extend放在規則內部是將Extend單獨作用在每個選擇器的簡化形式。

放在內部:
pre:hover,.some-class{
    &:extend(div pre);
    ...
}

等同于在每個選擇器中單獨添加Extend:
pre:hover:extend(div pre),
.some-class:extend(div pre){...}

Extend中使用嵌套選擇器

Extend允許使用嵌套選擇器(即B選擇器為嵌套形選擇器):

.bucket{
    tr{
        color: blue;
    }
}
.some-class:extend(.bucket tr){ ... }

編譯為:
.bucket tr,
.some-class{
    color: blue;
}

Extend準確匹配

Extend默認會在所有選擇器中尋找與B選擇器匹配的選擇器,無論B選擇器是否使用*(星號)。如果兩個后代表達式(詳細看下一段)對應同一個元素,但是匹配的時候也是要根據后代表達式中的格式進行匹配。一個唯一的例外就是屬性選擇器的,less知道它們意思相同并且能進行匹配。

.a.class,.class.a,.class>.a{
    color: blue;
}
.test:extend(.class){ ... }//匹配不到上面的任何選擇器

*可以認為是任意選擇器。 *.class和.class是對應同一個元素數組,但是Extend進行匹配的時候不會將二者認為是同一個。

*.class{
    color: blue;
}
.test:extend(.class){ ... }//不會匹配到*.class這個選擇器

編譯為:
*.class{
    color: blue;
}

匹配時會根據偽類的順序。選擇器link:hover:visitedlink:visited:hover匹配到的是同一個元素,但是Extend會區分它們。

link:visited:hover{
    color: blue;
}
.selector:extend(link:hover:visited){ ... }

編譯為:
link:visited:hover{
    color: blue;
}

后代表達式

匹配會根據后代表達式的形式進行匹配。后代表達式1n+3n+3是相等的,但是Extend不會匹配二者。

:nth-child(1n+3){
    color: blue;
}
.child:extend(:nth-child(n+3)){ ... }

編譯為:
:nth-child(1n+3){
    color: blue;
}

屬性選擇器的引用類型不會進行匹配。下面的情況都相等。

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

編譯為:
[title=indentifier],
.noQuote,
.singleQuote,
.doubleQuote{
    color: blue;
}
or
[title='identifier'],
.noQuote,
.singleQuote,
.doubleQuote {
  color: blue;
}
or
[title="identifier"],
.noQuote,
.singleQuote,
.doubleQuote {
  color: blue;
}

Extend"all"

當你指定了Extend的最后一個參數為all時,less將會匹配一些名字包含B選擇器的名字的C選擇器,類似模糊匹配那樣。當匹配到選擇器后,C選擇器將會被復制,并且將C選擇器名字中匹配到的那部分替換B選擇器的名字,變成新的選擇器。

.a.b.test,
.test.c{
    color: green;
}
.test{
    &:hover{
        color: red;
    }
}
.replace:extend(.test all){}

編譯成:

.a.b.test,
.test.c,
.a.b.replace,
.replace.c{
    color: green;
}
.test:hover,
.replace:hover{
    color: red;
}

你可以將這個操作理解成做一個非破壞性的搜索和匹配

在Extend中使用選擇器插入(Selector Interpolation with Extend)

Extend不能夠匹配有變量的選擇器,如果選擇器包含變量,Extend將會將其忽略。
這是一個未定的特性,但是不會輕易改變。但是extend可以連接插入性選擇器(包含變量的選擇器A)。

包含變量的選擇器將不會被匹配:

@var: .bucket;
@{var}{  //插入性選擇器
    color: blue;
}
.some-class:extend(.bucket){}//不做任何事

在目標選擇器進行extend中使用變量將不會被匹配:

.bucket{
    color: blue;
}
.some-class:extend(@{var}){}//匹配不到選擇器
@var: .bucket;

上面兩個都會編譯成:

.bucket{
    color: blue;
}

然而,:extend可以連接到插入性選擇器:

.bucket{
    color: blue;
}
@{var}:extend(.bucket){}
@var: .test;

編譯為:
.bucket,.test{
    color: blue;
}

總結就是:A選擇器可以包含變量,但是B選擇器不能包含變量。

作用范圍/@media里面的extend

寫在一個media聲明中的extend只能匹配在同一個media里面的選擇器:

@media print{
    .screenClass:extend(.selector){}
    .selector{
        color: black;
    }
}
.selector{
    color: red;
}
@media screen{
    .selector{
        color: blue;
    }
}

編譯為:

@meida print{
    .screenClass,.selector{
        color: black;
    }
}
.selector{
    color: red;
}
@media screen{
    .selector{
        color: blue;
    }
}

寫在一個media聲明中的extend不會匹配到嵌套在里面的media聲明里面的選擇器:

@media screen{
    .selectorClass:extend(.selector){}
    @media (min-width: 768px){
        .selector{
            color: blue;
        }    
    }
}

編譯為:

@media screen and (min-width: 768px){
    .selector{
        color: blue;
    }
}

外部extend可以匹配范圍無限制,包括內部的嵌套media里面的選擇器:

@media screen{
    .selector{
        color: blue;
    }
    @media (min-width: 768px){
        .selector{
            color: red;
        }
    }
}
.topLevel:extend(.selector){}
編譯為:
@media screen{
    .selector,
    .topLevel{
        color: blue;
    }
}
@media screen and (min-width: 768px){
    .selector,
    .topLevel{
        color: red;
    }
}

重復檢測

現在是沒有重復檢測的功能。

.alert,.widget{ ... }
.test:extend(.alert, .widget){}

編譯為:

.alert,.widget,.test,.test{ ... }

所以在使用extend的時候需要注意不要extend具有相同規則的選擇器

extend的使用情況

  • 典型使用情況

典型的使用情況是為了避免增加一個類:

如果你有一個類animal
.animal{
    background-color: black;
    color: white;
}
然后你想要通過復寫background-color這個屬性來得到一個animal的子類,那么HTML就會變成這樣:
<a class="animal bear">bear</a>
css樣式就會變成這樣:
.animal{
    background-color: black;
    color: white;
}
.bear{
    background-color: grey;
}
不然你可以在less中使用extend,那樣你的HTML就會變得很簡單:
<a class="bear">bear</a>
less就會為:
.animal{
    background-color: black;
    color: white;
}
.bear{
    &:extend(.animal);
    background-color: grey;
}
  • 減少css大小

mixin將所有的屬性都復制到新的選擇器中,從而導致了不必要的重復。因此你可以使用extend去代替mixin將你想要用的屬性添加到新的選擇器中,從而減少css代碼。
使用mixin:

.mine{
    color: #fff;
    font-size: 16px;
}
.test1{
    .mine;
}
.test2{
    .mine;
}

編譯為:
.mine{
    color: #fff;
    font-size: 16px;
}
.test1{
    color: #fff;
    font-size: 16px;
}
.test2{
    color: #fff;
    font-size: 16px;
}

使用extend:

.mine{
    color: #fff;
    font-size: 16px;
}
.test1{
    &:extend(.mine);
}
.test2{
    &:extend(.mine);
}

編譯為:
.mine,
.test1,
.test2{
    color: #fff;
    font-size: 16px;
}
  • 組合樣式/更先進的mixin

另一種使用情況是作為mixin的一種替代方法,因為mixin只能用在建檔的選擇器,如果在HTML中有兩個不同的塊(block),但是需要應用同一個樣式,那么你就可以使用extend去鏈接兩個塊元素。

li.list >a{ ... }
button.list-style{
    &:extend(li.list>a);
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Less作為 CSS 的一種擴展,不僅完全兼容 CSS 語法,而且連新增的特性也是使用 CSS 語法,你可以在任何...
    zhangivon閱讀 585評論 0 1
  • 花了這兩天上班的空閑時間把mixins的大部分的相關內容寫完了,但是還有兩小塊內容還沒寫,預計放在下一篇當中,下一...
    程愷閱讀 2,431評論 0 1
  • <a name='html'>HTML</a> Doctype作用?標準模式與兼容模式各有什么區別? (1)、<...
    clark124閱讀 3,570評論 1 19
  • 午夜夢回。村頭的桂花樹下,披頭散發的母親,對著一只狗傻笑。 我又想我的母親了。 我不知道母親的名字,也不知道她來自...
    西川紫閱讀 813評論 5 6
  • -1- 其實,對于別人所說的緣分但憑命中注定,自己是從來都沒有相信過的。只是遇見你之后,我多么希望這說法是對的,而...
    夜落y閱讀 555評論 0 1