LESS言語の機能に関する詳細なガイドです。Lessの簡単な概要については、概要を参照してください。
Less環境のインストールと設定、およびLessの開発に関するドキュメントの詳細なガイドについては、Less.jsの使い方を参照してください。
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;
}
// 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
は濃い赤になります。
&
を使用した親セレクタの参照
&
演算子は、ネストされたルールの親セレクタを表し、既存のセレクタに修飾クラスまたは擬似クラスを適用する場合に最もよく使用されます。
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;
}
他のスタイルシートからスタイルをインポートします。
標準のCSSでは、@import
アットルールは他のすべてのタイプのルールよりも前に配置する必要があります。しかし、Lessは @import
ステートメントをどこに配置しても構いません。
例
.foo {
background: #900;
}
@import "this-is-valid.less";
@import
ステートメントは、ファイル拡張子に応じてLessによって異なる方法で処理される場合があります。
.css
拡張子が付いている場合、CSSとして扱われ、@import
ステートメントはそのまま残されます(以下のインラインオプションを参照)。.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";
@import (reference)
を使用して外部ファイルをインポートしますが、参照されない限り、インポートされたスタイルはコンパイルされた出力に追加されません。
リリース v1.5.0
例: @import (reference) "foo.less";
reference
は、インポートされたファイル内のすべてのat-ruleとセレクタに*参照フラグ*を付け、通常どおりインポートしますが、CSSが生成されると、「reference」セレクタ(およびreferenceセレクタのみを含むメディアクエリ)は出力されません。 reference
スタイルは、mixinまたはextendとして使用されない限り、生成されたCSSには表示されません。
さらに、**reference
**は、使用されたメソッド(mixinまたはextend)によって異なる結果を生成します。
@import
ステートメントの位置にプルインされます。reference
スタイルが暗黙のmixinとして使用される場合、そのルールはmixinされ、「参照なし」とマークされ、参照された場所に通常どおり表示されます。これにより、Bootstrapなどのライブラリから、次のような操作を行うことで、特定のターゲットスタイルのみをプルインできます。
.navbar:extend(.navbar all) {}
そして、Bootstrapから.navbar
関連のスタイルのみをプルインします。
@import (inline)
を使用して外部ファイルを含めますが、処理はしません。
リリース v1.5.0
例: @import (inline) "not-less-compatible.css";
CSSファイルがLessと互換性がない場合にこれを使用します。これは、Lessはほとんどの既知の標準CSSをサポートしていますが、一部の場所でのコメントをサポートしておらず、CSSを変更せずにすべての既知のCSSハックをサポートしていないためです。
そのため、これを使用してファイルを出力に含め、すべてのCSSが1つのファイルに収まるようにすることができます。
@import (less)
を使用して、ファイル拡張子に関係なく、インポートされたファイルをLessとして扱います。
リリース v1.4.0
例
@import (less) "foo.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;
}
@import (optional)
を使用して、ファイルが存在する場合にのみファイルのインポートを許可します。 optional
キーワードがない場合、LessはFileErrorをスローし、見つからないファイルをインポートするときにコンパイルを停止します。
リリース v2.3.0
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は、セレクタに添付されるか、ルールセットに配置されます。セレクタパラメータを持つ疑似クラスのように見え、オプションでキーワード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はセレクタの最後に配置する必要があります。
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キーワードを含めることができます。1つのルールセットにextendを持つ複数のセレクタ
.big-division,
.big-bag:extend(.bag),
.big-bucket:extend(.bucket) {
// body
}
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はデフォルトでセレクタ間の完全一致を探します。セレクタが先頭にアスタリスクを使用するかどうかは重要です。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:visited
とlink:visited:hover
は同じ要素セットと一致しますが、extendはそれらを異なるものとして扱います。
link:hover:visited {
color: blue;
}
.selector:extend(link:visited:hover) {}
出力
link:hover:visited {
color: blue;
}
n番目の式の形式は重要です。n番目の式1n+3
とn+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は補間されたセレクタに添付できます。
変数を持つセレクタは一致しません
@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 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 */
}
典型的なユースケースは、基本クラスの追加を避けることです。たとえば、次のような場合です。
.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;
}
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;
}
もう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
は、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
では、保留中の各結合宣言に明示的な +
または +_
フラグが必要です。
既存のスタイルからプロパティを「ミックスイン」する
クラスセレクターと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を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にはプロパティだけでなく、セレクターも含めることができます。
例えば
.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に引数を渡す方法
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"
に似ています。 これにより、コードベースでセミコロンセパレータが不要になる場合があります。
例
.name(1, 2, 3; something, else)
.name(1, 2, 3)
.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を定義することは許容されます。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
であった場合、結果はより暗い色になります。
何が起こったのか説明します。
dark
を期待していたため、一致しませんでした。light
を期待していたため、一致しました。一致した mixin 定義のみが使用されました。変数は任意の値と一致し、バインドされます。変数以外のものは、それ自体と等しい値とのみ一致します。
arity(引数の数)で一致させることもできます。次に例を示します。
.mixin(@a) {
color: @a;
}
.mixin(@a, @b) {
color: fade(@a, @b);
}
ここで、.mixin
を単一の引数で呼び出すと、最初の定義の出力が得られますが、*2 つの*引数で呼び出すと、2 番目の定義、つまり @a
が @b
にフェードアウトしたものが得られます。
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 がある場合、すべてのルールが評価およびマージされ、その識別子を持つ最後の一致する値が返されます。これは 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 は、呼び出し元のスコープで表示および使用できます。例外は 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;
}
ループの作成
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%;
}
ガードは、単純な値や 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
リリース 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;
}
ルールセットを変数に割り当てる
リリース 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;
}
*/
これは、将来のリリースで削除される可能性のあるミックスインスコープ機能のリストです。
#ns {
.mixin-1() {
prop: @a;
}
}
.rule {
@a: one;
#ns.mixin-1();
}
/* OUTPUTS:
.rule {
prop: one;
}
*/
これは直感に反します、なぜなら
**推奨されるアプローチ**:ミックスインに表示したい変数を渡します。
#ns {
.mixin-1(@a) {
prop: @a;
}
}
.rule {
#ns.mixin-1(@a: one);
}
ミックスインは変数を呼び出し元のスコープにプッシュしますが、変数がローカルに定義されていない場合*のみ*です。
#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;
}
*/
これは直感に反します、なぜなら
また、マップを導入することで、変数値(およびミックスイン)を直接取得できます。
推奨されるアプローチ:
#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;
}
*/
非推奨の変数の動作と同様に、ミックスインも呼び出し元のスコープにプッシュされます。ただし、変数とは異なり、マージされたスコープミックスインと同じ名前のミックスインはマージされます。
#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
}
}
}
セレクター周辺の「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();
リリース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 ノードに変換されます)。
関数を呼び出したいが、何も出力したくない場合があります(後で使用する値を保存する場合など)。そのような場合は、関数から 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 プラグインは、これらのプロパティの 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 の使用」セクションの プリロードされたプラグイン を参照してください。