概要

"overview" のマークダウンソースを編集する

LESS言語の機能に関する詳細なガイドです。Lessの簡単な概要については、概要を参照してください。

Less環境のインストールと設定、およびLessの開発に関するドキュメントの詳細なガイドについては、Less.jsの使い方を参照してください。


変数

"variables" のマークダウンソースを編集する

よく使う値を一箇所で管理します。

概要

スタイルシート全体で *数百回とは言わないまでも数十回* 同じ値が繰り返されるのは珍しいことではありません。

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

変数を2回定義すると、現在のスコープから上に向かって検索し、変数の最後の定義が使用されます。これは、定義内の最後のプロパティが値を決定するために使用される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" のマークダウンソースを編集する

& を使用した親セレクタの参照

& 演算子は、ネストされたルールの親セレクタを表し、既存のセレクタに修飾クラスまたは擬似クラスを適用する場合に最もよく使用されます。

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

結果は

a {
  color: blue;
}

a:hover {
  color: green;
}

& がない場合、上記の例では a :hover ルール(<a> タグ内のホバーされた要素に一致する子孫セレクタ)になり、これはネストされた :hover で通常必要なものではないことに注意してください。

「親セレクタ」演算子にはさまざまな用途があります。基本的に、ネストされたルールのセレクタをデフォルト以外の方法で組み合わせる必要がある場合はいつでも使用できます。たとえば、& のもう1つの典型的な使用法は、反復的なクラス名を生成することです。

.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 アットルール

"imports" のマークダウンソースを編集する

他のスタイルシートからスタイルをインポートします。

標準のCSSでは、@import アットルールは他のすべてのタイプのルールよりも前に配置する必要があります。しかし、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アットルールにいくつかの拡張機能を提供して、外部ファイルでできることをより柔軟にします。

構文: @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は、インポートされたファイル内のすべてのat-ruleとセレクタに*参照フラグ*を付け、通常どおりインポートしますが、CSSが生成されると、「reference」セレクタ(およびreferenceセレクタのみを含むメディアクエリ)は出力されません。 referenceスタイルは、mixinまたはextendとして使用されない限り、生成されたCSSには表示されません。

さらに、**reference**は、使用されたメソッド(mixinまたはextend)によって異なる結果を生成します。

  • **extend**: セレクタが拡張されると、新しいセレクタのみが*参照されていない*とマークされ、参照@importステートメントの位置にプルインされます。
  • **mixins**: referenceスタイルが暗黙のmixinとして使用される場合、そのルールはmixinされ、「参照なし」とマークされ、参照された場所に通常どおり表示されます。

referenceの例

これにより、Bootstrapなどのライブラリから、次のような操作を行うことで、特定のターゲットスタイルのみをプルインできます。

.navbar:extend(.navbar all) {}

そして、Bootstrapから.navbar関連のスタイルのみをプルインします。

inline

@import (inline)を使用して外部ファイルを含めますが、処理はしません。

リリース v1.5.0

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

CSSファイルがLessと互換性がない場合にこれを使用します。これは、Lessはほとんどの既知の標準CSSをサポートしていますが、一部の場所でのコメントをサポートしておらず、CSSを変更せずにすべての既知のCSSハックをサポートしていないためです。

そのため、これを使用してファイルを出力に含め、すべてのCSSが1つのファイルに収まるようにすることができます。

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

once

@importステートメントのデフォルトの動作。ファイルは一度だけインポートされ、そのファイルの後続のインポートステートメントは無視されることを意味します。

リリース v1.4.0

これは、@importステートメントのデフォルトの動作です。

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

multiple

@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


Extend

"extend"のMarkdownソースを編集する

Extendは、それが配置されているセレクタを、それが参照するものと一致するセレクタとマージするLess疑似クラスです。

リリース v1.4.0

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

上記のルールセットでは、:extendセレクタは、「拡張セレクタ」(nav ul)を.inlineクラスに適用します。*.inlineクラスが表示される場所ならどこでも*。宣言ブロックはそのまま保持されますが、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は他のセレクタに影響を与える可能性があります)。

Extendの構文

extendは、セレクタに添付されるか、ルールセットに配置されます。セレクタパラメータを持つ疑似クラスのように見え、オプションでキーワード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"
}

カンマで区切られた、拡張する1つ以上のクラスを含めることができます。

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

// the above and the below do the same thing
.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キーワードを含めることができます。1つのルールセットにextendを持つ複数のセレクタ

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

ルールセット内の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はネストされたセレクタと一致させることができます。以下の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は元のlessではなく、コンパイルされたcssを見ます。

.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はデフォルトでセレクタ間の完全一致を探します。セレクタが先頭にアスタリスクを使用するかどうかは重要です。2つの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;
}

n番目の式

n番目の式の形式は重要です。n番目の式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"

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

背景色をオーバーライドする動物のサブタイプが必要な場合は、2つの選択肢があります。1つ目は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サイズの削減

Mixinはすべてのプロパティをセレクターにコピーするため、不要な重複が発生する可能性があります。そのため、Mixinの代わりにextendを使用して、セレクターを使用したいプロパティに移動することで、生成される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;
}

例 (extendを使用)

.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

もう1つのユースケースは、mixinの代替手段としての使用です。mixinは単純なセレクターでのみ使用できるため、2つの異なるHTMLブロックがあり、両方に同じスタイルを適用する必要がある場合は、extendを使用して2つの領域を関連付けることができます。

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

プロパティのマージ

"merge" のマークダウンソースを編集する

プロパティの結合

merge 機能を使用すると、複数のプロパティの値を、単一のプロパティの下にカンマまたはスペースで区切ったリストに集約できます。 merge は、backgroundやtransformなどのプロパティに役立ちます。

カンマ

プロパティ値をカンマで追加する

リリース 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 では、保留中の各結合宣言に明示的な + または +_ フラグが必要です。


Mixin

"mixins" のマークダウンソースを編集する

既存のスタイルからプロパティを「ミックスイン」する

クラスセレクターとIDセレクターをミックスインできます。例:

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

結果は次のとおりです。

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

歴史的に、mixin呼び出しの括弧は省略可能でしたが、省略可能な括弧は非推奨となり、将来のリリースでは必須となります。

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

括弧付きMixin

mixinを作成したいが、そのmixinをCSS出力に含めたくない場合は、mixin定義の後に括弧を付けます。

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

出力

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

Mixinのセレクター

Mixinにはプロパティだけでなく、セレクターも含めることができます。

例えば

.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構文では、名前空間とmixinの間に > と空白を使用できます。この構文は非推奨であり、削除される可能性があります。現在、これらは同じ動作をします。

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

このようにmixinの名前空間を設定すると、他のライブラリのmixinやユーザーmixinとの競合が軽減されますが、mixinのグループを「整理」する方法にもなります。

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

ガード付き名前空間

名前空間にガードがある場合、ガード条件がtrueを返す場合にのみ、名前空間で定義されたmixinが使用されます。名前空間ガードは、mixinのガードとまったく同じように評価されるため、次の2つのmixinは同じように機能します。

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

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

default 関数は、すべてのネストされた名前空間とmixinで同じ値を持つと想定されています。次のmixinは評価されません。ガードの1つは必ずfalseになります。

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

!important キーワード

mixin呼び出しの後に !important キーワードを使用して、mixinによって継承されたすべてのプロパティを !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のborder-radiusが含まれます。

パラメータを取らないパラメトリック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"に似ています。 これにより、コードベースでセミコロンセパレータが不要になる場合があります。

  • 2つの引数があり、それぞれにカンマ区切りのリストが含まれています:.name(1, 2, 3; something, else)
  • 3つの引数があり、それぞれに1つの数値が含まれています:.name(1, 2, 3)
  • ダミーのセミコロンを使用して、カンマ区切りのcssリストを含む1つの引数を持つmixin呼び出しを作成します:.name(1, 2, 3;)。 *注: 末尾のセミコロンが奇妙に思える場合は、.name(~(1, 2, 3))の方が良いかもしれません。*
  • カンマ区切りのデフォルト値を記述する方法
    • @param-values: red, blue; .name(@param1: @param-values).
    • .name(@param1: red, blue;)
    • .name(@param1: ~(red, blue))

Mixinのオーバーロード

同じ名前とパラメータ数で複数のmixinを定義することは許容されます。Lessは、適用可能なすべてのプロパティを使用します。1つのパラメータを持つmixinを使用した場合は、例:.mixin(green);、必須パラメータが1つだけのすべてのmixinのプロパティが使用されます。

.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参照は、位置だけでなく、名前でパラメータ値を指定できます。任意のパラメータを名前で参照でき、特別な順序で指定する必要はありません。

.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(@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 であった場合、結果はより暗い色になります。

何が起こったのか説明します。

  • 最初の mixin 定義は、最初の引数として dark を期待していたため、一致しませんでした。
  • 2 番目の mixin 定義は、light を期待していたため、一致しました。
  • 3 番目の mixin 定義は、任意の値を期待していたため、一致しました。

一致した mixin 定義のみが使用されました。変数は任意の値と一致し、バインドされます。変数以外のものは、それ自体と等しい値とのみ一致します。

arity(引数の数)で一致させることもできます。次に例を示します。

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

ここで、.mixin を単一の引数で呼び出すと、最初の定義の出力が得られますが、*2 つの*引数で呼び出すと、2 番目の定義、つまり @a@b にフェードアウトしたものが得られます。


Mixin を関数として使用する

"mixins-as-functions" の Markdown ソースを編集する

mixin 呼び出しからプロパティと変数を選択する

プロパティ / 値アクセサー

リリース v3.5.0

Less 3.5 以降、プロパティ/変数アクセサーを使用して、評価された mixin のルールから値を選択できます。これにより、mixin を関数のように使用できます。

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

Mixin 値のオーバーライド

複数の一致する mixin がある場合、すべてのルールが評価およびマージされ、その識別子を持つ最後の一致する値が返されます。これは CSS のカスケードに似ており、mixin 値を「オーバーライド」できます。

// 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] にルックアップ値を指定せずに、mixin またはルールセット呼び出しの後に [] を記述すると、*すべて*の値がカスケードされ、最後に宣言された値が選択されます。

つまり、上記の例の平均化 mixin は次のように記述できます。

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

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

出力は同じです。

div {
  padding: 33px;
}

ルールセットまたは mixin 呼び出しにエイリアスされた変数についても、同じカスケード動作が当てはまります。

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

これは次を出力します。

.box {
  my-value: foo;
}

呼び出し元のスコープへの Mixin と変数のアンロック

**非推奨** - プロパティ / 値アクセサーを使用してください

mixin で定義された変数と mixin は、呼び出し元のスコープで表示および使用できます。例外は 1 つだけです。呼び出し元に同じ名前の変数(別の mixin 呼び出しによって定義された変数を含む)が含まれている場合、変数はコピーされません。呼び出し元のローカルスコープに存在する変数のみが保護されます。親スコープから継承された変数はオーバーライドされます。

注: この動作は非推奨であり、将来的には、変数と mixin はこのように呼び出し元のスコープにマージされなくなります。

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

最後に、mixin で定義された 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

"mixin-loops" の Markdown ソースを編集する

ループの作成

Less では、mixin は自身を呼び出すことができます。このような再帰的 mixin は、ガード式 および パターンマッチングと組み合わせると、さまざまな反復/ループ構造を作成するために使用できます。

.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 ガード

"mixin-guards" の Markdown ソースを編集する

ガードは、単純な値や arity ではなく、*式*で一致させたい場合に役立ちます。関数型プログラミングに精通している場合は、すでに遭遇している可能性があります。

CSS の宣言型の性質にできるだけ近づけるために、Less は if/else ステートメントの代わりに、@media クエリ機能仕様のように、**ガード付き mixin** を介して条件付き実行を実装することを選択しました。

例から始めましょう。

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

重要なのは when キーワードです。これはガードシーケンスを導入します(ここではガードは 1 つだけです)。ここで、次のコードを実行すると

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

次のような結果が得られます。

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

ガード比較演算子

ガードで使用できる比較演算子の完全なリストは次のとおりです。>>===<<。さらに、キーワード true のみが truthy 値であるため、次の 2 つの mixin は同等です。

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

キーワード true 以外の値は falsy です。

.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* 演算子をエミュレートできます。いずれかのガードが true と評価された場合、一致と見なされます。

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

not キーワードを使用して条件を否定します。

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

型チェック関数

最後に、値の型に基づいて mixin を一致させたい場合は、is 関数を使用できます。

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

基本的な型チェック関数は次のとおりです。

  • iscolor
  • isnumber
  • isstring
  • iskeyword
  • isurl

値が数値であることに加えて、特定の単位であるかどうかを確認したい場合は、次のいずれかを使用できます。

  • ispixel
  • ispercentage
  • isem
  • isunit

Mixin のエイリアシング

"mixins-aliasing" の Markdown ソースを編集する

リリース v3.5.0

Mixin 呼び出しを変数に割り当てる

Mixin は変数に割り当てて、変数呼び出しとして呼び出すか、マップルックアップに使用できます。

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

変数呼び出し

Mixin 呼び出し全体をエイリアス化し、変数呼び出しとして呼び出すことができます。次のように。

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

出力

.box {
  background: green;
}

ルートで使用される mixin とは異なり、変数に割り当てられ、*引数なしで呼び出される* mixin 呼び出しには、常に括弧が必要です。以下は無効です。

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

これは、変数にセレクターのリストまたは mixin 呼び出しのどちらが割り当てられているかが不明確であるためです。たとえば、Less 3.5 以降では、この変数を次のように使用できます。

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

上記は次を出力します。

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

デタッチされたルールセット

"detached-rulesets" の Markdown ソースを編集する

ルールセットを変数に割り当てる

リリース v1.7.0

デタッチされたルールセットは、css プロパティ、ネストされたルールセット、メディア宣言、または変数に格納されているその他のもののグループです。ルールセットまたは別の構造に含めることができ、そのすべてのプロパティがそこにコピーされます。また、mixin 引数として使用したり、他の変数と同様に渡したりすることもできます。

簡単な例

// 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; は機能しません。

メディアクエリまたはサポートされていないブラウザークラス名でコードの一部をラップすることを抽象化する mixin を定義する場合に役立ちます。ルールセットは mixin に渡すことができるため、mixin はコンテンツをラップできます。例:

.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 mixin はメディアクエリとルートクラスを定義するため、mixin を使用してコードの一部をラップできます。これは次を出力します。

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

デタッチされたルールセット呼び出しは、mixin 呼び出しと同じ方法ですべての mixin を呼び出し元にアンロック(返します)。ただし、変数は**返しません**。

返された mixin

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

ルックアップから返されるものが別のデタッチドルールセットである場合、2番目のルックアップを使用してその値を取得できます。

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

ルックアップ値が別のルールセットを生成する場合、次のように2番目の`[]`ルックアップを追加できることに注意してください。

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

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

このように、ルールセットと変数呼び出しは、ミックスインと同様に、ある種の「名前空間」をエミュレートできます。

マップとして変数に割り当てられたミックスインまたはルールセットを使用するかどうかは、ユーザー次第です。ルールセットに割り当てられた変数を再宣言することで、マップ全体を置き換えることができます。または、個々のキー/値ペアを「マージ」する場合、マップとしてのミックスインの方が適切な場合があります。

ルックアップでの変数変数の使用

注意すべき重要なことの1つは、`[@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と同様に、ガードはcssセレクターにも適用できます。これは、ミックスインを宣言してからすぐに呼び出すための糖衣構文です。

たとえば、1.5.0より前は、これを行う必要がありました。

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

これで、ガードをスタイルに直接適用できます。

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

これを`&`機能と組み合わせることで、`if`タイプのステートメントを実現することもでき、複数のガードをグループ化できます。

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

実際の`if()`関数と変数呼び出しを使用することで、同様のパターンを実現できることにも注意してください。のように

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

@pluginアットルール

「プラグイン」のマークダウンソースを編集する

リリースv2.5.0

JavaScriptプラグインをインポートして、Less.jsの関数と機能を追加します

最初のプラグインの作成

`@plugin`アットルールの使用は、`.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;
        });
    }
};

`require()`のような他のNode.js CommonJS規則は、ブラウザでは使用できないことに注意してください。クロスプラットフォームプラグインを作成するときは、これを覚えておいてください。

プラグインで何ができますか?たくさんありますが、基本から始めましょう。最初に`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-rule によって追加された関数は、Less のスコープ規則に従います。これは、名前の競合を引き起こすことなく機能を追加したい Less ライブラリの作成者にとって便利です。

たとえば、2 つのサードパーティライブラリからの 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 以降、関数はあらゆる種類のノードタイプを返すことができ、あらゆるレベルで呼び出すことができます。

つまり、2.x では、関数はプロパティまたは変数代入の値の一部でなければならなかったため、これはエラーをスローします

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

3.x では、もはやそうではなく、関数は At-Rules、Rulesets、その他の Less ノード、文字列、数値を返すことができます(後者の 2 つは 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 プラグインは、これらのプロパティの 1 つ以上を持つオブジェクトをエクスポートする必要があります。

{
    /* 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 の使用」セクションの プリロードされたプラグイン を参照してください。