あと味

たくさん情報を食べて、たくさん発信すると、あとになって味わい深い。

SassでCSS Spritesをなるべく簡単に書きたい

前段

Sass始めました。くそ便利ですねこれ。

したいこと

以下のような幅の違う横長なナビゲーションがあると想定して、これをCSS Spritesを使ってなるべく簡単にCSSを書きたい。

CSS Spritesは手計算でやるとくそメンドイので。

┏━━━┳━━━━━┳━┳━━┳━━━┓
┗━━━┻━━━━━┻━┻━━┻━━━┛

前提1 Sprites画像

ナビゲーションはホバー時に画像が置換される。

そのSprites画像は以下のように上段に通常のナビゲーションの画像、下段にホバー時のナビゲーションの画像がくっついていると仮定する。

┏━━━┳━━━━━┳━┳━━┳━━━┓
┣━━━╋━━━━━╋━╋━━╋━━━┫
┗━━━┻━━━━━┻━┻━━┻━━━┛

前提2 HTML

以下のようなHTMLがある仮定する。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf8">
    <title>タイトル</title>
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <div id="nav">
      <ul>
        <li><a href="#" class="nav1">nav1</a></li>
        <li><a href="#" class="nav2">nav2</a></li>
        <li><a href="#" class="nav3">nav3</a></li>
        <li><a href="#" class="nav4">nav4</a></li>
        <li><a href="#" class="nav5">nav5</a></li>
      </ul>
    </div>
  </body>
</html>

Sass(SCSS)で書いてみると

@mixin clearfix {
  \zoom: 1;
  &:after {
    content: '';
    display: block;
    clear: both;
    height: 0;
  }
}

@mixin nonspace {
  margin: 0;
  padding: 0;
}

@mixin nav-sprite($accum, $width, $height) {
  width: $width;
  height: $height;
  background-position: $accum 0;
  &:hover {
    background-position: $accum (-$height);
  }
}

#nav ul {
  @include nonspace;
  @include clearfix;
  li {
    @include nonspace;
    list-style-type: none;
    float: left;
    a {
      text-indent: -9999px;
      display: block;
      background: {
        image: url(nav.png);
        repeat: no-repeat;
      }

      /* 計算に使う値を初期化 */
      $width: 0; $height: 30px; $accum: 0;
      &.nav1 {
        $accum: $accum - $width;
        $width: 90px;
        @include nav-sprite($accum, $width, $height);
      }
      &.nav2 {
        $accum: $accum - $width;
        $width: 150px;
        @include nav-sprite($accum, $width, $height);
      }
      &.nav3 {
        $accum: $accum - $width;
        $width: 30px;
        @include nav-sprite($accum, $width, $height);
      }
      &.nav4 {
        $accum: $accum - $width;
        $width: 60px;
        @include nav-sprite($accum, $width, $height);
      }
      &.nav5 {
        $accum: $accum - $width;
        $width: 90px;
        @include nav-sprite($accum, $width, $height);
      }
    }
  }
}

直していくうちにこんな感じになった。

$accumに累計値を保存して、$widthも上書きしていくような感じ。とりあえず、累計値を手計算して当てはめていく必要はなくなる。

これより簡単にしようと思うと、制御構文とか独自メソッドを定義する*1とかになるのかもしれない。

何かもっといい方法はありませんか。

まとめ

Sassすごい。Sassがあると、使い回し効きやすいし、CSSの設計をしようという気になる。それだけでも大きな効果。

*1:CSS Spritesを作るためのフレームワークもあるみたいですね