less @import and extend及mixin詳解

世有因果知因求果發表於2015-10-28

在less中,通過

@import (keyword) "filename"
的方式引入其他的檔案,這個keyword可以是以下6種:

  • referrence

referrence這個keyword,例如: @import (reference) "file.less"將使得file.less檔案中定義的所有mixin和class可以被使用,但是並不會把這些mixin/class編譯到最終的css檔案中

@import (reference) "styles";
.nav:extend(.nav all){};

 


將輸出styles.less中定義的.nav class的所有相關selector/rule(包括巢狀部分),這樣就可以取其所需,不需要的則不會被編譯進來!

.nav {
list-style: none outside none;
padding: 0;
}
.nav li a {
text-decoration: none;
color: #000000;
width: 100%;
display: block;
padding: 10px 0 10px 10px;
border: 1px solid #004d00;
margin-top: -1px;
}
.nav li a:hover {
color: #ffffff;
background-color: #004d00;
}
.nav li.active a {
color: #000000;
background-color: #00b300;
}
.nav li:first-child a {
border-radius: 15px 15px 0 0;
}
.nav li:last-child a {
border-radius: 0 0 15px 15px;
}

 


這個reference關鍵字對於定製類似於bootstrap這樣的前端框架為我所用也是非常有用的。 比如,你可能不需要bootstrap的其他臃腫的功能,你只希望用到bootstrap的幾個button style,怎麼辦呢?最好的辦法就是使用reference關鍵字來import BS的入口檔案bootstrap.less,隨後通過extend bootstrap定義的一些helper class或者一些mixin,來生成自己的定製semantic style集,這樣做的另外一個好處是實現了所謂semantic 的css

@import (reference) "bootstrap.less";
.btn:extend(.btn){};
.btn-colored {
.button-variant(blue;red;green);
}

 


或者可以通過直接引用bootstrap定義好的預定義class,來這樣定製一個semantic css

.btncolored {
.btn;
.btn-primary;
.btn-lg;
}

 


上述會將.btn, .btn-primary,.btn-lg都放進來,但是貌似有一些程式碼冗餘。從這裡可以看出對css屬性的分類是非常重要的:layout屬性,顏色屬性(color,background-color,border-color),尺寸屬性(font-size, line-height)

inline
inline關鍵字用於輸入和less不相容的code.雖然less接受標準的css,但是comments和一些hacks有時並不會被編譯。使用inline關鍵字來輸入一個css檔案,原封不動地輸出到編譯結果中。

less
less關鍵字強制被輸入的檔案作為一個less檔案並且被編譯

@import (less) "styles.css" 這種情況下style.css將作為less被和普通less檔案一樣重新編譯

css
css關鍵字強制@import和一個普通的css import一樣工作。比如:

@import (css) "styles.css";
The output of the preceding code is as follows in the compiled output:
@import "styles.css";

once
預設情況下,less只會import一個檔案一次(即使是你可能前後主動import了多次!)

multiple
有時,你可能希望import同一個檔案多次,則使用multiple關鍵字

p {
color: red;
}
And your Less code is as follows:
@import (multiple) "style";
@import (multiple) "style";
The preceding code will output the following CSS code:
p {
color: red;
}
p {
color: red;
}

extend關鍵詞

extend pseudo-class是一個less專有的pseudo-class,並且使用css pseudo-class一樣的語法。該extend pseduo-class將把:extend前面的selector放到被extended的selector list中去,從而繼承了被extended css selctor(class)的所有css屬性。(adds the selector to the extended selector list).將selector增加到不同的class的selector list中去將使得這個selector擁有被extended class相同的屬性。

.hyperlink{
color: blue;
&:hover {
color: red;
}
}
.other-hyperlink:extend(.hyperlink){};
將會編譯輸出(注意selector nested in .hyperlink並未被輸出!!):
.hyperlink,
.other-hyperlink {
color: blue;
}
.hyperlink:hover {
color: red;
}

 

.other-hyperlink:hover:extend(.hyperlink){};也可以使用
如果要將.hperlink中的nested rule也繼承過來必須使用

.other-hyperlink:hover:extend(.hyperlink all){};

不帶()的mixin實際上也就是一般的class,他們自然會在編譯後的檔案中輸出出來如果希望這個mixin(class)只作為在其他地方呼叫或者extend,而不會編譯自己本身形成class的,那麼最簡單的方法是在class選擇器後新增()即可extend往往用於擴充套件重用一個靜態的class,mixin則相當於函式的pattern,用於不同地方被重複使用

  • Extended vs. Mixins in Less

http://transmission.vehikl.com/less-extend/

如果你使用過less,那麼你一定用過mixin的強大功能來使得你的css更加dry(don't repeat yourself),減少冗餘,或許你可能有下面的標準button的style:

.btn { background: blue; color: white; }

 


你又希望在另外一個特定button中包含這些style,你可以使用mixins來簡單地混合那個.btn class到另外一個class中,這樣將允許您不用copy/paste就能重用那些style.

.round-button { .btn; border-radius: 4px; }

 


這麼做看起來很ok,但是如果你仔細看一下編譯後生成的css,你將發現有很多浪費空間的重複程式碼:

.btn { background: blue; color: white; } 
.round-button { background: blue; color: white; border-radius: 4px; }

 


有沒有發現編譯的結果就是將.btn類的style完全copy到round-button class中?

標準的css允許我們將selectors進行分組,所以如果我們重新清理一下程式碼你就會發現下面更好的css定義方式:

.btn, .round-button { background: blue; color: white; } 
.round-button { border-radius: 4px; } 

 


如果less必css本身要好,為什麼它卻傻到不會充分用好css的這個打包分組css style以便節省檔案空間的功能呢?

這實際上是一個對LESS的合理的抱怨,這也是為什麼很多人選擇SASS而不用less的原因之一。但是好訊息是從1.4開始,less就增加了extend功能,而這個extend功能就能有效地解決這個程式碼重複問題。

我們重寫程式碼:

.btn { background: blue; color: white; } 
.round-button { 
&:extend(.btn); 
border-radius: 4px; 
}

 


編譯以後我們就將獲得下面乾淨的輸出:

.btn, .round-button { background: blue; color: white; }
.round-button { border-radius: 4px; }

 


注意:預設情況下,nested selectors並不會被extended,比如:

.footer {
padding: 20px;
h2 { color: white; }
}
.feed { &:extend(.footer) }
上面這段程式碼編譯後將會在.feed的輸出中忽略h2

.footer, .feed { padding: 20px; }
.footer h2 { color: white; }
你可以通過增加一個all 關鍵字來強制compiler來包含所有nested selectors

.feed { &:extend(.footer all); }
編譯之後就如下面內容:

.footer, .feed { padding: 20px; }
.footer h2, feed h2 { color: white; }
你也可以使用一個特定的nested selector:

.feed { &:extend(.footer h2); }
Media Queries:
extend關鍵字只會extend 在同一個media query中包含的selectors

@media (max-width: 1024px) {
.feed { padding: 20px; }
.sig { &:extend(.feed); }
}
所以上面的程式碼是可以工作的,但是下面的程式碼卻不能work(由於.sig希望extend不在一個media query block中定義的clss)

.feed { padding: 20px; }
@media (max-width: 1024px) { .sig { &:extend(.feed); } }
既然extend就能實現如此完美的功能,我們為什麼還要使用mixin呢?

Parametric Mixins

注意:當你只是希望在多個class中共享一些靜態的style,那麼extend是一個非常好的選擇,但是minins在你需要增加一組動態的style時變得非常有用。Mixin是更高一級的抽象,類似於程式設計中的函式

我們繼續來看buttons,比如我們有以下起始的css style

.btn { 
background: #217a39; 
border: 1px solid #0f3c1c; 
border-radius: 4px; color: #fff; 
&:hover { 
    background: #3eb061; border-color: #165929; 
    }
}

這套css規則定義了一個小小的綠色button,並有一個非常酷的hover效果。

現在如果我們希望重用這個button,而同時又希望使用另外一個顏色,該怎麼辦呢?

extend在這種情況下確實無法真正幫助我們,而有參的mixins在這裡就幫上大忙了:

.btn(@color) { 
background: @color; 
border: 1px solid darken(@color, 15); 
border-radius: 4px; 
color: #fff; 
&:hover { background: lighten(@color, 10); 
border-color: darken(@color, 5);
 } 
}

使用上面的mixin,我們就能夠方便地定義一套不同的button:

.btn-success { .btn(#18682f); } 
.btn-alert { .btn(#9b6910); } 
.btn-error { .btn(#9b261a); }

 

相關文章