2016.01.30
課題解決のためのUI実装講座 Web Designing 2016年2月号
Webフォントが普及しても、まだ手放せない画像テキスト(2/2) 画像テキストを使ったレスポンシブ対応メニューを実装してみよう
画像テキストとWebフォントのメリットとデメリットを理解したところで、画像テキストを使ったメニューを実装してみよう。今風にレスポンシブに対応するのはもちろん、CSSスプライトやSassを使って、効率的に制作していく。
サンプルファイルダウンロードのご案内
このコーナーで紹介しているサンプルファイルは、こちらからダウンロードできます。ぜひ、サンプルを動かしたりカスタマイズしながら読み進めてください。
[IMAGE TEXT MENU 01]画像テキストを用いたレスポンシブなメニューをつくる
画像テキストを用いたメニューをつくってみよう。しかもレスポンシブデザインに対応させ、さらにPC版とスマホ版で一部異なるデザインにする。こうした場合は必要な画像ファイル数がかなり増えてしまい、実装の手間がかかる上に、サーバへのリクエストも無駄に増えてしまう。そこで、CSSスプライトやSassを使用して、これらの問題を解決する方法を紹介しよう。
Photoshopから個別画像の書き出し
作成するのは、テキスト部分がすべて画像のPC・スマホ対応メニューだ(01、02)。

シンプルなUIでも、PC版とスマホ版で30枚の画像が必要となる
<ul class="button-list"> <li><a href="#" class="button top active"><span class="sprite">トップ</span></a></li> <li><a href="#" class="button blog"><span class="sprite">ブログ</span></a></li> <li><a href="#" class="button latest"><span class="sprite">新着</span></a></li> <li><a href="#" class="button popular"><span class="sprite">人気</span></a></li> <li><a href="#" class="button recommended"><span class="sprite">おすすめ</span></a></li> <li><a href="#" class="button search"><span class="sprite">検索</span></a></li> </ul>
まず、Photoshopでボタンのテキストをデザインする。ボタン状態は「通常」「ホバー(PC版のみ)」「選択中」を用意し、Retinaディスプレイなどの高解像度画面向けに、PC版とスマホ版で異なる解像度のボタンを作成する(03)。

Photosohpのアートボードにボタンの状態ごとのデザインをまとめていく
あとは、各ボタンのデザインをPNGファイルとして書き出す(04)。

バージョンCCでは、レイヤーから個別に画像書き出しができる。書き出したいレイヤーを選択し、右クリックで「PNGとしてクイック書き出し」を実行するだけだ。レイヤー名が書き出し後のファイル名となるので、規則性のある命名をしよう
スプライト画像の作成
Photoshopで書き出した画像は30枚にもなる。このままだとサーバへのリクエストが無駄に増えるので、画像を一枚にまとめて background-positionで位置をずらして配置する「CSSスプライト」を使用する。今回、スプライト画像の作成にはTexturePacker※1を使う。
Photoshopから書き出した画像をTexture Packerの画面にドラッグすると、画像のプレビューが作成される(05)。Publish sprite sheetボタンを押して保存先を指定すると、スプライト画像とCSSコードが出力される。

無料版では使用できないオプションがあるので、エラーメッセージが出る場合はオプション内容を確認しよう
スプライト画像の最適化
スプライト画像をそのまま使用するのではなく、少しでもデータ量を軽くしておきたい。ImageOptim(OS X対応)※2やPNGGauntlet(Windows対応)※3といった、透過PNGの容量を最適化できる無料アプリケーションがある。最適化の効果は画像によって異なるが、多いときは20%から40%ほどの容量削減効果が期待できるので、ぜひ行っておきたい。
[IMAGE TEXT MENU 02]Sassの機能をフル活用してスプライト画像を効率よく配置する
メニューでCSSスプライトを使う際に面倒なのが、同じようなCSSスタイル定義をボタンごとに何度も繰り返す作業だ。さらにレスポンシブ対応ともなると、ボタン一つで多くのスタイル定義が必要になる。このような繰り返し部分を持つUIの場合、Sass※4の変数、連想配列、@mixin、@eachなどの機能を効果的に使うと効率よく実装することができる。
TexturePackerで生成したCSSから、変数の一覧を作成する。テキストエディタの検索置換機能などを使って、「変数にスペース区切りで数値が代入された」データに整える(01)。
.item1-1x{width:42px; height:15px; background-position: -107px -25px} .item1-2x{width:82px; height:29px; background-position: -5px -91px} .item1-active-1x{width:42px; height:15px; background-position: -154px -25px} .item1-active-2x{width:82px; height:29px; background-position: -313px -91px} .item1-hover-1x{width:42px; height:15px; background-position: -201px -25px
$item1-1x: 42px 15px -107px -25px; $item1-2x: 82px 29px -5px -91px; $item1-active-1x: 42px 15px -154px -25px; $item1-active-2x: 82px 29px -313px -91px; $item1-hover-1x: 42px 15px -201px -25px; 省略 $item6-1x: 30px 15px -334px -5px; $item6-2x: 59px 29px -318px -57px; $item6-active-1x: 30px 15px -369px -5px; $item6-active-2x: 59px 29px -254px -57px; $item6-hover-1x: 30px 15px -229px -5px;
SCSS(sample/style.scss)。class名を変数名に変更し、プロパティを除き、「変数にスペース区切りで数値が代入された」データに整形する(下)
@mixinの作成
整形したデータを使って、スプライト画像を配置する@mixinを作成する(02)。この第2引数に0.5を入れると、画像をRetinaディスプレイ用の2分の1サイズで表示することができる。途中の計算では、変数の内部から数値を取得するためにSassのnth()関数を使用している。
変数をmap型のデータにまとめる
Sass 3.3以降では「map型」というデータ型で、連想配列を作成できるようになった。今回は作成した変数をボタンごと、デバイスごとに整理してmapに格納した(03)。
@eachによるループ
map型のデータを対象に、@eachでまとめてスタイルを作成している(04)。@eachを使うと、連想配列の内容一つひとつに対して処理を行える。内部のデータへのアクセスには、Sassのmap-get()関数を使用している。
// 配列と拡大率からスプライト画像を配置するミックスインを定義 @mixin sprite($sprite, $scale:1) { // スプライト画像全体の横幅・高さをここに入力 $sprite-width: 477px; $sprite-height: 125px; // 背景画像サイズを計算 background-size: $sprite-width * $scale, $sprite-height * $scale; // オフセットを計算 $sprite-offset-x: nth($sprite, 3) * $scale; $sprite-offset-y: nth($sprite, 4) * $scale; background-position: $sprite-offset-x $sprite-offset-y; // 表示サイズを計算 width: nth($sprite, 1) * $scale; height: nth($sprite, 2) * $scale; }
// map型データを作成 $spriteMap: ( top: ( // PC用データ (通常, ホバー用, アクティブ用) pc: ($item1-1x, $item1-hover-1x, $item1-active-1x), // SP用データ (通常, アクティブ用) sp: ($item1-2x, $item1-active-2x) ), 省略 search: ( pc: ($item6-1x, $item6-hover-1x, $item6-active-1x), sp: ($item6-2x, $item6-active-2x) ) );
// map型データを対象にループでルールを作成 @each $key, $item in $spriteMap { $pc: map-get($item, pc); $sp: map-get($item, sp); .#{$key} { // インターポレーションを使い、class名にmapのキー名を代入 > .sprite { // SPサイズ @include sprite(nth($sp, 1), 0.5); } &.active > .sprite { // SPアクティブ状態 @include sprite(nth($sp, 2), 0.5); } @media all and (min-width: 600px) { > .sprite { // PCサイズ @include sprite(nth($pc, 1), 1); } &:hover > .sprite { // PCサイズホバー状態 @include sprite(nth($pc, 2), 1); } &:active > .sprite, // PCサイズアクティブ状態 &.active > .sprite { @include sprite(nth($pc, 3), 1); } } } } .sprite { background-image: url(./sprite.png); background-repeat: no-repeat; text-indent: 100%; overflow: hidden; white-space: nowrap; display: inline-block; }
※1 TexturePackerはさまざまな形式でスプライト画像を作成できるアプリケーション(OS X、Windows対応)で、無料版でもCSSスプライトを書き出すことができる。 https://www.codeandweb.com/texturepacker
※2 ImageOptim
※3 PNGGauntlet
4 Sassとは、CSSを効率よく記述するためのCSS拡張メタ言語。変数やネストなど、CSS仕様には用意されていない機能を使うことができる。

- 藤田遼
- インターネット・アカデミーにてHTML・CSSを学ぶ。2013年より(株)LIGに入社。現在はWebデザイナーとして主にコーポレートサイトのリニューアルやキャンペーンサイトのデザイン業務に従事している。

- 堀祐磨
- 多摩美術大学を中退後、デザイナーとしてグラフィックデザイン・Webデザインを経験。デザイン業務のかたわらプログラミングを行うようになり、Webフロントエンドへ関心を持つ。2015年に(株)LIGに入社。 http://liginc.co.jp/