混入 Mixins
混入是指把已存在的樣式混入到別的樣式中烈拒。
你可以把 class
選擇器 和 id
選擇器混入到其他樣式中。例如:
.a, #b {
color: red;
}
.mixin-class {
.a();
}
.mixin-id {
#b();
}
輸出結(jié)果:
.a, #b {
color: red;
}
.mixin-class {
color: red;
}
.mixin-id {
color: red;
}
注意:當(dāng)調(diào)用 mixin 時(shí)岁歉,括號(hào)是可選的
// 下面兩種 mixin 的調(diào)用方法效果是一樣的
.a, #b {
color: red;
}
.mixin-class {
.a();
}
.mixin-class {
.a;
}
不把 Mixin 輸出到編譯后的 CSS 中
如果你想用 mixin 但又不想把它輸出到編譯結(jié)果中惶翻,在定義 mixin 的時(shí)候姑蓝,在 mixin 后面加上括號(hào)
.my-mixin {
color: black;
}
// 注意 my-other-mixin 后面加了括號(hào)
.my-other-mixin() {
background: white;
}
.class {
.my-mixin;
.my-other-mixin;
}
編譯輸出結(jié)果:
.my-mixin {
color: black;
}
//可以看到這一行并沒(méi)有輸出上面定義的 my-other-mixin. 但是下面的 .class 中卻含有 background: white;
.class {
color: black;
background: white;
}
Mixin 中使用選擇器
Mixin 中不只可以寫(xiě) css 樣式屬性,還可以包含選擇器吕粗。例如:
.my-hover-mixin() {
&:hover {
border: 1px solid red;
}
}
button {
.my-hover-mixin();
}
編譯輸出結(jié)果:
button:hover {
border: 1px solid red;
}
命名空間
如果要在更復(fù)雜的選擇器中混入屬性纺荧,可以疊加多個(gè)id或類(lèi)。
#outer {
.inner {
color: red;
}
}
.c {
#outer > .inner;
}
>
和空格都可以省略。如下
// 下面的寫(xiě)法效果是一樣的
#outer > .inner;
#outer > .inner();
#outer .inner;
#outer .inner();
#outer.inner;
#outer.inner();
這種方法的一個(gè)用途被稱(chēng)為命名空間宙暇。您可以將mixin放在id選擇器下输枯,這樣可以確保它不會(huì)與另一個(gè)庫(kù)沖突(即隔離外界干擾,避免其他樣式對(duì)該 mixin 的影響)占贫。例如:
#my-library {
.my-mixin {
color: black;
}
}
// 可以如下方法調(diào)用
.class {
#my-library > .my-mixin();
}
命名空間守衛(wèi)
如果命名空間具有保護(hù)桃熄,則僅當(dāng)保護(hù)條件返回true時(shí)才使用由其定義的mixin。命名空間保護(hù)的計(jì)算方式與mixin上的保護(hù)完全相同型奥,因此接下來(lái)兩個(gè)mixin的工作方式相同:
#namespace when (@mode=huge) {
.mixin() {/* */}
}
#namespace {
.mixin() when (@mode=huge) {/* */}
}
下面的 default
函數(shù)對(duì)于嵌套的 命名空間 和 mixin 有相同的返回值瞳收,因此如下的 mixin 永遠(yuǎn)不會(huì)執(zhí)行。因?yàn)樗哪骋粋€(gè)守衛(wèi)(即 default()
和 not(default())
)肯定是false:
#sp_1 when (default()) {
#sp_2 when (default()) {
.mixin() when not(default()) {/* */}
}
}
!important
關(guān)鍵字
在 mixin 調(diào)用之后使用 !important
關(guān)鍵字厢汹,會(huì)把 mixin 所包含的全部css屬性標(biāo)記為 !important
.
.foo (@bg: #f5f5f5, @color: #900) {
background: @bg;
color: @color;
}
.unimportant {
.foo();
}
.important {
.foo() !important;
}
輸出結(jié)果為:
.unimportant {
background: #f5f5f5;
color: #900;
}
.important {
background: #f5f5f5 !important;
color: #900 !important;
}
攜帶參數(shù)的混入
怎么傳遞參數(shù)給 mixins 呢?
Mixins 也可以攜帶參數(shù)螟深,這些參數(shù)是在選擇器調(diào)用 mixin 時(shí)傳遞給它的變量.
例如:
.border-radius(@radius) {
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
border-radius: @radius;
}
下面是我們?nèi)绾握{(diào)用該mixin:
#header {
.border-radius(4px);
}
.button {
.border-radius(6px);
}
帶參數(shù)的 mixins 可以為其參數(shù)設(shè)置默認(rèn)值:
.border-radius(@radius: 5px) {
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
border-radius: @radius;
}
這樣我們可以像下面這樣使用:
#header {
.border-radius;
}
這樣 id
為 header
的元素會(huì)有5px的邊框圓角。
也可以不給 mixin 傳遞參數(shù)烫葬。當(dāng)你想在編譯后的 CSS 中包含該 mixin 的所有屬性界弧, 卻又想隱藏某些規(guī)則集(ruleset),這會(huì)非常有用搭综。
.wrap() {
text-wrap: wrap;
white-space: -moz-pre-wrap;
white-space: pre-wrap;
word-wrap: break-word;
}
pre { .wrap }
編譯后的輸出結(jié)果為:
// 定義的 .wrap() 這個(gè) mixin夹纫, 因?yàn)?.wrap 后面加了括號(hào),這個(gè)mixin 并沒(méi)有輸出到css中
pre {
text-wrap: wrap;
white-space: -moz-pre-wrap;
white-space: pre-wrap;
word-break: break-word;
}
攜帶多個(gè)參數(shù)的 mixin
多個(gè)參數(shù)之間用 逗號(hào)
或 分號(hào)
隔開(kāi)设凹,推薦用 分號(hào)
. 逗號(hào)有兩重意思,它可以被解釋為 mixin參數(shù)的分隔符 或者是 CSS列表分隔符
使用逗號(hào)作為 mixin 參數(shù)分隔符時(shí),而 mixin 的每一個(gè)參數(shù)又是需要用逗號(hào)分開(kāi)的列表茅姜,這將不可能實(shí)現(xiàn)闪朱。另一方面,如果編譯器在調(diào)用或聲明 mixin 的地方發(fā)現(xiàn)至少一個(gè) 分號(hào) 钻洒,編譯器就會(huì)認(rèn)為所有的參數(shù)將以 分號(hào) 分隔奋姿,所有的逗號(hào)都是css列表:
- 兩個(gè)參數(shù),每個(gè)參數(shù)是逗號(hào)分隔的列表:
.name(1, 2, 3; something, else)
. - 三個(gè)參數(shù)素标,每個(gè)參數(shù)都是一個(gè)數(shù)字:
.name(1, 2, 3)
. - 使用偽分號(hào)創(chuàng)建一個(gè)包含逗號(hào)分隔css列表的參數(shù)的mixin調(diào)用:
.name(1, 2, 3;)
. - 逗號(hào)分隔默認(rèn)值:
.name(@param1: red, blue;)
.
使用相同的名稱(chēng)和參數(shù)數(shù)量定義多個(gè) mixins 是允許的称诗。LESS 會(huì)使用所有 可以使用的 css屬性。記住如下mixin編譯規(guī)則
:
如果以 .mixin(green)
這樣只攜帶一個(gè)參數(shù)的方式使用這多個(gè)相同名稱(chēng)的 mixin头遭,則所有相同名稱(chēng)的 mixins 且參數(shù)列表中只含有該必填參數(shù)寓免,其他參數(shù)都為可選的 mixins 中所包含的全部 css 樣式合并起來(lái),賦予給調(diào)用這個(gè)只傳了一個(gè)必傳參數(shù)的mixin的選擇器:
// 定義第 1 個(gè) .mixin 混入函數(shù)
.mixin(@color) { // 這里的 color 參數(shù)在調(diào)用 .mixin 時(shí)是必傳的计维,因?yàn)闆](méi)有給 color 設(shè)置默認(rèn)顏色值
color-1: @color;
}
// 定義第 2 個(gè) .mixin 混入函數(shù)袜香,它和上一個(gè)混入函數(shù)同名
.mix(@color; @padding: 2) { // 這里的 color 也是必傳的。padding參數(shù)是選填的鲫惶,因?yàn)橛心J(rèn)值
color-2: @color;
padding-2: @padding;
}
// 定義第 3 個(gè) .mixin 混入函數(shù)蜈首,它和第1、2個(gè)混入函數(shù)同名
.mixin(@color; @padding; @margin: 2) { // 這里的 color 是必傳的,需要注意的是欢策,padding也是必傳的吆寨,
// 和1、2兩個(gè) mixin 不同的是踩寇,這個(gè) mixin 有2個(gè)必傳參數(shù)啄清,
// margin 參數(shù)可以省略,因?yàn)橛心J(rèn)值
color-3: @color;
padding-3: @padding;
margin: @margin @margin @margin @margin;
}
.some .selector div {
.mixin(#008000); // 這里只傳入了 color 這一個(gè)必填參數(shù)姑荷。注意看下面編譯的結(jié)果
}
最終編譯輸出的結(jié)果為:
.some .selector div {
color-1: #008000;
color-2: #008000;
padding-2: 2;
}
上面的編譯結(jié)果盒延,是因?yàn)樵谡{(diào)用同名的 mixin 函數(shù) .mixin
時(shí),只傳入了一個(gè)參數(shù) color
,我們逐步看一下最終的編譯結(jié)果是怎么出來(lái)的鼠冕。
- 在第一個(gè)
.mixin
中添寺,參數(shù)@color
是必傳的,根據(jù)上面的mixin編譯規(guī)則
,該 mixin 中包含的 css 樣式最終會(huì)編譯進(jìn)調(diào)用它的選擇器中懈费。 - 在第二個(gè)
.mixin
中计露,參數(shù)@color
是必傳的,@padding
是可省略的憎乙,因此該 mixin 中只有@color
一個(gè)必傳參數(shù)票罐,根據(jù)mixin編譯規(guī)則
,該 mixin 中包含的 css 樣式最終也會(huì)編譯進(jìn)調(diào)用它的選擇器中泞边。 - 在第三個(gè)
.mixin
中该押,參數(shù)@color
@padding
都是必傳的,根據(jù)mixin編譯規(guī)則
阵谚,不符合只有@color
這一個(gè)必傳參數(shù)的原則蚕礼,因此該 mixin 中的所有樣式 都不會(huì) 編譯進(jìn)輸出結(jié)果中。
命名參數(shù)
mixin 不只可以通過(guò)參數(shù)位置來(lái)傳遞實(shí)參梢什,可以通過(guò)參數(shù)名稱(chēng)來(lái)給它傳遞實(shí)參奠蹬。任何的 mixin 形參都可以通過(guò)指定形參名稱(chēng)來(lái)給它傳遞實(shí)參,而不依賴(lài)于定義該 mixin 時(shí)的形參順序:
.mixin(@color: black; @margin: 10px; @padding: 20px) {
color: @color;
margin: @margin;
padding: @padding;
}
.class1 {
.mixin(@margin: 20px; @color: #33acfe); // 調(diào)用 mixin 時(shí)通過(guò)指定形參名稱(chēng)傳遞實(shí)參值嗡午,并沒(méi)有按照定義
// mixin 時(shí)的順序 先 color 其次 margin 最后 padding 的
// 順序來(lái)傳值
}
.class2 {
.mixin(#efca44; @padding: 40px); // 按原有的形參順序傳值時(shí)囤躁,可以不指定形參名
}
@arguments
變量
@arguments
在 mixins 中有獨(dú)特的含義,它包含了傳入的所有參數(shù)荔睹,當(dāng)該 mixin 被調(diào)用時(shí)狸演,如果不想單獨(dú)的寫(xiě)每個(gè)參數(shù)時(shí)會(huì)比較有用。
.box-shadow(@x: 0; @y: 0; @blur: 1px; @color: #000) {
-webkit-box-shadow: @arguments;
-moz-box-shadow: @arguments;
box-shadow: @arguments;
}
.big-block {
.box-shadow(2px; 5px);
}
編譯結(jié)果如下:
.big-block {
-webkit-box-shadow: 2px 5px 1px #000;
-moz-box-shadow: 2px 5px 1px #000;
box-shadow: 2px 5px 1px #000;
}
高級(jí)參數(shù) 和 @rest
變量
當(dāng)一個(gè) mixin 攜帶有可變數(shù)量的參數(shù)時(shí)僻他,可以使用 ...
在變量名后面使用該操作符將會(huì)把這些參數(shù)賦給變量
.mixin(...) { // 匹配第 0 - N 個(gè) arguments
.mixin() { // 匹配第 0 個(gè) arguments
.mixin(@a: 1) { // 匹配第 0 -1 個(gè) arguments
.mixin(@a: 1; ...) { // 匹配 0 - N 個(gè) arguments
.mixin(@a; ...) { // 匹配 1 - N 個(gè) arguments
此外:
.mixin(@a; @rest...) {
// @rest 綁定到 @a 之后的所有參數(shù)
// @arguments 綁定到所有參數(shù)
}
模式匹配
有時(shí)候我們想根據(jù)傳入的參數(shù)改變一個(gè) mixin 的行為严沥。讓我們從一個(gè)基礎(chǔ)的例子開(kāi)始:
.mixin(@s; @color) {...}
.class {
.mixin(@switch; #888);
}
我們想根據(jù) @switch
的不同讓 mixin 表現(xiàn)出不同的結(jié)果。我們可以如下定義 .mixin
:
.mixin(dark; @color) {
color: darken(@color, 10%);
}
.mixin(light; @color) {
color: lighten(@color, 10%);
}
.mixin(@_; @color) {
display: block;
}
此時(shí)如果我們編譯下面的樣式:
@switch: light;
.class {
.mixin(@switch; #888);
}
編譯得到的CSS結(jié)果為:
.class {
color: #a2a2a2;
display: block;
}
給 .mixin
傳入 color 的地方會(huì)變亮中姜。如果 @switch
的值為 dark
, 結(jié)果就是一個(gè)比較暗的顏色消玄。我們逐步分析是怎么編譯出來(lái)的:
- 第一個(gè) mixin 不匹配跟伏,因?yàn)榈谝粋€(gè)參數(shù)為
dark
- 第二個(gè) mixin 匹配,因?yàn)樗牡谝粋€(gè)參數(shù)為
light
- 第三個(gè) mixin 匹配翩瓜,因?yàn)樗牡谝粋€(gè)參數(shù)接受任意值
只有匹配的 mixin 才會(huì)被采用受扳。變量匹配并綁定到任意值。變量以外的任何內(nèi)容都只和等于自身的值匹配兔跌。
我們也可以匹配參數(shù)個(gè)數(shù)勘高,看下面的例子:
.mixin(@a) {
color: @a;
}
.mixin(@a; @b) {
color: fade(@a; @b);
}
如果我們調(diào)用 .mixin
時(shí)只傳入了一個(gè)參數(shù), 我們會(huì)得到第一個(gè) .mixin 的編譯結(jié)果.如果傳入了兩個(gè)參數(shù),就會(huì)得到第二個(gè) .mixin 的編譯結(jié)果坟桅,即 @a
變?yōu)?@b
.
作為函數(shù)的 mixins
從 mixins 中返回變量或 mixins
在 mixin 中定義的變量和 mixin 是可見(jiàn)的华望,可以在調(diào)用者的作用域中使用。只有一個(gè)例外仅乓,如果調(diào)用方包含同名變量(包括由另一個(gè) mixin 調(diào)用定義的變量)赖舟,則不復(fù)制變量。只有調(diào)用方本地作用域中存在的變量才受保護(hù)夸楣。從父作用域繼承的變量將被重寫(xiě)(覆蓋)宾抓。
例如:
.mixin() {
@width: 100%;
@height: 200px;
}
.caller {
.mixin();
width: @width;
height: @height;
}
編譯結(jié)果為:
.caller {
width: 100%;
height: 200px;
}
因此,mixin中定義的變量可以作為其返回值豫喧。這允許我們創(chuàng)建一個(gè)可以像函數(shù)一樣使用的mixin
例如:
.average(@x, @y) {
@average: ((@x + @y) / 2);
}
div {
.average(16px, 50px); // 調(diào)用 mixin
padding: @average;
}
編譯結(jié)果為:
div {
padding: 33px;
}
在調(diào)用者作用域內(nèi)定義的變量不會(huì)被覆蓋石洗。然而,在調(diào)用者父級(jí)作用域中定義的變量將不被保護(hù)且可以被覆蓋:
.mixin() {
@size: in-mixin;
@defineOnlyInMixin: in-mixin;
}
.class {
margin: @size @defineOnlyInMixin;
.mixin();
}
@size: globaly-defined-value; // 調(diào)用者父作用域 - 無(wú)保護(hù)
編譯結(jié)果為:
.class {
margin: in-mixin in-mixin;
}
最后紧显, mixin 中定義的 mixin 也會(huì)被當(dāng)做返回值
.unlock(@value) { // 父級(jí) mixin
.doSomething() { // 子級(jí) mixin
declaration: @value;
}
}
讲衫、#namespace {
.unlock(5); // unlock 做一些混入
.doSomething(); // 子級(jí) mixin 被拷貝到這里且可用
}
編譯結(jié)果
#namespace {
declaration: 5;
}