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

第6回mixinを作る(初歩編)

Twitter Bootstrapからmixinの使い方を読み解く

前回まででLESSの主だった記法はすべて紹介しました。

今回からはLESSの真骨頂であるmixinの作成に入ります。

まずはおさらいとして、第2回のmixinのサンプルコードを見てみましょう。

// LESS
.border-radius (@radius) {
  border-radius: @radius;
  -moz-border-radius: @radius;
  -webkit-border-radius: @radius;
}

#header {
  .border-radius(4px);
}


/* Compiled CSS */
#header {
  border-radius: 4px;
  -moz-border-radius: 4px;
   -webkit-border-radius: 4px;
}

このように、CSS3のベンダープリフィックスをまとめておくことにより、簡単に各ブラウザに対応したCSS3をまとめて宣言できるだけでなく、将来的に仕様の変更やベンダープリフィックスが不要になった際も、mixinを変更するだけで済みます。スピードと保守性を両立することができますね。

Twitter社が提供しているTwitter Bootstrapは、このような使い方を非常にうまく利用しています。

今回はそのTwitter Bootstrapで提供しているmixin.lessをかいつまんで読み解いてみましょう。

通常のダウンロードページではLESSから生成されたCSSファイルしか提供していないのですが、Twitter社のgithubページより生成前のLESSファイルをダウンロードすることができます。

ベンダープリフィックスをまとめる

mixin.lessでCSSのベンダープリフィックスをどのようにまとめているのか、おもだったものを見ていきましょう。

border-radius

これは先にご紹介したものと同様です。

// Border Radius
.border-radius(@radius) {
  -webkit-border-radius: @radius;
     -moz-border-radius: @radius;
          border-radius: @radius;
}

border-radiusの一箇所のみを指定

border-radiusの一箇所のみを指定する場合、特にwebkitとmozで縦と横の指定順が違うので、ミスをしがちです。

ブラウザ独自実装の非常に困った点なのですが、こういった記述こそmixinとして非常に有効です。

// Single Corner Border Radius
.border-top-left-radius(@radius) {
  -webkit-border-top-left-radius: @radius;
      -moz-border-radius-topleft: @radius;
          border-top-left-radius: @radius;
}
.border-top-right-radius(@radius) {
  -webkit-border-top-right-radius: @radius;
      -moz-border-radius-topright: @radius;
          border-top-right-radius: @radius;
}
.border-bottom-right-radius(@radius) {
  -webkit-border-bottom-right-radius: @radius;
      -moz-border-radius-bottomright: @radius;
          border-bottom-right-radius: @radius;
}
.border-bottom-left-radius(@radius) {
  -webkit-border-bottom-left-radius: @radius;
      -moz-border-radius-bottomleft: @radius;
          border-bottom-left-radius: @radius;
}

border-radiusの一辺を指定

これは前述のSingle Corner Border Radiusをさらに応用したものです。

CSSでは1箇所ずつしか角丸を記述できません。しかし、先ほどのmixinを以下のように入れ子にして、1回の指定で一辺(左上と右上/左上と左下など)の角丸を指定しています。

// Single Side Border Radius
.border-top-radius(@radius) {
  .border-top-right-radius(@radius);
  .border-top-left-radius(@radius);
}
.border-right-radius(@radius) {
  .border-top-right-radius(@radius);
  .border-bottom-right-radius(@radius);
}
.border-bottom-radius(@radius) {
  .border-bottom-right-radius(@radius);
  .border-bottom-left-radius(@radius);
}
.border-left-radius(@radius) {
  .border-top-left-radius(@radius);
  .border-bottom-left-radius(@radius);
}

もちろんmixinの入れ子を用いずに書くこともできます。しかし、記述が複雑化するだけでなく、CSSの仕様変更などに対応する際の工数も増え、保守性も悪くなってしまいます。以下のことを常に注意するようにしましょう。

  • mixin自体のコードのシンプル化
  • 生成されるCSSのシンプル化
  • LESSファイル全体の保守性

その他

その他、CSS3のベンダープリフィックスをまとめるためのTwitter Bootstrapオリジナルのmixinとしては下記のようなものがあります。

  • box-shadow
  • transition
  • rotate
  • scale
  • translate
  • skew
  • translate3d
  • backface-visibility
  • background-clip
  • background-size
  • box-sizing
  • user-select

記述を短縮する

単純なCSS3だけではなく、記述を短縮する便利なmixinもたくさんあります。

要素を中央寄せ

指定した要素を中央にレイアウトする際は、複数要素をほぼ必ずセットで記述するので、まとめておくと便利です。

以下の例では、指定した要素をブロック要素にして中央に配置しています。

// Center-align a block level element
// ----------------------------------
.center-block() {
  display: block;
  margin-left: auto;
  margin-right: auto;
}

widthとheightをまとめて記述

.size()では、widthとheightをまとめて記述できます。

.square()では、正方形のサイズ指定を1つの値で指定できます。

// Sizing shortcuts
// -------------------------
.size(@height, @width) {
  width: @width;
  height: @height;
}
.square(@size) {
  .size(@size, @size);
}

text-overflowを記述する

text-overflowは、1行からあふれた場合に文末を「…」にして省略するプロパティです。これはoverflowとwhite-spaceを一緒に記述しないと効果がないので、必ずセットで書くのにmixinはうってつけです。

// Text overflow
// -------------------------
// Requires inline-block or block for proper styling
.text-overflow() {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

clearfixを記述する

CSSハックとしてはおそらく一番メジャーで、かつ年々進化するcleafix。

特に対応ブラウザによって省略できる記述も多いので、mixinにとても向いています。

.clearfix {
  *zoom: 1;
  &:before,
  &:after {
    display: table;
    content: "";
    // Fixes Opera/contenteditable bug:
    // http://nicolasgallagher.com/micro-clearfix-hack/#comment-36952
    line-height: 0;
  }
  &:after {
    clear: both;
  }
}

短縮した記述量はわずかではありますが、mixinをうまく利用すれば簡単な記述でメンテナンス性が高くなるだけでなく、⁠何の目的でプロパティを指定しているか」がわかりやすくなるので、コードを読み解くのが容易になります。一見地味なmixinも、色々な優位性が出てくるのです。

mixinのセレクタを用いてグルーピングをする

Twitter Bootstrapのmixin.lessを読んでいくと、下記のような記述が出てきます。

#gradient {
  .horizontal(@startColor: #555, @endColor: #333) {
     ~中略~  }
  .vertical(@startColor: #555, @endColor: #333) {
     ~中略~
  }
  .directional(@startColor: #555, @endColor: #333, @deg: 45deg) {
     ~中略~
  }  .vertical-three-colors(@startColor: #00b3ee, @midColor: #7a43b6, @colorStop: 50%, @endColor: #c3325f) {
     ~中略~
  }  .radial(@innerColor: #555, @outerColor: #333)  {
     ~中略~
  }  .striped(@color, @angle: 45deg) {
     ~中略~
  }
}

中身の詳細は解説は省略しますが、これらはCSSで記述をすると非常に冗長になりがちなグラデーションの記述を簡素化するものです。横方向/縦方向など、よく使うグラデーションパターンをまとめてあります。

しかし今回注目したいのは、#gradientというidの中に.horizontalや.verticalというclassが入れ子になっており、そこがmixinになっていること。

今まではなんとなくclassで指定をしてきましたが、これらのmixinはどのように利用するのでしょうか?

たとえば

//LESS
#gradient {
  .horizontal(@startColor: #555, @endColor: #333) {
     ~中略~
  }
}

を利用する際は、以下のようにCSSと同様セレクタを続けて記述します。

//LESS
div {
  #gradient > .horizontal(#FFFFFF,#000000);
}

これが何階層入れ子になっていても指定の仕方は変わりません。

では、なぜこんな指定の仕方をわざわざするのでしょうか?

それは普段CSSを記述するのと同じように

  • 同じクラス名があった場合に競合を避ける

ため、それに加えて

  • 同じジャンルのmixinをグルーピングさせる

ためです。

今回のTwitter Bootstrapの例ではグラデーションに関するmixinをまとめるために、#gradientというidでくくられていると考えられます。

うまくグルーピングして可読性を高める

入れ子を使い過ぎると、mixinを呼び出す際の記述が長くなってしまいます。ただ、今回の例では「.horizontal」という名前だけではどちらにせよ何のためのmixinだか判別できません。入れ子にしない場合でも「.gradient-horizontal」などの名前になったでしょう。

このように、すべてが「.gradient-◯◯」というような名前になってしまうならば、むしろLESSの特徴を活かして入れ子にしてしまった方が、見た目もすっきりしてわかりやすいですね。

すべてをグルーピングしてしまうと結局冗長な記述になってしまいますが、適宜同様のmixinをまとめることで、可読性が高まります。

また、複数のサイトでコードを使いまわしたり、mixinを公開して配布する場合は、他と絶対に競合させないために、固有のidの下にmixinを記述していくのも良い方法です。

今回はTwitter Bootstrapを題材に取り上げましたが、mixinを集めたものとして、他にもPreboot.lessやLESS Elementsなどがあります。それぞれ独自の工夫がされており、これらを応用して自分のオリジナルmixin集を作るもおすすめです。

Preboot.less
http://www.markdotto.com/bootstrap/
LESS Elements
http://lesselements.com

次回はこれらをさらに改良し「引数が◯◯だったとき」など、条件分岐を加えてより複雑なmixinを作成していきます。お楽しみに。

おすすめ記事

記事・ニュース一覧