この記事は、Frontrend Conferenceのセッション「Inline layout」でお話させていただいた内容を基に、連載記事(全4回)として書き起こしたものです。今回は第3回目です。
vertical-alignごとのアイコンの揃え位置
前回に引き続き、vertical-align
の利用方法について解説していきます。今回はまず、文頭に置いたアイコン画像を、vertical-align
を用いて位置調節する方法から見ていきます。
以下の様なHTMLがあったとします。
- xAhy 鈴
- xAhy 鈴
- xAhy 鈴 ...
ここで配置されているimg要素は、文頭にあるアイコンのようなものを想定して下さい。このようにアイコンを配置する時、そのままだとなんだかアイコンの位置がイマイチうまい位置に配置されないことがあります。そんな時にどうすればよいか。それはこのimg要素のvertical-align
を調節すればいいのですが、これをどう調節すればよいかは悩みどころですね。
先に答えを言ってしまうと、筆者的にはvertical-align: middle
を指定するのが一番無難であるように思いました。前回までの内容を踏まえ、このアイコン画像のvertical-align
値を変えてみるとどうなるのか、見てみます。
vertical-align: top
まずはtop
です。文頭に置いたアイコンのサイズをいろいろと変えてみました。このとき、img
にvertical-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
の左側に32px
のpadding
が指定されています。これでは左に余白ができてしまうだけですが、ここでtext-indent: -32px
を指定します。すると何が起こるかというと、li
の1行目だけ、文字が本来の開始位置よりも32px
左にずれた箇所から開始されます。つまるところ、1行目だけは、左にpadding
が指定されていないかのように配置され、2行目以降では、左に32px
のpadding
が指定された状態になります。
このように1行目だけ左にめり込んでいるような状態で、liの始めにimg要素を置きます。このimg要素の幅は24px
で、右に8px
のmargin
が取られています。つまり、これらを合計した32px
のスペースは、画像とその右マージンが占めることになります。これに続けてテキストが配置されるため、結果として、アイコン画像が左に飛び出しているような結果を得ることができます。
もう一つの問題、「img要素の高さが大きい場合に行の高さが広くなってしまう」については、img要素の上下のネガティブマージン(上-14px
、下-10px
)で解決しています。このようにマージンを指定すると、画像の上端が上に14px
、下端が下に10px
ずれる形となり、画像の高さが24px
なので、結果として高さが0
の要素を配置しているかのように扱われます。また、middle
の位置からすると、上に2px
ずれた位置に配置されます。
こういった実装は、本来であればlist-style-image
で行いたいところですが、いろいろと融通が効かないため、筆者はこのような方法を採用しています。
ほか、テンプレート設計のテクニックとしては、アイコンの幅高さを揃えてしまうという点も、一つ重要なように思われます。余白をギリギリまで削れば画像サイズを最小にできるでしょうが、そこまではせず、ある程度の余白をもたせ、高さ24px、幅24pxで作るよう統一したりなどします。そうすれば、一つ一つのアイコンのサイズを考慮し、細かく微調節せずに済むでしょう。そのサイズのアイコンがうまい位置に配置されるよう、今回解説してきたような調整を行えば、大体において、うまい具合にアイコンを配置することができるのではないでしょうか。
次回はdisplay: inline-block
の利用について解説します。
CodeGridについて
この連載の内容は、弊社、株式会社PixelGridが運営するフロントエンドの技術情報を配信するサービス、CodeGridにて連載された内容を元にしています。ご興味があれば、こちらもチェックしていただけると幸いです。
イベント動画
イベントの模様はYoutubeで公開されています。よろしければ、ご覧ください。