以下のサイトを参考にまとめた「LESS」の基本的な使い方のメモ。詳細(解説等)は以下のサイトを参考にしてください。
LESS 日本語ページ「The dynamic stylesheet language」
gihyo.jp 「LESSで3倍ラクするスマートフォンコーディング」
CSS のセレクタを入れ子にすることができる
//LESS #header { h1 { font-size: 26px; font-weight: bold; } p { font-size: 18px; a { text-decoration: none; &:hover { color: red; } } } }
コンパイルされた CSS
#header h1 { font-size: 26px; font-weight: bold; } #header p { font-size: 18px; } #header p a { text-decoration: none; } #header p a:hover { color: red; }
「&」には「& を指定した親要素に,& 以降のセレクタをつなげる」という意味がある。
「&」のあとにスペースを入れると、普通にネストした場合と同様になってしまう。
//LESS .foo { background: red; &.var { background: blue; } } a { color: red; &:hover { color: blue; } }
コンパイルされた CSS
.foo { background: red; } .foo.var { background: blue; } a { color: red; } a:hover { color: blue; }
//Less .child, .sibling { .parent & { color: black; } }
コンパイルされた CSS
.parent .child, .parent .sibling { color: black; }
//Less .child, .sibling { & + & { color: red; } }
コンパイルされた CSS
.child + .child, .child + .sibling, .sibling + .child, .sibling + .sibling { color: red; }
たとえば「”eco”という class が body に付いているときのみ,背景を緑にする」には、「&」を利用すると,「親要素に body.eco があった場合」という記述ができる。
//Less .foo { .var { background: red; } body.eco & .var { background: green; } }
コンパイルされた CSS
.foo .var { background: red; } body.eco .foo .var { background: green; }
//Less @color : #0B68B5; @color2: @color + #663333; //色の演算も可能 @h1size: 24px; @h2size: round(@h1size * 0.8); //math関数の利用 h1 { color: @color; font-size: @h1size; } h2 { color: @color2; font-size: @h2size; }
コンパイルされた CSS
h1 { color: #0b68b5; font-size: 24px; } h2 { color: #719be8; font-size: 19px; }
//Less @foo: "This is Foo."; @bar: 'foo'; #foo { content: @@bar; //@bar は 'foo' なので @@bar は @foo }
コンパイルされた CSS
#foo { content: "This is Foo."; }
//Less .rounded-corners (@radius: 5px) { -webkit-border-radius: @radius; -moz-border-radius: @radius; -ms-border-radius: @radius; -o-border-radius: @radius; border-radius: @radius; } #header { border: 1px solid #ccc; .rounded-corners; } #main { border: 2px solid #999; .rounded-corners(10px); }
コンパイルされた CSS
#header { border: 1px solid #ccc; -webkit-border-radius: 5px; -moz-border-radius: 5px; -ms-border-radius: 5px; -o-border-radius: 5px; border-radius: 5px; } #main { border: 2px solid #999; -webkit-border-radius: 10px; -moz-border-radius: 10px; -ms-border-radius: 10px; -o-border-radius: 10px; border-radius: 10px; }
@arguments にはミックスインの中で定義した引数を渡すことができ、これにより個別に値の定義をしなくて済む。
//Less .box-shadow (@x: 0, @y: 0, @blur: 1px, @color: #000) { box-shadow: @arguments; -moz-box-shadow: @arguments; -webkit-box-shadow: @arguments; } #header { .box-shadow(2px, 5px); }
コンパイルされた CSS
#header { box-shadow: 2px 5px 1px #000000; -moz-box-shadow: 2px 5px 1px #000000; -webkit-box-shadow: 2px 5px 1px #000000; }
四則演算を用いて値を指定することができ、変数値を用いて計算するときなどに便利。
例えば、ある変数を文字サイズの基準値として設定すれば、その変数の値を変更するだけで,すべての文字サイズの比率を保ったまま文字の大きさを変更することができる。余白やマージンの値などにも利用すると便利。
//Less @baseFontSize: 12px; //文字サイズの基準値 h1 { font-size: @baseFontSize * 2; //基準値の2倍 } h2 { font-size: round(@baseFontSize * 1.8); //基準値の1.8倍を四捨五入 }
コンパイルされた CSS
h1 { font-size: 24px; } h2 { font-size: 22px; }
LESS は数字の値に対して利用できる math 関数を用意している。値をパーセンテージに変換させたい場合はパーセンテージ関数を利用することができる。
//Less round(1.67); // `2` を返す(四捨五入) ceil(2.4); // `3` を返す(切り上げ) floor(2.6); // `2` を返す(切り下げ) percentage(0.5); // `50%` を返す
以下は Math 関数を使って、最初の li 要素の幅は34pxに、それ以外の li 要素の幅は33pxにする例。
//Less @ulWidth: 100px; @lis: 3; ul { width: @ulWidth; li { width: floor(@ulWidth/@lis); //切り下げ &:first-child { width: ceil(@ulWidth/@lis); 切り上げ } } }
コンパイルされた CSS
ul { width: 100px; } ul li { width: 33px; } ul li:first-child { width: 34px; }
CSSの「@import:url()」は,パフォーマンス的な問題があるが、LESSの「@import」ではそのような心配がない。
そのため,機能ごとにCSSを分割して,コンパイル時にひとまとめに結合すると良い。
.less 拡張子は任意のため以下の2行とも同じ意味。
//Less @import "lib.less"; @import "lib";
通常のCSSファイルをインポートし、LESSでの処理が必要ない場合、.css 拡張子を利用する。
//Less @import "lib.css";
変数やミックスインはローカル内をまず検索し、見つからなければ 親スコープを検索し、最後にグローバルを検索する。
//Less @var: red; //グローバル #page { @var: white; //ローカル #header { color: @var; // white } } #footer { color: @var; // red }
コンパイルされた CSS
#page #header { color: #ffffff; } #footer { color: #ff0000; }
特定ページでしか使わない変数などは,グローバルな変数を宣言するのではなく,ページごとに id を振り,その id の中で変数を宣言すると良い。
//Less @pageColor: yellow; //指定ページ意外の色(グローバル) body { background: @pageColor; //yellow(グローバル) #top { @pageColor: red; //ローカル(トップページ) background: @pageColor; //red } #about { @pageColor: blue; //ローカル(Aboutページ) background: @pageColor; //blue } #contact { @pageColor: green; //ローカル(Contactページ) background: @pageColor; //green } }
body { background: #ffff00; } body #top { background: #ff0000; } body #about { background: #0000ff; } body #contact { background: #008000; }
構成やカプセル化のために変数やミックスインをグループ化することができる。
以下は #foo に変数やミックスインを1つにまとめて、#bar a で.button ミックスインを利用する例。
//Less #foo { .button () { display: block; border: 1px solid black; background-color: grey; &:hover { background-color: white } } .box { ... } .border { ... } } #bar a { color: red; #foo > .button; }
コンパイルされた CSS
#bar a { color: red; display: block; border: 1px solid black; background-color: grey; } #bar a:hover { background-color: #ffffff; }
色はまず HSL カラースペース(色空間)に変換され、チャネルレベルで操作することができる。
//Less lighten(@color, 10%); // @color より 10% 明度が高い値を返す darken(@color, 10%); // @color より 10% 明度が低い値を返す saturate(@color, 10%); // @color に 10% の彩度を追加した値を返す desaturate(@color, 10%); // @color から 10% の彩度を削減した値を返す spin(@color, 10); // @color から 10 度色相が大きい値を返す spin(@color, -10); // @color から 10 度色相が小さい値を返す //spinのみ,割合の値の単位が%ではない fadein(@color, 10%); // @color から 10% 透明度が高い値を返す fadeout(@color, 10%); // @color から 10% 透明度が低い値を返す fade(@color, 50%); // @color の 50% の透明度を持つ値を返す mix(@color1, @color2); // @color1 と @color2 をミックスした値を返す contrast(@color1, @darkcolor, @lightcolor); // もし@color1が >50% 以上の luma(例: 明るい色)の場合に @darkcolor を返し、そうでなければ @lightcolor を返す
lighten()、darken()、saturate()、desaturate()は spin() 同様に負(マイナス)の値も指定できる。以下の2つは同じカラーコードになる。
//Less lighten(@color, 10%); //@colorより 10 %明度が高い色を計算する darken(@color, -10%); //@colorより -10 %明度が低い色(=10%明度が高い色を計算する)
カラー関数を使ってミックスイン(.bg_gradient)を作成し、#foo、#bar に適用する例
//Less .bg_gradient(@color:#FF3300) { background: linear-gradient( @color, darken(@color, 30%) ); } #foo { .bg_gradient; } #bar { .bg_gradient(fade(green, 20%)); }
コンパイルされた CSS
#foo { background: linear-gradient(#ff3300, #661400); } #bar { background: linear-gradient(rgba(0, 128, 0, 0.2), rgba(0, 0, 0, 0.2)); }
//Less hue(@color); // @color の色相チャネルの値を返す saturation(@color); // @color の彩度チャネルの値を返す lightness(@color); // @color の明度チャネルの値を返す alpha(@color); // @color の透明度チャネルの値を返す luma(@color); // @color の luma 値(知覚明度)を返す
他のプログラム言語と同様,LESS でも’(シングルクォーテーション)や”(ダブルクォーテーション)で囲ったものは,すべて文字列として扱う。
変数は ruby や PHP と同じように @{name} と定義することで文字列を挿入することができる。
url の宣言に利用する例
//Less @base-url: "https://www.webdesignleaves.com/"; #foo { background-image: url("@{base-url}/images/bg.png"); }
コンパイルされた CSS
#foo { background-image: url("https://www.webdesignleaves.com//images/bg.png"); }
CSS シンタックスにおいて有効ではないか、あるいは LESS が認識できない固有のシンタックスを利用する必要がある場合は「~」を文字列の前に付けることで出力することができる。エスケープすることで、カンマなど LESS の特定の機能を持つ文字を出力することが可能。
また、エスケープされた文字列内では、変数を記述しても通常の文字列として認識されるため、エスケープ内で変数を利用するには、@{(変数名)}とする必要がある。
//Less .class { filter: ~"progid:DXImageTransform.Microsoft.AlphaImageLoader(src='image.png')"; } .opacity(@opacity) { opacity: @opacity; // IE8 filter @opacity-ie: (@opacity * 100); filter: ~"alpha(opacity=@{opacity-ie})"; } .foo { .opacity(0.5); }
コンパイルされた CSS
.class { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='image.png'); } .foo { opacity: 0.5; filter: alpha(opacity=50); }
カンマが含まれる場合のエスケープの例
//Less .box-shadow(@arg){ -moz-box-shadow: @arg; -webkit-box-shadow: @arg; box-shadow: @arg; } .shadow1{ //複数のbox-shadowではカンマが含まれるためエスケープ(この場合改行するとエラー) .box-shadow(~"0 1px 2px rgba(255,255,255,0.2) inset, 0 -1px 2px rgba(0,0,0,0.15) inset"); } .shadow2{ //引数を変数に入れて指定することも可能(この場合改行も使える)結果は.shadow1 と同じ。 @arg: 0 1px 2px rgba(255,255,255,0.2) inset, 0 -1px 2px rgba(0,0,0,0.15) inset; .box-shadow(@arg); }
コンパイルされた CSS
.shadow1 { -moz-box-shadow: 0 1px 2px rgba(255,255,255,0.2) inset, 0 -1px 2px rgba(0,0,0,0.15) inset; -webkit-box-shadow: 0 1px 2px rgba(255,255,255,0.2) inset, 0 -1px 2px rgba(0,0,0,0.15) inset; box-shadow: 0 1px 2px rgba(255,255,255,0.2) inset, 0 -1px 2px rgba(0,0,0,0.15) inset; } .shadow2 { -moz-box-shadow: 0 1px 2px rgba(255, 255, 255, 0.2) inset, 0 -1px 2px rgba(0, 0, 0, 0.15) inset; -webkit-box-shadow: 0 1px 2px rgba(255, 255, 255, 0.2) inset, 0 -1px 2px rgba(0, 0, 0, 0.15) inset; box-shadow: 0 1px 2px rgba(255, 255, 255, 0.2) inset, 0 -1px 2px rgba(0, 0, 0, 0.15) inset; }
/(スラッシュ)などの記号をプロパティの値として記述する場合の例。「’」で囲ったものは文字列として認識されるが,それをさらに「~」でエスケープすることにより,「/」を「割る」ではなく「/」という文字(記号)のまま認識させることができる。
//Less .class1 { border-radius: 100px ~'/' 50px; } .class2 { border-radius: 100px / 50px; //「100px÷50px」という計算結果が出力されてしまう }
コンパイルされた CSS
.class1 { border-radius: 100px / 50px; } .class2 { border-radius: 2px; }
//Less @foo: 'Hello'; @bar: 'World'; div::before { content: `@{foo}.length`; //文字列の長さを調べる:5 } div::before { content: `@{foo}.slice(0, 2)`; //文字列の一部を切り取る:"He" } div::before { content: `@{foo}.match(/Hell/) + "!"`; //正規表現で該当した部分を取り出して「"!"」を連結:"Hell!" } div::before { content: `@{bar}.replace('World','Universe')`; //該当した部分を置き換える:"Word" }
コンパイルされた CSS
div::before { content: 5; } div::before { content: "He"; } div::before { content: "Hell!"; } div::before { content: "Universe"; }
パラメータによってミックスインの挙動を変更させる。
以下は第1パラメータの値によって挙動を変更させる例。
//Less .mixin_switch (dark, @color) { color: darken(@color, 10%); } .mixin_switch (light, @color) { color: lighten(@color, 10%); } .mixin_switch (@_, @color) { display: block; } @switch1: light; @switch2: dark; .class1 { .mixin_switch(@switch1, #888); } .class2 { .mixin_switch(@switch2, #888); }
コンパイルされた CSS
.class1 { color: #a2a2a2; display: block; } .class2 { color: #6f6f6f; display: block; }
引数の個数に対してマッチさせる(引数の個数により挙動を変更させる)例。
//Less .mixin_pn (@a) { color: @a; } .mixin_pn (@a, @b) { color: fade(@a, @b); } .class1 { .mixin_pn(#888); } .class2 { .mixin_pn(#888, 50%); }
コンパイルされた CSS
.class1 { color: #888888; } .class2 { color: rgba(136, 136, 136, 0.5); }
//Less .mixin_color (@a) when (lightness(@a) >= 50%) { background-color: black; } .mixin_color (@a) when (lightness(@a) < 50%) { background-color: white; } .mixin_color (@a) { color: @a; } .class1 { .mixin_color(#eee) } .class2 { .mixin_color(#666) } [/code] コンパイルされた CSS [code] .class1 { background-color: black; color: #eeeeee; } .class2 { background-color: white; color: #666666; } [/code] 特定のベンダープレフィックスのみを付ける例。変数(@webkit、@moz)の値を変更することにより出力を変更できる。 [code] //Less @webkit: true; @moz: false; .border-radius(@radius)when(@webkit) { -webkit-border-radius: @radius; } .border-radius(@radius)when(@moz) { -moz-border-radius: @radius; } .border-radius(@radius) { border-radius: @radius; } .foo { .border-radius(5px); } [/code] コンパイルされた CSS [code] .foo { -webkit-border-radius: 5px; border-radius: 5px; } [/code] <h4>「and」キーワード</h4> 条件の追加(&& のようなもの)//Less .mixin (@a) when (ispixel(@a)) and (@a > 10) { margin: @a; } #foo { .mixin(20px); } #bar { .mixin(5px); }
コンパイルされた CSS(#bar は(@a > 10) を満たさない)
#foo { margin: 20px; }
否定の条件
//Less .mixin (@b) when not (@b > 10){ margin: @b; } #foo { .mixin(20px); } #bar { .mixin(5px); }
コンパイルされた CSS(#foo は not (@b > 10) 「10より大きくない」を満たさない)
#bar { margin: 5px; }
いずれかの条件が真の場合はマッチとして扱われる。
//Less
.mixin (@a) when (@a > 10), (@a < -10){
margin: @a;
}
#foo {
.mixin(20px);
}
#bar {
.mixin(-50px);
}
#not {
.mixin(-3px);
}
[/code]
コンパイルされた CSS(#not はいずれも満たしていない。)
[code]
#foo {
margin: 20px;
}
#bar {
margin: -50px;
}
[/code]