【less】今更始めるlessの基本文法とtips(1) - ネストと変数編

前書き

お仕事の方で5000ステップほどあるCSSを編集したりするんですが、人間が管理するにはあまりにも厳しいので、lessを導入することにしました。

流石に1から自分の手で書き直すのは辛いのでcss2lessを使って一度変換し、後は黙々とmixinなりなんなりを作るだけです。

CSSを知っていれば文法的に難しいところもほとんどなかったんですが、ちょっとわかりづらかったり、そのうち忘れそうなところもいくつかあったので適当にメモしていきます。

文法そのものの解説はぐぐるといっぱいでてきますが、公式のドキュメントがやはり最強でした。文章量もそんなにないので、下手にどこかの解説を読むよりこっちを全部読んだ方が早い気がします。

コンパイラのインストール

基本的にはnpm -g install lessだけでいいんですが、minifyするために必要なプラグインが別途用意されているのでnpm install -g less-plugin-clean-cssもしておきましょう。

セレクタのネスト

基本形式

lessではセレクタをネストして書くことができます。例えばこんなCSSがあったとします。

#header nav ul li {
  display: inline;
}

#header hoge {
  color: #000;
}

こんな風に書けます。

#header {
  nav {
    ul {
      li {
        display: inline;
      }
    }
  }
  
  #hoge {
    color: #000;
  }
}

疑似要素

:hover:afterなどの疑似要素は&を使うことで簡単に宣言できます。

// less
#header {
  background-color: #fff;
  
  &:hover { // #header:hover
    background-color: #000;
  }
  
  div {
    &:hover { // #header div:hover
      background-color: #ff0;
    }
  }
}

/* css */
#header {
  background-color: #fff;
}
#header:hover {
  background-color: #000;
}
#header div:hover {
  background-color: #ff0;
}

&は単純にセレクタ名を格納した擬似変数なので、疑似要素の定義以外にもこんなことができます。

// less
#header {
  &-hoge {
    color: #fff;
  }
  &-fuga {
    color: #000;
  }
}

/* css */
#header-hoge {
  color: #fff;
}
#header-fuga {
  color: #000;
}

メディアクエリのネスト

ネストした要素内でそれぞれのメディアクエリを書くことができます。さらに、メディアクエリ自体のネストも可能です。

// less
#header {
  font-size: 100%;
  @media screen and (max-width: 768px) {
    font-size: 90%;
  }
  @media screen and (max-width: 560px) {
    font-size: 80%;
  }
  
  div {
    @media screen and (max-width: 768px) {
      color: #ff0;
      @media screen and (min-width: 560px) {
        color: #f00;
      }
    }
  }
}

/* css */
#header {
  font-size: 100%;
}
@media screen and (max-width: 768px) {
  #header {
    font-size: 90%;
  }
}
@media screen and (max-width: 560px) {
  #header {
    font-size: 80%;
  }
}
@media screen and (max-width: 768px) {
  #header div {
    color: #ff0;
  }
}
@media screen and (max-width: 768px) and screen and (min-width: 560px) {
  #header div {
    color: #f00;
  }
}

出来上がったCSSは中々おぞましいものになりますが、まぁ、気にしないことにしましょう。

@keyframes@font-faceの扱い

自動で外に吐き出されますので、どんどんネスト内で書きましょう。

// less
#header {
  background-color: #fff;
  div {
    @font-face {
      font-family: 'hoge';
      src: url('/hoge.ttf');
    }
    font-family:'hoge';
  }
}

/* css */
#header {
  background-color: #fff;
}
#header div {
  font-family: 'hoge';
}
@font-face {
  font-family: 'hoge';
  src: url('/hoge.ttf');
}

変数

変数宣言

@識別子:値と言う形で変数宣言が可能です。

// less
@base-color: #fff;

div {
  color: @base-color;
}

/* css */
div {
  color: #ffffff;
}

変数として宣言できるもの

割となんでもいけます。

// less
// カラーコード
@base-color: #fff; 
@rgba-color: rgba(0,0,0,0.5); // RGBAもOK

div {
  color: @base-color;
  background-color: @rgba-color;
}

// もちろん数値もOK
@width: 100%;
@height: 50px;
@margin: 0;

div {
  width: @width;
  height: @height;
  margin: @margin;
}

// URLなんかもOK
@image-dir: "../images";
div {
  background-image: url("@{image-dir}/image.jpg");
}

// 変数にCSSのルールセットを定義することも可能
@rules: {
  color: @base-color;
  background-color: @rgba-color;
  width: @width;
  height: @height;
  margin: @margin;
  background-image: url("@{image-dir}/image.jpg");
};

div {
  @rules(); // ルールセットを展開する場合は"()"
}

/* css */
div {
  color: #ffffff;
  background-color: rgba(0, 0, 0, 0.5);
}
div {
  width: 100%;
  height: 50px;
  margin: 0;
}
div {
  background-image: url("../images/image.jpg");
}
div {
  color: #ffffff;
  background-color: rgba(0, 0, 0, 0.5);
  width: 100%;
  height: 50px;
  margin: 0;
  background-image: url("../images/image.jpg");
}

変数として宣言できるけど使い道が微妙なもの

セレクタを宣言しておくことも可能です。複数セレクタを一まとめにしたいとき便利かもしれません。

// less
@copyright: #footer address#copyright;

@{copyright} {
  color: #000;
}

/* css */
#footer address#copyright {
  color: #000;
}

また、プロパティ名も宣言できます。長いプロパティ名を省略するとき…とか?

// less
@ff: font-family;

div {
  @{ff}: monospace;
}

/* css */
div {
  font-family: monospace;
}

変数名そのものを宣言しておくことも可能です。この辺まで来ると普通に可読性が落ちそうです。

// less
@var-name: "mono";
@mono: monospace;
@ff: font-family;

div {
  @{ff}: @@var-name;
}

/* css */
div {
  font-family: monospace;
}

メディアクエリを変数として宣言

メディアクエリの条件を変数として宣言しておくことも可能です。

// less
@tablet: ~"screen and (max-width: 768px)"; // "()"が入っているものは"~"をつけてエスケープする

@media @tablet {
  div {
    color: #fff;
  }
}

/* css */
@media screen and (max-width: 768px) {
  div {
    color: #fff;
  }
}

変数の型

厳密にはlessに型と言う概念はないんですが、型チェックっぽい関数が用意されています。

該当するもの該当しないもの
Number
  • 1234
  • 56px
  • 7.8%
  • 9em
  • #ff0
  • blue
  • "string"
  • keyword
  • url(...)
  • { color: #fff; }
String
  • "string"
  • #ff0
  • blue
  • 1234
  • 56px
  • 7.8%
  • 9em
  • keyword
  • url(...)
  • { color: #fff; }
Color
  • #ff0
  • blue
  • "string"
  • 1234
  • 56px
  • 7.8%
  • 9em
  • keyword
  • url(...)
  • { color: #fff; }
Keyword
  • keyword
  • #ff0
  • blue
  • "string"
  • 1234
  • 56px
  • 7.8%
  • 9em
  • url(...)
  • { color: #fff; }
Url
  • url(...)
  • #ff0
  • blue
  • "string"
  • 1234
  • 56px
  • 7.8%
  • 9em
  • keyword
  • { color: #fff; }
Pixel
  • 56px
  • #ff0
  • blue
  • "string"
  • 1234
  • 7.8%
  • keyword
  • url(...)
  • { color: #fff; }
Em
  • 9em
  • #ff0
  • blue
  • "string"
  • 1234
  • 56px
  • 7.8%
  • keyword
  • url(...)
  • { color: #fff; }
Percentage
  • 7.8%
  • #ff0
  • blue
  • "string"
  • 1234
  • 56px
  • 9em
  • keyword
  • url(...)
  • { color: #fff; }
Ruleset
  • { color: #fff; }
  • #ff0
  • blue
  • "string"
  • 1234
  • 56px
  • 7.8%
  • 9em
  • keyword
  • url(...)

スコープ

変数にはスコープがあります。あるセレクタ内で宣言された変数は、他のセレクタから呼び出せません。

@global-color: #000;

#hoge {
  @inner-color: #fff;
  color: @global-color;
  
  div {
    color: @inner-color;
  }
}

#fuga {
  color: @inner-color; // スコープ外なので呼び出せない
}

他のスコープで宣言された変数を書き換えると、そのスコープ内でのみ値が書き換わります。

// less
@global-color: #000;

#hoge {
  color: @global-color;
}

#fuga {
  @global-color: #fff; // fugaで@global-colorの値を変更する
  color: @global-color;
}

#piyo {
  color: @global-color;
}

/* css */
#hoge {
  color: #000000;
}
#fuga {
  color: #ffffff;
}
#piyo {
  color: #000000; /* piyoの@global-colorは変わらない */
}

ただし、同スコープ内で変数の値を書き換えると、変更した場所に関わらず後に宣言した値が適用されます。

// less
@global-color: #000;

#hoge {
  color: @global-color;
}

@global-color: #fff; // hogeの後に@global-colorを書き換える

#fuga {
  color: @global-color;
}

#piyo {
  color: @global-color;
}

/* css */
/* @global-colorの値はすべて#fffになる */
#hoge {
  color: #ffffff;
}
#fuga {
  color: #ffffff;
}
#piyo {
  color: #ffffff;
}

なるべくであればグローバルなスコープでの変数は書き換えないようにしましょう。危なっかしいので…。

まとめ

すごい長くなりそうなので続き物にします。

次回はmixin関連を予定。早ければ明日に。

(2015/08/30)書きました。:-)