HTML5Experts.jp

理解しておきたい、CSSによるインラインレイアウトの仕組み(vertical-align編その2)Inline Layout─Frontrend Conference

この記事は、Frontrend Conferenceのセッション「Inline layout」でお話させていただいた内容を基に、連載記事(全4回)として書き起こしたものです。今回は第3回目です。

vertical-alignごとのアイコンの揃え位置

前回に引き続き、vertical-alignの利用方法について解説していきます。今回はまず、文頭に置いたアイコン画像を、vertical-alignを用いて位置調節する方法から見ていきます。

以下の様なHTMLがあったとします。


ここで配置されているimg要素は、文頭にあるアイコンのようなものを想定して下さい。このようにアイコンを配置する時、そのままだとなんだかアイコンの位置がイマイチうまい位置に配置されないことがあります。そんな時にどうすればよいか。それはこのimg要素のvertical-alignを調節すればいいのですが、これをどう調節すればよいかは悩みどころですね。

先に答えを言ってしまうと、筆者的にはvertical-align: middleを指定するのが一番無難であるように思いました。前回までの内容を踏まえ、このアイコン画像のvertical-align値を変えてみるとどうなるのか、見てみます。

vertical-align: top

まずはtopです。文頭に置いたアイコンのサイズをいろいろと変えてみました。このとき、imgvertical-align: topを指定すると、以下の様な表示になります。(わかりやすさのためにliには背景色をつけてあります)

img {
  vertical-align: top;
}

topが指定された場合、行の上端に画像の上端が合わせられます。

この場合ですと、画像の高さが行の高さと同じぐらいでないと、ちょうどよい位置に配置するのは難しそうです。アイコンのデザイン基準位置が上端であったならばアリかもしれませんが、そういったことは稀でしょう。今回のような用途でtopを指定することは、ほとんどなさそうです。

vertical-align: bottom

次はbottomの場合です。

img {
  vertical-align: bottom;
}

bottomが指定された場合、行の下端に画像の下端が合わせられます。

この場合もtopと同様に、画像の高さが行の高さと同じぐらいでないと、利用価値はなさそうです。ただ、アイコン画像が、文字の高さよりも少し大きいぐらいでばらつきがあり、なおかつ画像の下端を基準としたようなアイコンであれば、bottomを指定するのはアリかもしれません。

vertical-align: text-top

次はtext-topの場合です。

img {
  vertical-align: text-top;
}

text-topが指定された場合、inline boxの上端に画像の上端が合わせられます。

この場合は、アイコンの高さが文字の高さぐらいであれば、ちょうど真ん中に揃えられそうです。しかし、アイコンが大きい場合は、アイコンが下に飛び出るように配置されるため、おかしな配置となってしまいそうです。アイコンを配置する用途として利用する機会は少なそうに思います。

vertical-align: text-bottom

次はtext-bottomの場合です。

img {
  vertical-align: text-bottom;
}

text-bottomが指定された場合、inline boxの下端に画像の下端が合わせられます。

text-topと同様、アイコンの高さが文字の高さぐらいの場合にはちょうどよいですが、アイコンが大きい場合は、アイコンが上に飛び出ます。アイコンの高さにばらつきがあり、その高さが文字の高さを超えないぐらいなのであれば、ちょうどよい位置に配置することができそうです。

vertical-align: baseline

img {
  vertical-align: baseline;
}

次はbaselineの場合です。vertical-alignの初期値はbaselineですので、特に何も指定しなければこの方法でレイアウトされます。

baselineが指定された場合、baselineに画像の下端が合わせられます。

この指定が有効なのは、画像の高さが、x-heightの高さ〜文字の高さの範囲である場合でしょう。それよりも大きな画像の場合は、アイコンが上側に飛び出ているように見えてしまいます。このため、特に何もCSSで調節しないままアイコンを置いたら、どうも上めに配置されてしまうな〜と感じる方は多いのではないでしょうか。

vertical-align: <length>

次はlengthの場合です。3pxとか0.3em等が指定された場合です。ここでは、4pxを指定しました。

img {
  vertical-align: 4px;
}

lengthが指定された場合、baselineから、length分、上方向にずれた位置に画像の下端が揃えられます。

上記レンダリング結果を見てわかる通り、baselineよりも上にずれてしまっては、かなり小さいアイコンを使う場合にしか、利用価値はなさそうに思えます。ただ、例えば-3px-0.2emのように、マイナスの値を指定した場合、baselineよりもその分だけ下にずれた位置に画像の下端が揃えられます。

これを利用すれば、アイコンの下端位置を微調節できるため、アイコンの高さにある程度のバリエーションがあっても、うまく位置調節に利用できそうです。筆者はこの方法でこういったアイコン画像をよく調節していました。恥ずかしながら、なんとなく指定したぶんズレるぐらいにしか理解していませんでしたが……。

vertical-align: middle

次はmiddleの場合です。

img {
  vertical-align: middle;
}

middleが指定された場合、baselineよりもx-heightの高さの半分だけ上の位置に、画像の中央位置が揃えられます。

ここまでで紹介してきたほかプロパティと異なり、画像の「中央」の位置が揃えられるというのが、middleの便利なポイントかと思います。ここまでで紹介してきた他の値では、画像の上端か下端がいずこかに揃えられます。中央で揃えてくれるのはmiddleだけです。ちなみに、centralという、行の中央に画像の中央が揃えられる指定もありますが、ブラウザのサポートはまだまだのようです。

微調整を加えた例

ほとんどの場合、middle指定すれば、だいたいよい感じに中央に揃ってくれるのではないでしょうか。ただし、アイコンの高さによっては、やや下寄りにアイコンが寄っているように見えてしまうかもしれません。

例えば、アイコンの高さがちょうど文字の大きさぐらいで、アイコンに続くテキストが日本語である場合、そのように見えてしまう可能性が高いと私は感じます。これは、日本語の文字というものは、アルファベットと比較した場合、文字の上方まで密度が高く作られていることが多いためです。第1回で軽く触れましたが、日本語の文字のbaselineは、アルファベットのbaselineよりも少し下にあります。

そして、ほとんどの文字は、このbaselineよりも下方のスペースを利用しません。平仮名や漢字の書体を思い浮かべてみてください。gとかjとかいったように、下に伸びる文字は、日本語の中にはあまりなさそうです。それゆえ、日本語の文字というのは、アルファベットの文字と比較すると、行のやや上寄りに寄っているように見えるのではないでしょうか。

これを微調節すれば丁度真ん中ぐらいに見えるのでは?というのが、以下の様な微調整のアプローチです。

img {
  vertical-align: middle;
  position: relative;
  top: -0.1em;
}

このようにすると、以下のように、middleで揃えた位置から若干上寄りにアイコンが配置されます。(左がmiddle、右が微調整したもの)

レンダリング結果は、以下の様な形になります。

本当にちょっとだけ上に寄っているだけですけれども……。img要素の上下のmarginを微調節したり、このように相対配置をし、上めにずらすと、日本語と並べた時に自然になるように筆者は思います。

アイコンをリストのビュレットとして使う

ここまででアイコンの位置を調節するため、img要素のvertical-alignをいろいろといじってみてきました。ですが、このままではリストのビュレットのようには利用できません。以下のように、2行以上になれば、2行目以降は当然アイコンの左端からテキストが始まってしまいますし、アイコンのサイズが大きくなれば、その行の高さはそれに合わせ、大きくなってしまいます。

これを解決する実装例を一つ紹介します。以下です。


ul {
  list-style-type: none;
}
li {
  padding: 0 0 10px 32px;
  text-indent: -32px;
}
img {
  width: 24px;
  height: 24px;
  margin: -14px 8px -10px 0;
  vertical-align: middle;
}

リストマーカーだけを左に飛び出させているのがliに指定した左paddingと、text-indentです。ここではliの左側に32pxpaddingが指定されています。これでは左に余白ができてしまうだけですが、ここでtext-indent: -32pxを指定します。すると何が起こるかというと、liの1行目だけ、文字が本来の開始位置よりも32px左にずれた箇所から開始されます。つまるところ、1行目だけは、左にpaddingが指定されていないかのように配置され、2行目以降では、左に32pxpaddingが指定された状態になります。

このように1行目だけ左にめり込んでいるような状態で、liの始めにimg要素を置きます。このimg要素の幅は24pxで、右に8pxmarginが取られています。つまり、これらを合計した32pxのスペースは、画像とその右マージンが占めることになります。これに続けてテキストが配置されるため、結果として、アイコン画像が左に飛び出しているような結果を得ることができます。

もう一つの問題、「img要素の高さが大きい場合に行の高さが広くなってしまう」については、img要素の上下のネガティブマージン(上-14px、下-10px)で解決しています。このようにマージンを指定すると、画像の上端が上に14px、下端が下に10pxずれる形となり、画像の高さが24pxなので、結果として高さが0の要素を配置しているかのように扱われます。また、middleの位置からすると、上に2pxずれた位置に配置されます。

こういった実装は、本来であればlist-style-imageで行いたいところですが、いろいろと融通が効かないため、筆者はこのような方法を採用しています。

ほか、テンプレート設計のテクニックとしては、アイコンの幅高さを揃えてしまうという点も、一つ重要なように思われます。余白をギリギリまで削れば画像サイズを最小にできるでしょうが、そこまではせず、ある程度の余白をもたせ、高さ24px、幅24pxで作るよう統一したりなどします。そうすれば、一つ一つのアイコンのサイズを考慮し、細かく微調節せずに済むでしょう。そのサイズのアイコンがうまい位置に配置されるよう、今回解説してきたような調整を行えば、大体において、うまい具合にアイコンを配置することができるのではないでしょうか。

次回はdisplay: inline-blockの利用について解説します。

CodeGridについて

この連載の内容は、弊社、株式会社PixelGridが運営するフロントエンドの技術情報を配信するサービス、CodeGridにて連載された内容を元にしています。ご興味があれば、こちらもチェックしていただけると幸いです。

イベント動画

イベントの模様はYoutubeで公開されています。よろしければ、ご覧ください。