概觀

編輯「概觀」的 markdown 原始碼

深入瞭解 LESS 語言的功能。請參閱 概觀 以快速瞭解 Less。

如需深入瞭解如何安裝和設定 Less 環境,以及 Less 開發文件,請參閱:使用 Less.js


變數

編輯「變數」的標記原始檔

在單一位置控制常用值。

概觀

在您的樣式表中,看到同一個值重複出現數十次(如果不是數百次)是很常見的

a,
.link {
  color: #428bca;
}
.widget {
  color: #fff;
  background: #428bca;
}

變數讓您的程式碼更容易維護,因為它提供一種方式,讓您可以從單一位置控制這些值

// Variables
@link-color:        #428bca; // sea blue
@link-color-hover:  darken(@link-color, 10%);

// Usage
a,
.link {
  color: @link-color;
}
a:hover {
  color: @link-color-hover;
}
.widget {
  color: #fff;
  background: @link-color;
}

變數內插

上述範例著重於使用變數來控制CSS 規則中的值,但它們也可以用於其他地方,例如選擇器名稱、屬性名稱、URL 和 @import 陳述式。

選擇器

v1.4.0

// Variables
@my-selector: banner;

// Usage
.@{my-selector} {
  font-weight: bold;
  line-height: 40px;
  margin: 0 auto;
}

編譯為

.banner {
  font-weight: bold;
  line-height: 40px;
  margin: 0 auto;
}

URL

// Variables
@images: "../img";

// Usage
body {
  color: #444;
  background: url("@{images}/white-sand.png");
}

匯入陳述式

v1.4.0

語法:@import "@{themes}/tidal-wave.less";

請注意,在 v2.0.0 之前,只考慮在根或當前範圍中宣告的變數,且在尋找變數時只考慮當前檔案和呼叫檔案。

範例

// Variables
@themes: "../../src/themes";

// Usage
@import "@{themes}/tidal-wave.less";

屬性

v1.6.0

@property: color;

.widget {
  @{property}: #0ee;
  background-@{property}: #999;
}

編譯為

.widget {
  color: #0ee;
  background-color: #999;
}

變數變數

在 Less 中,你可以使用另一個變數來定義變數的名稱。

@primary:  green;
@secondary: blue;

.section {
  @color: primary;

  .element {
    color: @@color;
  }
}

編譯為

.section .element {
  color: green;
}

延遲評估

變數不一定要在使用前宣告。

有效的 Less 片段

.lazy-eval {
  width: @var;
}

@var: @a;
@a: 9%;

這也是有效的 Less

.lazy-eval {
  width: @var;
  @a: 9%;
}

@var: @a;
@a: 100%;

編譯為

.lazy-eval {
  width: 9%;
}

在兩次定義變數時,會使用變數的最後一個定義,從當前範圍向上搜尋。這類似於 css 本身,其中定義中的最後一個屬性用於決定值。

例如

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

編譯為

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

基本上,每個範圍都有「最終」值,類似於瀏覽器中的屬性,例如使用自訂屬性的範例

.header {
  --color: white;
  color: var(--color);  // the color is black
  --color: black;
}

這表示,與其他 CSS 預處理語言不同,Less 變數的行為非常類似於 CSS。

屬性當作變數 (新增功能)

v3.0.0

你可以使用 $prop 語法輕鬆地將屬性視為變數。有時候這可以讓你的程式碼更精簡。

.widget {
  color: #efefef;
  background-color: $color;
}

編譯為

.widget {
  color: #efefef;
  background-color: #efefef;
}

請注意,Less 會像變數一樣選擇目前/父範圍內的最後一個屬性作為「最後」值。

.block {
  color: red; 
  .inner {
    background-color: $color; 
  }
  color: blue;  
} 

編譯為

.block {
  color: red; 
  color: blue;  
} 
.block .inner {
  background-color: blue; 
}

預設變數

我們有時會收到預設變數的要求,也就是在變數尚未設定時設定一個變數。這個功能並非必要,因為你可以透過在定義後覆寫變數輕鬆地做到這一點。

例如

// library
@base-color: green;
@dark-color: darken(@base-color, 10%);

// use of library
@import "library.less";
@base-color: red;

這運作良好,因為 延遲載入 - @base-color 已被覆寫,而 @dark-color 是深紅色。


父選擇器

編輯「parent-selectors」的 markdown 原始碼

使用 & 參照父選擇器

& 運算子代表 巢狀規則 的父選取器,最常使用在將修改類別或偽類別套用至現有選取器時

a {
  color: blue;
  &:hover {
    color: green;
  }
}

結果為

a {
  color: blue;
}

a:hover {
  color: green;
}

請注意,若沒有 &,上述範例會產生 a :hover 規則(後代選取器,用於符合 <a> 標籤內的滑鼠游標移入元素),這通常不是我們使用巢狀 :hover 時想要的。

「父選取器」運算子有各種用途。基本上,只要您需要巢狀規則的選取器以非預設方式組合時,都可以使用它。例如,& 的另一個典型用途是產生重複的類別名稱

.button {
  &-ok {
    background-image: url("ok.png");
  }
  &-cancel {
    background-image: url("cancel.png");
  }

  &-custom {
    background-image: url("custom.png");
  }
}

輸出

.button-ok {
  background-image: url("ok.png");
}
.button-cancel {
  background-image: url("cancel.png");
}
.button-custom {
  background-image: url("custom.png");
}

多個 &

& 可以在選取器中出現多次。這使得您可以在不重複其名稱的情況下重複參照父選取器。

.link {
  & + & {
    color: red;
  }

  & & {
    color: green;
  }

  && {
    color: blue;
  }

  &, &ish {
    color: cyan;
  }
}

將輸出

.link + .link {
  color: red;
}
.link .link {
  color: green;
}
.link.link {
  color: blue;
}
.link, .linkish {
  color: cyan;
}

請注意,& 代表所有父選取器(不只是最近的祖先),因此以下範例

.grand {
  .parent {
    & > & {
      color: red;
    }

    & & {
      color: green;
    }

    && {
      color: blue;
    }

    &, &ish {
      color: cyan;
    }
  }
}

結果為

.grand .parent > .grand .parent {
  color: red;
}
.grand .parent .grand .parent {
  color: green;
}
.grand .parent.grand .parent {
  color: blue;
}
.grand .parent,
.grand .parentish {
  color: cyan;
}

變更選取器順序

將選取器置於繼承的(父)選取器之前會很有用。這可透過將 & 放在目前選取器之後來完成。例如,在使用 Modernizr 時,您可能想要根據支援的功能指定不同的規則

.header {
  .menu {
    border-radius: 5px;
    .no-borderradius & {
      background-image: url('images/button-background.png');
    }
  }
}

選擇器 .no-borderradius & 會將 .no-borderradius 加到其父層 .header .menu,在輸出時形成 .no-borderradius .header .menu

.header .menu {
  border-radius: 5px;
}
.no-borderradius .header .menu {
  background-image: url('images/button-background.png');
}

組合爆炸

& 也可用於產生逗號分隔清單中選擇器的所有可能排列組合

p, a, ul, li {
  border-top: 2px dotted #366;
  & + & {
    border-top: 0;
  }
}

這會擴充到指定元素的所有可能(16)種組合

p,
a,
ul,
li {
  border-top: 2px dotted #366;
}
p + p,
p + a,
p + ul,
p + li,
a + p,
a + a,
a + ul,
a + li,
ul + p,
ul + a,
ul + ul,
ul + li,
li + p,
li + a,
li + ul,
li + li {
  border-top: 0;
}

@import At-Rules

編輯「imports」的 markdown 原始碼

從其他樣式表匯入樣式

在標準 CSS 中,@import at-rules 必須先於所有其他類型的規則。但 Less 不在乎你把 @import 陳述式放在哪裡。

範例

.foo {
  background: #900;
}
@import "this-is-valid.less";

檔案副檔名

@import 陳述式可能會根據檔案副檔名而由 Less 以不同的方式處理

  • 如果檔案具有 .css 副檔名,它將被視為 CSS,且 @import 陳述會保持原樣(請參閱下列 內嵌選項)。
  • 如果它具有 任何其他副檔名,它將被視為 Less 並匯入。
  • 如果它沒有副檔名,將附加 .less,且它將作為匯入的 Less 檔案包含在內。

範例

@import "foo";      // foo.less is imported
@import "foo.less"; // foo.less is imported
@import "foo.php";  // foo.php imported as a Less file
@import "foo.css";  // statement left in place, as-is

下列選項可用於覆寫此行為。

匯入選項

Less 提供 CSS @import CSS at-rule 的多個擴充功能,以提供更多彈性,讓您能對外部檔案進行處理。

語法:@import (關鍵字) "檔名";

已實作下列匯入選項

  • reference:使用 Less 檔案,但不要輸出它
  • inline:在輸出中包含原始檔案,但不要處理它
  • less:將檔案視為 Less 檔案,不論檔案副檔名為何
  • css:將檔案視為 CSS 檔案,不論檔案副檔名為何
  • once:只包含檔案一次(這是預設行為)
  • multiple:包含檔案多次
  • optional:在找不到檔案時繼續編譯

每個 @import 可以有多個關鍵字,您必須使用逗號來分隔關鍵字

範例:@import (optional, reference) "foo.less";

reference

使用 @import (reference) 匯入外部檔案,但除非有參照,否則不會將匯入的樣式新增至已編譯的輸出。

已發布 v1.5.0

範例:@import (reference) "foo.less";

想像一下,reference 會在匯入的檔案中,使用 reference flag 標記每個 at-rule 和選取器,正常匯入,但當產生 CSS 時,不會輸出「reference」選取器(以及僅包含 reference 選取器的任何媒體查詢)。除非 reference 樣式用作 mixinsextended,否則 reference 樣式不會顯示在您產生的 CSS 中。

此外,reference 會根據使用哪種方法(mixin 或 extend)產生不同的結果

  • extend:當選取器被延伸時,只有新的選取器會被標記為 未參照,且會在 reference @import 陳述的位置中拉入。
  • mixins:當 reference 樣式用作 隱含 mixin 時,其規則會被混合,標記為「未參照」,並正常顯示在參照位置。

reference 範例

這讓您可以從像 Bootstrap 這樣的程式庫中,僅拉入特定、目標的樣式,方法如下

.navbar:extend(.navbar all) {}

您將僅從 Bootstrap 中拉入 .navbar 相關的樣式。

內嵌

使用 @import (inline) 來包含外部檔案,但不要處理它們。

已發布 v1.5.0

範例:@import (inline) "not-less-compatible.css";

當 CSS 檔案可能與 Less 不相容時,你會使用這個;這是因為儘管 Less 支援大多數已知的標準 CSS,它在某些地方不支援註解,也不支援所有已知的 CSS hack,而不會修改 CSS。

因此你可以使用這個來在輸出中包含檔案,以便所有 CSS 都會在一個檔案中。

less

使用 @import (less) 來將匯入的檔案視為 Less,不論檔案副檔名為何。

已發布 v1.4.0

範例

@import (less) "foo.css";

css

使用 @import (css) 來將匯入的檔案視為一般 CSS,不論檔案副檔名為何。這表示匯入陳述會保持原樣。

已發布 v1.4.0

範例

@import (css) "foo.less";

輸出

@import "foo.less";

一次

@import 陳述的預設行為。這表示檔案只會匯入一次,而後續針對該檔案的匯入陳述會被忽略。

已發布 v1.4.0

這是 @import 陳述的預設行為。

範例

@import (once) "foo.less";
@import (once) "foo.less"; // this statement will be ignored

多重

使用 @import (multiple) 允許匯入多個同名的檔案。這是與 once 相反的行為。

已發布 v1.4.0

範例

// file: foo.less
.a {
  color: green;
}
// file: main.less
@import (multiple) "foo.less";
@import (multiple) "foo.less";

輸出

.a {
  color: green;
}
.a {
  color: green;
}

optional

使用 @import (optional) 僅在檔案存在時允許匯入。如果沒有 optional 關鍵字,Less 會擲回 FileError,並在匯入找不到的檔案時停止編譯。

已發布 v2.3.0


延伸

編輯「延伸」的標記原始碼

延伸是一個 Less 偽類別,它會將其所置入的選擇器與符合其引用的選擇器合併。

已發布 v1.4.0

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

在上述規則集中,:extend 選擇器會將「延伸選擇器」(nav ul) 套用至 .inline 類別.inline 類別出現的任何地方。宣告區塊將保持原樣,但不會有任何延伸參考 (因為延伸不是 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 - 延伸在輸出之前會被移除,而選擇器區塊則保留原樣。如果該區塊中未放入任何屬性,則會從輸出中移除(但延伸仍可能會影響其他選擇器)。

延伸語法

延伸會附加到選擇器或置入規則集中。它看起來像一個偽類別,其選擇器參數後方可選擇性地加上關鍵字 all

範例

.a:extend(.b) {}

// the above block does the same thing as the below block
.a {
  &:extend(.b);
}
.c:extend(.d all) {
  // extends all instances of ".d" e.g. ".x.d" or ".d.x"
}
.c:extend(.d) {
  // extends only instances where the selector will be output as just ".d"
}

它可以包含一個或多個要延伸的類別,並以逗號分隔。

範例

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

// the above and the below do the same thing
.e:extend(.f, .g) {}

延伸附加到選擇器

附加到選擇器的延伸看起來像一個以選擇器為參數的普通偽類別。一個選擇器可以包含多個延伸子句,但所有延伸都必須在選擇器的結尾。

  • 選擇器後的延伸: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 關鍵字。規則集中有多個選擇器的 extend

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

規則集中的 Extend

Extend 可以使用 &:extend(selector) 語法放入規則集的主體中。將 extend 放入主體中是將其放入該規則集的每個單一選擇器的捷徑。

主體中的 Extend

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

與在每個選擇器後加入 Extend 完全相同

pre:hover:extend(div pre),
.some-class:extend(div pre) {}

延伸巢狀選擇器

Extend 能夠比對巢狀選擇器。Less 遵循

範例

.bucket {
  tr { // nested ruleset with target selector
    color: blue;
  }
}
.some-class:extend(.bucket tr) {} // nested ruleset is recognized

輸出

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

基本上,Extend 會查看已編譯的 CSS,而不是原始的 Less。

範例

.bucket {
  tr & { // nested ruleset with target selector
    color: blue;
  }
}
.some-class:extend(tr .bucket) {} // nested ruleset is recognized

輸出

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

使用 Extend 進行完全比對

Extend 預設會尋找選擇器之間的完全比對。選擇器是否使用開頭星號並不重要。兩個 nth 表達式具有相同意義並不重要,它們需要具有相同的形式才能比對。唯一的例外是屬性選擇器中的引號,Less 知道它們具有相同的意義並會比對它們。

範例

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

開頭的星號很重要。選擇器 *.class.class 是等效的,但 extend 將不會匹配它們

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

輸出

*.class {
  color: blue;
}

偽類的順序很重要。選擇器 link:hover:visitedlink:visited:hover 匹配相同的元素集,但 extend 將它們視為不同

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

輸出

link:hover:visited {
  color: blue;
}

nth 表達式

nth 表達式的形式很重要。nth 表達式 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;
}
[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 關鍵字時,它會告訴 Less 將該選擇器作為另一個選擇器的一部分進行匹配。選擇器將被複製,然後選擇器的匹配部分將被 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;
}

您可以將這種操作模式視為本質上執行非破壞性搜尋和替換。

使用 Extend 進行選擇器內插

Extend 無法 匹配帶有變數的選擇器。如果選擇器包含變數,extend 將忽略它。

不過,extend 可以附加到內插選擇器。

帶有變數的選擇器不會匹配

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

而帶有變數的 extend 在目標選擇器中不匹配任何內容

.bucket {
  color: blue;
}
.some-class:extend(@{variable}) {} // interpolated selector matches nothing
@variable: .bucket;

以上兩個範例編譯成

.bucket {
  color: blue;
}

不過,附加到內插選擇器的 :extend 有效

.bucket {
  color: blue;
}
@{variable}:extend(.bucket) {}
@variable: .selector;

編譯成

.bucket, .selector {
  color: blue;
}

範圍 / @media 內的 Extend

目前,@media 宣告中的 :extend 只會匹配同一個媒體宣告中的選擇器

@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 宣告中的選擇器

@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;
  }
}

重複偵測

目前沒有重複偵測。

範例

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

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

輸出

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

Extend 的使用案例

經典使用案例

經典使用案例是避免新增基本類別。例如,如果你有

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

如果您想要一個覆寫背景顏色的動物子類型,您有兩個選擇,首先變更您的 HTML

<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;
}

縮小 CSS 大小

Mixins 將所有屬性複製到一個選取器中,這可能會導致不必要的重複。因此,您可以使用 extends 代替 mixins,將選取器移到您想要使用的屬性,這會產生較少的 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;
}

範例 (使用 extends)

.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;
}

結合樣式 / 一個更進階的 mixin

另一個使用案例是作為 mixin 的替代方案 - 因為 mixins 只能用於簡單的選取器,如果您有兩個不同的 HTML 區塊,但需要對兩個區塊套用相同的樣式,您可以使用 extends 來關聯兩個區域。

範例

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

合併屬性

編輯「merge」的 markdown 原始碼

合併屬性

merge 功能允許將多個屬性的值聚合到單一屬性下的逗號或空格分隔清單中。merge 對於背景和轉換等屬性非常有用。

逗號

附加逗號的屬性值

已發布 v1.5.0

範例

.mixin() {
  box-shadow+: inset 0 0 10px #555;
}
.myclass {
  .mixin();
  box-shadow+: 0 0 20px black;
}

輸出

.myclass {
  box-shadow: inset 0 0 10px #555, 0 0 20px black;
}

空格

附加空格的屬性值

已發布 v1.7.0

範例

.mixin() {
  transform+_: scale(2);
}
.myclass {
  .mixin();
  transform+_: rotate(15deg);
}

輸出

.myclass {
  transform: scale(2) rotate(15deg);
}

為避免任何意外的合併,merge 要求在每個合併宣告中明確標示 ++_ 旗標。


混合

編輯「混合」的標記來源

從現有樣式中「混合」屬性

您可以混合類別選擇器和 ID 選擇器,例如

.a, #b {
  color: red;
}
.mixin-class {
  .a();
}
.mixin-id {
  #b();
}

將產生

.a, #b {
  color: red;
}
.mixin-class {
  color: red;
}
.mixin-id {
  color: red;
}

傳統上,混合呼叫中的括號是可選的,但可選括號已不建議使用,且在未來的版本中將會強制使用。

.a(); 
.a;    // currently works, but deprecated; don't use
.a (); // white-space before parentheses is also deprecated

帶括號的混合

如果您想要建立一個混入,但您不希望該混入出現在您的 CSS 輸出中,請在混入定義後加上括號。

.my-mixin {
  color: black;
}
.my-other-mixin() {
  background: white;
}
.class {
  .my-mixin();
  .my-other-mixin();
}

輸出

.my-mixin {
  color: black;
}
.class {
  color: black;
  background: white;
}

混入中的選擇器

混入不只能包含屬性,它們也可以包含選擇器。

例如

.my-hover-mixin() {
  &:hover {
    border: 1px solid red;
  }
}
button {
  .my-hover-mixin();
}

輸出

button:hover {
  border: 1px solid red;
}

命名空間

如果您想要在更複雜的選擇器中混入屬性,您可以堆疊多個 ID 或類別。

#outer() {
  .inner {
    color: red;
  }
}

.c {
  #outer.inner();
}

注意:舊版 Less 語法允許在命名空間和混入之間使用 > 和空白。此語法已棄用,可能會被移除。目前,這些語法會執行相同的工作。

#outer > .inner(); // deprecated
#outer .inner();   // deprecated
#outer.inner();    // preferred

像這樣為您的混入加上命名空間可以減少與其他函式庫混入或使用者混入的衝突,但也可以用來「整理」混入群組。

範例

#my-library {
  .my-mixin() {
    color: black;
  }
}
// which can be used like this
.class {
  #my-library.my-mixin();
}

受保護的命名空間

如果命名空間有保護,則只有在保護條件回傳 true 時,才會使用由它定義的混入。命名空間保護的評估方式與混入保護完全相同,因此以下兩個混入運作方式相同

#namespace when (@mode = huge) {
  .mixin() { /* */ }
}

#namespace {
  .mixin() when (@mode = huge) { /* */ }
}

假設 default 函數對所有巢狀命名空間和混入都具有相同的值。以下混入永遠不會被評估;它的其中一個保護保證為 false

#sp_1 when (default()) {
  #sp_2 when (default()) {
    .mixin() when not(default()) { /* */ }
  }
}

!important 關鍵字

在 mixin 呼叫後使用 !important 關鍵字,將其繼承的所有屬性標記為 !important

範例

.foo (@bg: #f5f5f5, @color: #900) {
  background: @bg;
  color: @color;
}
.unimportant {
  .foo();
}
.important {
  .foo() !important;
}

結果

.unimportant {
  background: #f5f5f5;
  color: #900;
}
.important {
  background: #f5f5f5 !important;
  color: #900 !important;
}

參數化 Mixin

編輯「mixins-parametric」的標記原始碼

如何將參數傳遞給 mixin

Mixin 也可以接受參數,這些參數是在混入區塊選擇器時傳遞給它的變數。

例如

.border-radius(@radius) {
  -webkit-border-radius: @radius;
     -moz-border-radius: @radius;
          border-radius: @radius;
}

以下是如何將它混入各種規則集

#header {
  .border-radius(4px);
}
.button {
  .border-radius(6px);
}

參數化 Mixin 的參數也可以有預設值

.border-radius(@radius: 5px) {
  -webkit-border-radius: @radius;
     -moz-border-radius: @radius;
          border-radius: @radius;
}

現在我們可以像這樣呼叫它

#header {
  .border-radius();
}

它將會包含一個 5px 的邊框半徑。

您也可以使用不接受參數的參數化 Mixin。如果您想要從 CSS 輸出中隱藏規則集,但想要將其屬性包含在其他規則集中,這會很有用

.wrap() {
  text-wrap: wrap;
  white-space: -moz-pre-wrap;
  white-space: pre-wrap;
  word-wrap: break-word;
}

pre { .wrap() }

輸出結果如下

pre {
  text-wrap: wrap;
  white-space: -moz-pre-wrap;
  white-space: pre-wrap;
  word-wrap: break-word;
}

參數分隔符號

參數目前使用分號逗號分隔。

最初,參數只使用逗號分隔,但後來新增了分號,以支援將逗號分隔的清單值傳遞給單一參數。

注意:自 Less 4.0 起,您可以使用括號轉義 [~()] 包裹清單值,例如 .name(@param1: ~(red, blue))。這類似於引號轉義語法:~"quote"。這可能會讓您的程式碼庫中不再需要分號分隔符號。

範例

  • 兩個引數,且每個引數都包含以逗號分隔的清單:.name(1, 2, 3; something, else)
  • 三個引數,且每個引數都包含一個數字:.name(1, 2, 3)
  • 使用一個虛擬分號來建立一個混入呼叫,其中一個引數包含一個以逗號分隔的 CSS 清單:.name(1, 2, 3;)注意:如果尾隨分號看起來很奇怪,您可能會偏好:.name(~(1, 2, 3))
  • 撰寫以逗號分隔的預設值的各種方法
    • @param-values: red, blue; .name(@param1: @param-values).
    • .name(@param1: red, blue;)
    • .name(@param1: ~(red, blue))

混入重載

定義多個具有相同名稱和參數數量的混入是合法的。Less 將使用所有適用混入的屬性。如果您使用一個參數的混入,例如 .mixin(green);,則將使用具有完全一個強制參數的所有混入的屬性

.mixin(@color) {
  color-1: @color;
}
.mixin(@color, @padding: 2) {
  color-2: @color;
  padding-2: @padding;
}
.mixin(@color, @padding, @margin: 2) {
  color-3: @color;
  padding-3: @padding;
  margin: @margin @margin @margin @margin;
}
.some .selector div {
  .mixin(#008000);
}

編譯成

.some .selector div {
  color-1: #008000;
  color-2: #008000;
  padding-2: 2;
}

命名參數

混入參考可以依據參數名稱而非僅位置提供參數值。任何參數都可以依據其名稱來參考,而且它們不需要以任何特定順序出現

.mixin(@color: black; @margin: 10px; @padding: 20px) {
  color: @color;
  margin: @margin;
  padding: @padding;
}
.class1 {
  .mixin(@margin: 20px; @color: #33acfe);
}
.class2 {
  .mixin(#efca44; @padding: 40px);
}

編譯成

.class1 {
  color: #33acfe;
  margin: 20px;
  padding: 20px;
}
.class2 {
  color: #efca44;
  margin: 10px;
  padding: 40px;
}

@arguments 變數

@arguments 在 mixin 內部具有特殊意義,它包含呼叫 mixin 時傳遞的所有參數。如果您不想處理個別參數,這會很有用

.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);
}

結果如下

.big-block {
  -webkit-box-shadow: 2px 5px 1px #000;
     -moz-box-shadow: 2px 5px 1px #000;
          box-shadow: 2px 5px 1px #000;
}

進階參數和 @rest 變數

如果您希望 mixin 採用變數數量的參數,可以使用 ...。在變數名稱後使用此功能會將這些參數指派給變數。

.mixin(...) {        // matches 0-N arguments
.mixin() {           // matches exactly 0 arguments
.mixin(@a: 1) {      // matches 0-1 arguments
.mixin(@a: 1, ...) { // matches 0-N arguments
.mixin(@a, ...) {    // matches 1-N arguments

此外

.mixin(@a, @rest...) {
   // @rest is bound to arguments after @a
   // @arguments is bound to all arguments
}

模式比對

有時,您可能想要根據傳遞給 mixin 的參數來變更 mixin 的行為。我們從一些基本概念開始

.mixin(@s, @color) { ... }

.class {
  .mixin(@switch, #888);
}

現在,假設我們希望 .mixin 根據 @switch 的值產生不同的行為,我們可以定義 .mixin 如下

.mixin(dark, @color) {
  color: darken(@color, 10%);
}
.mixin(light, @color) {
  color: lighten(@color, 10%);
}
.mixin(@_, @color) {
  display: block;
}

現在,如果我們執行

@switch: light;

.class {
  .mixin(@switch, #888);
}

我們將取得下列 CSS

.class {
  color: #a2a2a2;
  display: block;
}

其中傳遞給 .mixin 的顏色變亮了。如果 @switch 的值為 dark,結果將會是較深的顏色。

以下是發生的事情

  • 第一個混合定義不匹配,因為它預期 dark 為第一個參數。
  • 第二個混合定義匹配,因為它預期 light
  • 第三個混合定義匹配,因為它預期任何值。

只有匹配的混合定義會被使用。變數會匹配並繫結到任何值。除了變數之外的任何東西只會與等於其本身的值匹配。

我們也可以在元組上匹配,以下是一個範例

.mixin(@a) {
  color: @a;
}
.mixin(@a, @b) {
  color: fade(@a, @b);
}

現在,如果我們使用單一參數呼叫 .mixin,我們會取得第一個定義的輸出,但如果我們使用兩個參數呼叫它,我們會取得第二個定義,也就是 @a 漸變到 @b


使用混合作為函數

編輯「mixins-as-functions」的標記原始檔

從混合呼叫中選取屬性和變數

屬性 / 值存取器

發布 v3.5.0

從 Less 3.5 開始,您可以使用屬性/變數存取器從已評估的混合規則中選取值。這讓您可以使用類似函式的混合。

範例

.average(@x, @y) {
  @result: ((@x + @y) / 2);
}

div {
  // call a mixin and look up its "@result" value
  padding: .average(16px, 50px)[@result];
}

結果

div {
  padding: 33px;
}

覆寫混合值

如果您有多個相符的混合,所有規則都會評估並合併,且會傳回最後一個具有該識別碼的相符值。這類似於 CSS 中的串聯,讓您可以「覆寫」混合值。

// library.less
#library() {
  .mixin() {
    prop: foo;
  }
}

// customize.less
@import "library";
#library() {
  .mixin() {
    prop: bar;
  }
}

.box {
  my-value: #library.mixin[prop];
}

輸出

.box {
  my-value: bar;
}

未命名查詢

如果您未在 [@lookup] 中指定查詢值,而是在混合或規則集呼叫後寫入 []所有 值都會串聯,且會選取最後宣告的值。

意即:上述範例中的平均混合可以寫成

.average(@x, @y) {
  @result: ((@x + @y) / 2);
}

div {
  // call a mixin and look up its final value
  padding: .average(16px, 50px)[];
}

輸出相同

div {
  padding: 33px;
}

規則集或別名為混合呼叫的變數也有相同的串聯行為。

@dr: {
  value: foo;
}
.box {
  my-value: @dr[];
}

這會輸出

.box {
  my-value: foo;
}

將混合 & 變數解鎖到呼叫方範圍

已棄用 - 使用屬性 / 值存取器

在混合中定義的變數和混合在呼叫者的範圍中可見且可用。只有一個例外:如果呼叫者包含同名的變數(包括由其他混合呼叫定義的變數),則不會複製變數。只有呼叫者本機範圍中存在的變數受到保護。從父範圍繼承的變數會被覆寫。

注意:此行為已棄用,未來變數和混合不會以這種方式合併到呼叫者範圍中。

範例

.mixin() {
  @width:  100%;
  @height: 200px;
}

.caller {
  .mixin();
  width:  @width;
  height: @height;
}

結果

.caller {
  width:  100%;
  height: 200px;
}

在呼叫者範圍中直接定義的變數無法覆寫。但是,在呼叫者父範圍中定義的變數不受保護,並且會被覆寫

.mixin() {
  @size: in-mixin;
  @definedOnlyInMixin: in-mixin;
}

.class {
  margin: @size @definedOnlyInMixin;
  .mixin();
}

@size: globaly-defined-value; // callers parent scope - no protection

結果

.class {
  margin: in-mixin in-mixin;
}

最後,在混合中定義的混合也充當回傳值

.unlock(@value) { // outer mixin
  .doSomething() { // nested mixin
    declaration: @value;
  }
}

#namespace {
  .unlock(5); // unlock doSomething mixin
  .doSomething(); //nested mixin was copied here and is usable
}

結果

#namespace {
  declaration: 5;
}

遞迴混合

編輯「mixin-loops」的標記原始碼

建立迴圈

在 Less 中,混合可以呼叫自己。這種遞迴混合與 防護表達式模式比對 結合使用時,可用於建立各種反覆運算/迴圈結構。

範例

.loop(@counter) when (@counter > 0) {
  .loop((@counter - 1));    // next iteration
  width: (10px * @counter); // code for each iteration
}

div {
  .loop(5); // launch the loop
}

輸出

div {
  width: 10px;
  width: 20px;
  width: 30px;
  width: 40px;
  width: 50px;
}

使用遞迴迴圈產生 CSS 格線類別的範例

.generate-columns(4);

.generate-columns(@n, @i: 1) when (@i =< @n) {
  .column-@{i} {
    width: (@i * 100% / @n);
  }
  .generate-columns(@n, (@i + 1));
}

輸出

.column-1 {
  width: 25%;
}
.column-2 {
  width: 50%;
}
.column-3 {
  width: 75%;
}
.column-4 {
  width: 100%;
}

混合防護

編輯「mixin-guards」的標記原始碼

當您想要比對表達式(而非單純的值或項數)時,守衛會很有用。如果您熟悉函數式程式設計,您可能已經接觸過它們。

為了盡可能貼近 CSS 的宣告式性質,Less 選擇透過受守衛的混合來實作條件式執行,而非 if/else 陳述式,就像 @media 查詢功能規格一樣。

我們從一個範例開始

.mixin(@a) when (lightness(@a) >= 50%) {
  background-color: black;
}
.mixin(@a) when (lightness(@a) < 50%) {
  background-color: white;
}
.mixin(@a) {
  color: @a;
}

關鍵在於 when 關鍵字,它會引入一個守衛序列(這裡只有一個守衛)。現在,如果我們執行以下程式碼

.class1 { .mixin(#ddd) }
.class2 { .mixin(#555) }

我們會得到以下結果

.class1 {
  background-color: black;
  color: #ddd;
}
.class2 {
  background-color: white;
  color: #555;
}

守衛比較運算子

守衛中可用的比較運算子完整清單為:>>===<<。此外,關鍵字 true 是唯一的真值,讓這兩個混合等價

.truth(@a) when (@a) { ... }
.truth(@a) when (@a = true) { ... }

除了關鍵字 true 之外的任何值都是假值

.class {
  .truth(40); // Will not match any of the above definitions.
}

請注意,您也可以將參數彼此比較,或與非參數比較

@media: mobile;

.mixin(@a) when (@media = mobile) { ... }
.mixin(@a) when (@media = desktop) { ... }

.max(@a; @b) when (@a > @b) { width: @a }
.max(@a; @b) when (@a < @b) { width: @b }

邏輯運算子

您可以將邏輯運算子與防護結合使用。語法基於 CSS 媒體查詢。

使用 and 關鍵字來結合防護

.mixin(@a) when (isnumber(@a)) and (@a > 0) { ... }

您可以透過逗號 , 分隔防護來模擬 or 運算子。如果任何防護評估為真,則視為符合

.mixin(@a) when (@a > 10), (@a < -10) { ... }

使用 not 關鍵字來否定條件

.mixin(@b) when not (@b > 0) { ... }

類型檢查函數

最後,如果您想要根據值類型來比對混合,您可以使用 is 函數

.mixin(@a; @b: 0) when (isnumber(@b)) { ... }
.mixin(@a; @b: black) when (iscolor(@b)) { ... }

以下是基本類型檢查函數

  • iscolor
  • isnumber
  • isstring
  • iskeyword
  • isurl

如果您想要檢查值是否除了是數字之外,還位於特定單位中,您可以使用下列其中一個

  • ispixel
  • ispercentage
  • isem
  • isunit

混合別名

編輯「mixins-aliasing」的標記原始碼

發布 v3.5.0

將混入呼叫指派給變數

混入可以指派給變數,以變數呼叫的方式呼叫,或用於查詢對應。

#theme.dark.navbar {
  .colors(light) {
    primary: purple;
  }
  .colors(dark) {
    primary: black;
    secondary: grey;
  }
}

.navbar {
  @colors: #theme.dark.navbar.colors(dark);
  background: @colors[primary];
  border: 1px solid @colors[secondary];
}

這將會輸出

.navbar {
  background: black;
  border: 1px solid grey;
}

變數呼叫

整個混入呼叫可以設定別名,並以變數呼叫的方式呼叫。例如

#library() {
  .colors() {
    background: green;
  }
}
.box {
  @alias: #library.colors();
  @alias();
}

輸出

.box {
  background: green;
}

請注意,與在根目錄中使用的混入不同,指派給變數的混入呼叫,且未帶任何引數呼叫時,總是需要括號。下列範例無效。

#library() {
  .colors() {
    background: green;
  }
}
.box {
  @alias: #library.colors;
  @alias();   // ERROR: Could not evaluate variable call @alias
}

這是因為如果變數指派為選取器清單或混入呼叫,將會產生歧義。例如,在 Less 3.5 以上,這個變數可以用這種方式使用。

.box {
  @alias: #library.colors;
  @{alias} {
    a: b;
  }
}

上述範例將會輸出

.box #library.colors {
  a: b;
}

分離規則集

編輯「detached-rulesets」的標記原始碼

將規則集指定給變數

已發布 v1.7.0

分離規則集是儲存在變數中的 CSS 屬性、巢狀規則集、媒體宣告或其他任何項目的群組。你可以將它包含在規則集或其他結構中,而且它的所有屬性都將複製到該處。你也可以將它用作混合參數,並像其他任何變數一樣傳遞它。

簡單範例

// declare detached ruleset
@detached-ruleset: { background: red; }; // semi-colon is optional in 3.5.0+

// use detached ruleset
.top {
    @detached-ruleset(); 
}

編譯成

.top {
  background: red;
}

分離規則集呼叫後面的括號是強制性的(除非後面接著 查詢值)。呼叫 @detached-ruleset; 將無法運作。

當你想要定義一個混合,將一段程式碼包裝在媒體查詢或非支援瀏覽器類別名稱中時,這會很有用。規則集可以傳遞給混合,以便混合可以包裝內容,例如

.desktop-and-old-ie(@rules) {
  @media screen and (min-width: 1200px) { @rules(); }
  html.lt-ie9 &                         { @rules(); }
}

header {
  background-color: blue;

  .desktop-and-old-ie({
    background-color: red;
  });
}

這裡的 desktop-and-old-ie 混合定義了媒體查詢和根類別,以便你可以使用混合來包裝一段程式碼。這將輸出

header {
  background-color: blue;
}
@media screen and (min-width: 1200px) {
  header {
    background-color: red;
  }
}
html.lt-ie9 header {
  background-color: red;
}

規則集現在可以指定給變數或傳遞給混合,並且可以包含 Less 功能的完整設定,例如

@my-ruleset: {
    .my-selector {
      background-color: black;
    }
  };

例如,您甚至可以利用媒體查詢冒泡

@my-ruleset: {
    .my-selector {
      @media tv {
        background-color: black;
      }
    }
  };
@media (orientation:portrait) {
    @my-ruleset();
}

它會輸出

@media (orientation: portrait) and tv {
  .my-selector {
    background-color: black;
  }
}

分離的規則集呼叫會將其所有混入解鎖(傳回)給呼叫者,就像混入呼叫一樣。但是,它不會傳回變數。

傳回的混入

// detached ruleset with a mixin
@detached-ruleset: { 
    .mixin() {
        color: blue;
    }
};
// call detached ruleset
.caller {
    @detached-ruleset(); 
    .mixin();
}

結果

.caller {
  color: blue;
}

私人變數

@detached-ruleset: { 
    @color:blue; // this variable is private
};
.caller {
    color: @color; // syntax error
}

範圍

分離的規則集可以使用在其定義呼叫位置可存取的所有變數和混入。換句話說,定義和呼叫者範圍都對其可用。如果兩個範圍都包含相同的變數或混入,則宣告範圍值優先。

宣告範圍是指定義分離規則集主體的範圍。將分離規則集從一個變數複製到另一個變數無法修改其範圍。規則集不會因為在那裡被參照而獲得新的範圍。

最後,分離的規則集可以透過解鎖(匯入)到範圍中來獲得範圍存取權。

注意:透過呼叫的混入將變數解鎖到範圍中已不建議使用。請使用 屬性 / 變數存取器

定義和呼叫者範圍可見性

分離的規則集會看到呼叫者的變數和混入

@detached-ruleset: {
  caller-variable: @caller-variable; // variable is undefined here
  .caller-mixin(); // mixin is undefined here
};

selector {
  // use detached ruleset
  @detached-ruleset(); 

  // define variable and mixin needed inside the detached ruleset
  @caller-variable: value;
  .caller-mixin() {
    variable: declaration;
  }
}

編譯成

selector {
  caller-variable: value;
  variable: declaration;
}

從定義中存取的變數和混入會優先於呼叫者中可用的變數和混入

@variable: global;
@detached-ruleset: {
  // will use global variable, because it is accessible
  // from detached-ruleset definition
  variable: @variable; 
};

selector {
  @detached-ruleset();
  @variable: value; // variable defined in caller - will be ignored
}

編譯成

selector {
  variable: global;
}

參照不會修改分離的規則集範圍

規則集不會因為在其中被參照而取得對新範圍的存取權

@detached-1: { scope-detached: @one @two; };
.one {
  @one: visible;
  .two {
    @detached-2: @detached-1; // copying/renaming ruleset 
    @two: visible; // ruleset can not see this variable
  }
}

.use-place {
  .one > .two(); 
  @detached-2();
}

會擲回錯誤

ERROR 1:32 The variable "@one" was not declared.

解鎖修改分離的規則集範圍

分離的規則集會透過在範圍內解鎖 (匯入) 而取得存取權

#space {
  .importer-1() {
    @detached: { scope-detached: @variable; }; // define detached ruleset
  }
}

.importer-2() {
  @variable: value; // unlocked detached ruleset CAN see this variable
  #space > .importer-1(); // unlock/import detached ruleset
}

.use-place {
  .importer-2(); // unlock/import detached ruleset second time
   @detached();
}

編譯成

.use-place {
  scope-detached: value;
}

屬性 / 變數存取器

(查詢值)

發布 v3.5.0

從 Less 3.5 開始,您可以使用屬性/變數存取器(也稱為「查詢」)來從變數(分離)規則集中選擇一個值。

@config: {
  option1: true;
  option2: false;
}

.mixin() when (@config[option1] = true) {
  selected: value;
}

.box {
  .mixin();
}

輸出

.box {
  selected: value;
}

如果查詢回傳的結果是另一個分離規則集,您可以使用第二次查詢來取得該值。

@config: {
  @colors: {
    primary: blue;
  }
}

.box {
  color: @config[@colors][primary];
}

查詢中的變數變數

回傳的查詢值本身可以是變數。例如,您可以撰寫

@config: {
  @dark: {
    primary: darkblue;
  }
  @light: {
    primary: lightblue;
  }
}

.box {
  @lookup: dark;
  color: @config[@@lookup][primary];
}

這將輸出

.box {
  color: darkblue;
}

對應

編輯「對應」的標記原始碼

發布 v3.5.0

使用規則集和混合作為值對應

透過結合命名空間與查詢 [] 語法,您可以將規則集/混合轉換為對應。

@sizes: {
  mobile: 320px;
  tablet: 768px;
  desktop: 1024px;
}

.navbar {
  display: block;

  @media (min-width: @sizes[tablet]) {
    display: inline-block;
  }
}

輸出

.navbar {
  display: block;
}
@media (min-width: 768px) {
  .navbar {
    display: inline-block;
  }
}

由於命名空間和覆載混合的能力,混合作為對應時會更靈活。

#library() {
  .colors() {
    primary: green;
    secondary: blue;
  }
}

#library() {
  .colors() { primary: grey; }
}

.button {
  color: #library.colors[primary];
  border-color: #library.colors[secondary];
}

輸出

.button {
  color: grey;
  border-color: blue;
}

您也可以透過混合作別名稱來讓這件事變得更簡單。也就是說

.button {
  @colors: #library.colors();
  color: @colors[primary];
  border-color: @colors[secondary];
}

請注意,如果查詢值產生另一個規則組,你可以附加第二個 [] 查詢,如下所示

@config: {
  @options: {
    library-on: true
  }
}

& when (@config[@options][library-on] = true) {
  .produce-ruleset {
    prop: val;
  }
}

透過這種方式,規則組和變數呼叫可以模擬類似於混合的「命名空間」類型。

至於要使用混合還是指派給變數的規則組作為映射,則由你決定。你可能想要透過重新宣告指派給規則組的變數來取代整個映射。或者你可能想要「合併」個別的鍵值對,這種情況下,混合作為映射可能更合適。

在查詢中使用變數變數

需要注意的一件重要事情是,[@lookup] 中的值是鍵(變數)名稱 @lookup,並且不會評估為變數。如果你想要鍵名稱本身是變數,你可以使用 @@variable 語法。

例如

.foods() {
  @dessert: ice cream;
}

@key-to-lookup: dessert;

.lunch {
  treat: .foods[@@key-to-lookup];
}

這將會輸出

.lunch {
  treat: ice cream;
}

範圍

編輯「範圍」的標記原始碼

Less 的一些額外範圍功能

混合範圍功能

直覺上,混合可以存取定義範圍。

#ns {
  @a: one;
  .mixin-1() {
    prop: @a;
  }
}
.rule {
  #ns.mixin-1();
}

/* OUTPUTS:
.rule {
  prop: one;
}
*/

已棄用的混合範圍功能

以下是可能會在未來版本中移除的混合範圍功能清單。

#1. (已棄用) 混合可以存取呼叫者範圍。

#ns {
  .mixin-1() {
    prop: @a;
  }
}
.rule {
  @a: one;
  #ns.mixin-1();
}
/* OUTPUTS:
.rule {
  prop: one;
}
*/

這違反直覺,因為

  1. 大多數其他語言並非如此。
  2. 從定義中無法立即得知混合會產生什麼輸出。

建議做法:傳入您希望混合可見的變數。

#ns {
  .mixin-1(@a) {
    prop: @a;
  }
}
.rule {
  #ns.mixin-1(@a: one);
}

#2. (已棄用) 呼叫者範圍可以存取混合的變數

混合會將其變數推入呼叫者範圍,但僅限變數未在本地定義時。

#ns {
  .mixin-1() {
    @a: one;
    @b: two;
  }
}
.rule {
  @b: three;
  #ns.mixin-1();
  prop-1: @a;
  prop-2: @b;
}
/* OUTPUTS:
.rule {
  prop-1: one;
  prop-2: three;
}
*/

這違反直覺,因為

  1. 呼叫者範圍中較高的變數可以被覆寫。
  2. 這也不是典型的語言行為。
  3. 這與分離規則集的行為不同。

此外,透過導入對應,您可以直接擷取變數值 (和混合)。

偏好的方法:

#ns {
  .mixin-1() {
    @a: one;
    @b: two;
  }
}
.rule {
  @returns: #ns.mixin-1();
  prop-1: @returns[@a];
  prop-2: @returns[@b];
}
/* OUTPUTS:
.rule {
  prop-1: one;
  prop-2: two;
}
*/

#3. (已棄用) 呼叫者範圍有權存取混合中的混合

類似於已棄用的變數行為,混合也會推送到呼叫者範圍。但是,與變數不同的是,與合併範圍混合同名的混合會合併。

#ns {
  .mixin-1() {
    prop-1: one;
    prop-2: two;
  }
}
.rule {
  #ns();
  .mixin-1();
  .mixin-1() {
    prop-3: three;
  }
}
/* OUTPUT:
.rule {
  prop-1: one;
  prop-2: two;
  prop-3: three;
}
*/

偏好的方法:直接呼叫混合。

#ns {
  .mixin-1() {
    prop-1: one;
    prop-2: two;
  }
}
.rule {
  .mixin-1() {
    prop-3: three;
  }
  #ns.mixin-1();
  .mixin-1();
}
/* OUTPUT:
.rule {
  prop-1: one;
  prop-2: two;
  prop-3: three;
}
*/

提示和技巧

來源:less/less.js/issues/1472

以下是定義變數並將它們保留在某些私有範圍中的技巧,防止它們洩漏到全域空間。

& {
  // Vars
  @height: 100px;
  @width: 20px;
  // Don't define any prop:value on this scope (as doing so will generate (wrong) output).

  .test {
    height: @height;
    width: @width;
  }
}

.rest {
  height: @height; // Name error: variable @height is undefined
}

在此,@height@width 僅針對 & { ... } 建立的範圍定義。您還可以在規則中巢狀範圍

.some-module {
  @height: 200px;
  @width: 200px;
  text-align: left;
  line-height: @height; // 200px

  & {
    // Override original values
    @height: 100px;
    @width: auto;

    .some-module__element {
      height: @height; // 100px
      width: @width; // 200px
    }

    .some-module__element .text {
      line-height: (@height / 2); // 50px
    }
  }

  & {
    // Override original values
    @height: 50px;

    .some-module__another-element {
      height: @height; // 50px
      width: @width; // 200px
    }

    .some-module__another-element .text {
      line-height: (@height / 2); // 25px
    }
  }
}

CSS 守衛

編輯「css-guards」的標記源

選擇器周圍的「if」

已發布 v1.5.0

如同 Mixin Guards,guards 也可套用至 css 選擇器,這是一種宣告 mixin 然後立即呼叫它的語法糖。

例如,在 1.5.0 之前,你必須這樣做

.my-optional-style() when (@my-option = true) {
  button {
    color: white;
  }
}
.my-optional-style();

現在,你可以直接將 guard 套用至樣式。

button when (@my-option = true) {
  color: white;
}

你也可以將此與 & 功能結合,達成 if 類型的陳述式,讓你能夠群組多個 guards。

& when (@my-option = true) {
  button {
    color: white;
  }
  a {
    color: blue;
  }
}

請注意,你也可以使用實際的 if() 函數和變數呼叫,達成類似的模式。如同

@dr: if(@my-option = true, {
  button {
    color: white;
  }
  a {
    color: blue;
  }
});
@dr();

@plugin At-Rules

編輯「plugins」的 markdown 原始碼

已發佈 v2.5.0

匯入 JavaScript 外掛程式,以新增 Less.js 函數和功能

撰寫你的第一個外掛程式

使用 @plugin at-rule 類似於為 .less 檔案使用 @import

@plugin "my-plugin";  // automatically appends .js if no extension

由於 Less 外掛程式會在 Less 範圍內評估,因此外掛程式定義可以非常簡單。

registerPlugin({
    install: function(less, pluginManager, functions) {
        functions.add('pi', function() {
            return Math.PI;
        });
    }
})

或者你可以使用 module.exports(在瀏覽器和 Node.js 中都可使用)。

module.exports = {
    install: function(less, pluginManager, functions) {
        functions.add('pi', function() {
            return Math.PI;
        });
    }
};

請注意,其他 Node.js CommonJS 慣例(例如 require())在瀏覽器中不可用。在撰寫跨平台外掛程式時請牢記這一點。

外掛程式能做什麼?很多事情,但讓我們從基礎開始。我們會先專注於你可能會放入 install 函式的內容。假設你寫了這個

// my-plugin.js
install: function(less, pluginManager, functions) {
    functions.add('pi', function() {
        return Math.PI;
    });
}
// etc

恭喜!你已經寫了一個 Less 外掛程式!

如果你在你的樣式表中使用這個

@plugin "my-plugin";
.show-me-pi {
  value: pi();
}

你會得到

.show-me-pi {
  value: 3.141592653589793;
}

但是,如果你想要將它乘以其他值或執行其他 Less 運算,則需要傳回一個適當的 Less 節點。否則,樣式表中的輸出將會是純文字(這對於你的目的來說可能很好)。

意思是,這個比較正確

functions.add('pi', function() {
    return new tree.Dimension(Math.PI);
});

注意:維度是一個有或沒有單位的數字,例如「10px」,這將會是 less.Dimension(10, "px")。有關單位清單,請參閱 Less API

現在你可以在運算中使用你的函式。

@plugin "my-plugin";
.show-me-pi {
  value: pi() * 2;
}

你可能已經注意到你的外掛程式檔案有可用的全域變數,即函式註冊表(functions 物件)和 less 物件。這些變數的存在是為了方便起見。

外掛程式範圍

透過 @plugin at 規則新增的函式會遵守 Less 範圍規則。這對於想要新增功能而不引入命名衝突的 Less 函式庫作者來說非常棒。

例如,假設你從兩個第三方函式庫中擁有 2 個外掛程式,這兩個外掛程式都有名為「foo」的函式。

// lib1.js
// ...
    functions.add('foo', function() {
        return "foo";
    });
// ...

// lib2.js
// ...
    functions.add('foo', function() {
        return "bar";
    });
// ...

沒問題!你可以選擇哪個函式庫的函式會產生哪個輸出。

.el-1 {
    @plugin "lib1";
    value: foo();
}
.el-2 {
    @plugin "lib2";
    value: foo();
}

這將會產生

.el-1 {
    value: foo;
}
.el-2 {
    value: bar;
}

對於分享外掛程式的外掛程式作者,這表示您也可以透過將它們置於特定範圍內來有效地建立私人函式。例如,這會造成錯誤

.el {
    @plugin "lib1";
}
@value: foo();

從 Less 3.0 開始,函式可以傳回任何類型的 Node,而且可以在任何層級呼叫。

這表示,這會在 2.x 中擲回錯誤,因為函式必須是屬性值或變數指派的一部分

.block {
    color: blue;
    my-function-rules();
}

在 3.x 中,情況不再如此,函式可以傳回 At-Rules、Rulesets、任何其他 Less 節點、字串和數字(後兩者會轉換為 Anonymous 節點)。

Null 函式

有時您可能想要呼叫函式,但您不想要任何輸出(例如儲存值以供稍後使用)。在這種情況下,您只需要從函式傳回 false 即可。

var collection = [];

functions.add('store', function(val) {
    collection.push(val);  // imma store this for later
    return false;
});
@plugin "collections";
@var: 32;
store(@var);

稍後您可以執行類似下列動作

functions.add('retrieve', function(val) {
    return new tree.Value(collection);
});
.get-my-values {
    @plugin "collections";
    values: retrieve();   
}

Less.js 外掛程式物件

Less.js 外掛程式應該匯出一個具有下列其中一個或多個屬性的物件。

{
    /* Called immediately after the plugin is 
     * first imported, only once. */
    install: function(less, pluginManager, functions) { },

    /* Called for each instance of your @plugin. */
    use: function(context) { },

    /* Called for each instance of your @plugin, 
     * when rules are being evaluated.
     * It's just later in the evaluation lifecycle */
    eval: function(context) { },

    /* Passes an arbitrary string to your plugin 
     * e.g. @plugin (args) "file";
     * This string is not parsed for you, 
     * so it can contain (almost) anything */
    setOptions: function(argumentString) { },

    /* Set a minimum Less compatibility string
     * You can also use an array, as in [3, 0] */
    minVersion: ['3.0'],

    /* Used for lessc only, to explain 
     * options in a Terminal */
    printUsage: function() { },

}

install() 函式的 PluginManager 實例提供新增訪客、檔案管理員和後處理器的函式。

以下是一些顯示不同外掛程式類型的範例儲存庫。

預先載入的外掛程式

雖然 @plugin 呼叫在大部分情況下都能正常運作,但在某些時候,您可能想要在開始分析之前載入外掛程式。

請參閱「使用 Less.js」區段中的 預先載入的外掛程式,了解如何執行此操作。