LESSで3倍ラクするスマートフォンコーディング

第3回LESS記法について(中級編:ネストの応用)

前回ご紹介したネストは、階層構造をわかりやすくするとともに、無駄な繰り返しの記述を減らし、コードを速く書くことができる便利な記法です。今回ご紹介する応用記法を利用すれば、それらにさらに磨きをかけることができます。

ネスト時の変数のスコープ(参照範囲)を理解する

変数の内容は、要所で新たに定義しなおすことができます。

たとえば以下の例では、最初に@varという変数の値をredとしていますが、header内でwhiteと定義しなおしています。

// LESS
@var: red;
header {
     @var: white;
     nav {
          background: @var;     //headerで宣言された@var(white)を参照
     }
}
footer {
     background: @var;     //一番最初に宣言したグローバル変数の@var(red)を参照;
}


/* Compiled CSS */
header nav {
     background: #ffffff;
}
footer {
     background: #ff0000;
}

とはいえ、変数の値はどこでも自由に定義して良いわけではありません。

変数は以下の流れでスコープ(参照範囲)が決まる点に注意する必要があります。

  1. 変数が実際に記述されたセレクタに@varがないかどうか探す
  2. なければ、その親セレクタ(DOM上ではなくLESSの宣言上のもの)を探す
  3. なければ、そのさらに親セレクタを探す
  4. 最後はグローバルな(セレクタの中にない)変数を参照する

同じ変数を定義しなおすメリットとは

もちろん、毎回違う変数を宣言しなおしても問題はありません。しかし、あえて同じ変数を定義しなおすのは、下記のメリットがあるためです。

  • スコープ外には影響を及ぼさないため、参照範囲内では他範囲への影響を考えず自由に宣言ができ、例外指定や条件ごとの指定が容易
  • 似た内容を宣言する場合、同じ変数名で宣言しなおした方がわかりやすい
  • 余計な変数名を増やすことで他の変数と干渉してしまうトラブルが起こりにくい

このため、特定ページでしか使わない変数などは、グローバルな変数を宣言してしまうのではなく、ページごとにidを振って、そのidの中で変数を宣言すると良いでしょう。

たとえば、ページごとに背景色が違う場合は、以下のように書くことができます。

//指定ページ意外の色
@pageColor: yellow;
background: @pageColor;     //yellow
//トップページ
#top {
     @pageColor: red;
     background: @pageColor;     //red
}
//会社概要ページ
#company {
     @pageColor: blue;
     background: @pageColor;     //blue
}
//FAQページ
#faq {
     @pageColor: green;
     background: @pageColor;     //green
}

このように、ページごとのidの中でならば、どのページでも「@pageColor」など同じ名前で宣言できます。毎回違う名前で宣言してしまうよりもずっと可読性が良く、わかりやすいですね。

今回のような単調な繰り返しであれば、前回ご紹介したmixinでまとめてしまうのも良いでしょう。

変数定義の注意点

上記の例では同じ変数名で異なる値を宣言してみましたが、1つだけ注意点があります。

同じスコープで、同じ変数に、違う値を宣言してはいけません。

プログラミング言語では、⁠変数」というものは、随時その値を変更してくことができます。

しかしLESSでは、異なるスコープであれば異なる値を宣言できますが、同じスコープでは後で宣言した内容が全範囲において優先されてしまうのです。

たとえば以下の例では、一見初めのheaderには直前で宣言されているredが適応されそうに思えます。しかし同一スコープ内の場合、全範囲において、後から宣言されたblueが適応されてしまいます。

@foo: red;
header {
     background: @foo;     //後で宣言された@fooを参照→blue;
}

@foo: blue;
footer {
     background: @foo;     //後で宣言された@fooを参照→blue;
}

変数(Variables)と名前が付いていますが、実質的には定数のようなものなのです。

このような宣言の仕方は、どこを修正すればどのような変化が起きるのか、第三者がコードを見たときにわからないので避けるべきでしょう。

スコープを理解して同セレクタ内での干渉に注意しておけば、悩まずに、そしてわかりやすくLESSを記述できます。

ネストの応用 ~&で複数の要素を並列に指定する

ネストは基本的にHTMLの階層構造にならってCSSを記述していく方法です。

しかし、以下のCSSのように、複数のclass指定や、:link・:hoverのように、階層構造ではなく並列に指定することもよくありますよね。

/*CSS*/
.foo {
     background: red;
}
.foo.var {
     background: blue;
}

a {
     color: red;
}
a:hover {
     color: blue;
}

LESSでは、⁠&(アンパサンド⁠⁠」を利用することで、このような複数のclass指定や、擬似要素/擬似クラスも階層構造で記述できます。

//LESS
.foo {
     background: red;
     &.var {
          background: blue;
     }
}

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


/* Compiled CSS */
.foo {
     background: red;
}
.foo.var {
     background: blue;
}

a {
     color: red;
}
a:hover {
     color: blue;
}

「&」には「&を指定した親要素に、&以降のセレクタをつなげる」という意味があります。つまり「&」のあとにスペースを入れてしまうと、普通にネストした場合と同様になってしまうので気をつけてください。

"ios"というclassがbodyに付いているときのみ、背景を青にするには

この「&」は他にも非常に強力な利用法があります。

たとえば「"ios"というclassがbodyに付いているときのみ、背景を青にする」という指定をすることを考えてみましょう。

そのような指定は今までのネストの書き方では不可能なので、そのネストとは別に記述する必要が出てきます。

しかし「&」を利用すると、⁠親要素にbody.iosがあった場合」という記述がかんたんにできるのです。

//LESS
.foo {
     .var {
          background: red;
     }
     body.ios & .var {
          background: blue;
     }
}

/* Compiled CSS */
.foo .var {
     background: red;
}
body.ios .foo .var {
     background: blue;
}

ネストの階層構造にすると少し違和感を感じるかもしれませんが、⁠&」の前に記述したセレクタを一番前に持ってきて、それ以降のセレクタは普段のルールどおりに生成されます。

これにより、⁠"ios"というclassがbodyに付いているときのみ背景を青にする」といった記述も、その色指定の前後で行えるようになります。場合分けの指定を近くに書いておけるので、可読性が上がり、修正時のミスなども減らすことができます。

iOSとAndroidの両方に対応させる場合など、どうしても同一の記述ができない場合は多いですが、そういった際にとても強力な手助けとなるでしょう。

以上、前回ご紹介したネストをさらに魅力的なものにする活用法をご紹介しました。これらの記法は、一度慣れてしまうと手放せず、日常的に使えるものとなるしょう。

次回は変数で宣言された色や数値の計算方法などをご紹介します。ぜひお楽しみに!

おすすめ記事

記事・ニュース一覧