vertical-alignの使い方と別の実装方法について

こんにちは、エンジニアの井戸田です。

先日 vertical-align ではまり、検索してみると予測変換で vertical-aling 効かない と出てくるので、結構皆さんもはまっているんだなと感じました。 なので今回は僕もはまったcssのプロパティである、 vertical-align の値・使い方や、垂直方向の調整の別の実装方法を紹介したいと思います。

コードについて、htmlはslim、cssはscssを使用しているので注意してください。

vertical-alignの説明

vertical-align は行内のテキスト、画像の垂直方向の揃え位置を指定するプロパティです。 vertical-align は適用できるのが、 inline要素テーブルセル です。なので divタグpタグ などの ブロック要素 に対して vertical-align を指定してもうまくいきません。
divタグpタグvertical-align を指定したい時は diplay: inline や, display: table-cell , diplay: inline-block を指定し、要素自体を変更する必要があります。

説明
baseline 適当した要素のベースラインを親要素のベースラインに合わせる(初期値)
top 適用した要素の上端を、行ボックスの上端に合わせる
middle 適用した要素の中心を、親要素の中心に揃える
bottom 適用した要素の下端を、行ボックスの下端に合わせる
text-top 適用した要素の上端を、親要素の文字の上端に合わせる (テーブルセルへの指定はできない)
text-bottom 適用した要素の上端を、親要素の文字の下端に合わせる (テーブルセルへの指定はできない)
super 上付き文字 (テーブルセルへの指定はできない) 
sub 下付き文字 (テーブルセルへの指定はできない)
pxなどの単位 px, emなどの単位を使用しての指定(ベースラインが揃った状態を0、正の値は上方向、負の値はした方向になる)
  • 初期値が baseline なのですが、画像などは baseline を持たないため、下端が親要素のベースラインに揃えられます。
  • middleとは、フォントの場合 0.5ex 。小文字の「x」の半分高さです。

toptext-topbottomtext-bottombaselinetext-bottom の違いについて、勘違いしやすいので下記にまとめておきます。

top と text-topの違い

.verticalAlign.verticalAlign-top
  span.example
    | Example
    span.parent
      | parent
      span.child
        | top

.verticalAlign.verticalAlign-textTop
  span.example
    | Example
    span.parent
      | parent
      span.child
        | text-top
.verticalAlign {
  margin: 0 0 8px 0;
  background-color: #f93;

  &-top {
    .child {
      vertical-align: top;
    }
  }

  &-textTop {
    .child {
      vertical-align: text-top;
    }
  }
}

.example {
  background-color: #fd7c79;
  font-size: 5rem;
}

.parent {
  background-color: #33cfff;
  font-size: 2.5rem;
}

.child {
  background-color: #24ff18;
  font-size: 1rem;
}

f:id:cluex-developers:20160909205157p:plain

上が top で 下が text-top になります。
text-top は親要素の文字の上端(一番高い場所)を基準とします。なので上端を基準として配置することが可能です。
top は適用した要素の上端を、行ボックスの上端に合わせるため上記のような表示になります。

bottom と text-bottomの違い

.verticalAlign.verticalAlign-bottom
  span.example
    | Example
    span.parent
      | parent
      span.child
        | bottom

.verticalAlign.verticalAlign-textBottom
  span.example
    | Example
    span.parent
      | parent
      span.child
        | text-bottom
.verticalAlign {
  margin: 0 0 8px 0;
  background-color: #f93;

  &-bottom {
    .child {
      vertical-align: bottom;
    }
  }

  &-textTop {
    .child {
      vertical-align: text-bottom;
    }
  }
}

// 省略 以下はtopとtext-topと指定の仕方は同じです。

f:id:cluex-developers:20160909205407p:plain

上が bottom で下が text-bottom になります。
text-bottom は親要素の文字の下端(ディセンター文字の下端)を基準として配置することが可能です。
また bottom は適用した要素の下端を、行ボックスの下端に合わせるため上記のような表示になります。

baseline と text-bottom

次は baselinebottom-text に対してどのような違いがあるのか、説明します。

.verticalAlign.verticalAlign-baseline
  span.example
    | Example
    span.parent
      | parent
      span.child
        | baseline

.verticalAlign.verticalAlign-textBottom
  span.example
    | Example
    span.parent
      | parent
      span.child
        | text-bottom
.verticalAlign {
  margin: 0 0 8px 0;
  background-color: #f93;

  &-baseline {
    .child {
      vertical-align: baseline;
    }
  }

  &-textBottom {
    .child {
      vertical-align: text-bottom;
    }
  }
}

// 省略 以下はtopとtext-topと指定の仕方は同じです。

f:id:cluex-developers:20160909205017p:plain

上記を見てみるとどのような違いがあるのか迷うと思うのですが、親要素( .parent )を対して line-height を入れてみると違いが良く分かります。

.verticalAlign.verticalAlign-baseline
  span.example
    | Example
    span.parent
      | parent
      span.child
        | baseline

.verticalAlign.verticalAlign-textBottom
  span.example
    | Example
    span.parent
      | parent
      span.child
        | text-bottom
.verticalAlign {
  margin: 0 0 8px 0;
  background-color: #f93;
  
  &-baseline {
    .child {
      vertical-align: baseline;
    }
  }
  
  &-textBottom {
    .child {
      vertical-align: text-bottom;
    }
  }
}

.example {
  background-color: #fd7c79;
  font-size: 5rem;
}

.parent {
  background-color: #33cfff;
  font-size: 2.5rem;
  line-height: 2; // ← 追加
}

.child {
  background-color: #24ff18;
  font-size: 1rem;
}

f:id:cluex-developers:20160909205503p:plain

.parent に対して line-height: 2; を指定すると、 baseline は親のフォントのベースライン(基準線)に合わせるので、ズレは生じません。ただ text-bottom は親の要素の文字の下端に合わせるので、ズレが生じてしまいます。
上記の例の様に親の要素で line-height (や height などの縦幅調整をするプロパティ)を指定している時は注意が必要です。

(実際に実装する時には 初期値が baseline なので、 vertical-aling: baseline; の指定は必要ありません。)

ブロック要素への対応

テーブルセルとdisplay: table-cellの使い方

テーブルセルとは tableタグ で使用する tdタグ , thタグ のことです。こちらの要素に対しても vertical-align を使用すことができます。但し text-top , text-bottom , super , sub は指定することができません。 display: table-cell での実装方法は下記の様になります。下記の例では .block を垂直方向に中央揃えにしています。

.tableCell
  .block
    | block
.tableCell {
  display: table-cell;
  height: 100px;
  background-color: #f93;
  vertical-align: middle;
}

f:id:cluex-developers:20160909205532p:plain

block要素 に対して vertical-align を使用する場合には、垂直方向の調整をしたいタグの親要素に対して display: table-cell , vertical-align: ◯◯ を指定することで、使用することができます。 ただ表に関係ない要素に display: table-cell を指定するのはバットな気がしますね。

display: inline-block

display: table-cell を使用しないで display: inline-block を使用する方法もあります。inline-block要素 とは inline要素block要素 を兼ね備えた要素です。下記の例では2つの inline-block要素 を垂直方向に中央揃えにしています。

.block
  .inlineBlock1
    | inlineBlock1
  .inlineBlock2
    | inlineBlock2
.inlineBlock1 {
  display: inline-block;
  height: 8rem;
  background-color: #fd7c79;
  font-size: 2rem;
  vertical-align: middle;
}

.inlineBlock2 {
  display: inline-block;
  background-color: #33cfff;
  font-size: 2rem;
  vertical-align: middle;
}

f:id:cluex-developers:20160909205049p:plain

block要素 に対して display: inline-blockvertical-align: ◯◯ を指定することで、使用することができます。 inline-block要素inline要素 で異なるのが、 inline-block要素 の場合は横幅・縦幅が指定が可能なので、その分 inline要素 より使い易いかも知れません。

block inline inline-block の違いについては、また別の機会に詳しく話したいと思います!

vertical-alingを使用しないで垂直方向を調整する方法として

  • line-height
    line-height を使用して、親要素のheightに調整する。なんとなくバットな調整方法だと思います・・・。
  • position
    親のblock要素に対して position: relative 、子要素に対して postion: absolute を指定する。
    ただ垂直方向の中央揃えにしたいと思っていても、 postion:absolute は指定した要素の本来の位置からの相対位置なので top: 50% という指定をしていても、その要素の上端が真ん中にきてしまうので、 top: 50% ではなく調整する必要があります。

上記2つを挙げましたが、それぞれ調整が難しいと思います。そこで僕個人がおすすめしたいのが FlexBox を使用する方法です。

FlexBoxを使用し垂直方向を調整する

FlexBox とは「Flexible Box Layout Module(フレキシブルボックスレイアウトモジュール)」のことで、要素をFlexコンテナというボックス内にフレキシブルで簡単に整列する方法です。

FlexBoxに対応しているブラウザは下記のようになります。

f:id:cluex-developers:20160909210303p:plain

参考) Can I use... Support tables for HTML5, CSS3, etc

  • IE11から正式対応。
  • safariには -webkit- のベンダープレフィックス必要のようです。

垂直方向の調整をするために align-items 又は align-self というプロパティを使用します。

align-items と align-self

  • align-items
    flexコンテナに対して指定することで、コンテナ内のすべてflexアイテム(子要素)に対して、同じ位置に調整します。
  • align-self
    flexアイテムに対して指定することで、個別に位置を調整します。
説明
baseline flexアイテム内の文字のベースラインを揃える。 最初のflexアイテムのbaselineに揃うようです。
flex-start flexアイテムの上端を揃える( flex-directioncolumncolumn-reverse の場合は右側を揃える)
flex-end flexアイテムの下端を揃える( flex-directioncolumncolumn-reverse の場合は右側を揃える)
center 適用した要素の中心を、親要素の中心に揃える( flex-directioncolumncolumn-reverse の場合は横幅の中央を揃える)
stretch レックスアイテムの高さを揃える( flex-directioncolumncolumn-reverse の場合は横幅を揃える)

下記の例では、 align-items: center を使用して実装してます。

.flexBox
  .flexItem1
    | flexItem1
  .flexItem2
    | flexItem2
  span.flexItem3
    | flexItem3
.flexBox {
  display: flex;
  align-items: center;
}

.flexItem1 {
  background-color: #fd7c79;
  height: 200px;
}

.flexItem2 {
  background-color: #33cfff;
  height: 80px;
}

.flexItem3 {
  background-color: #24ff18;
  height: 160px;
}

f:id:cluex-developers:20160909205040p:plain

.flexBox に対して display: flex , align-items: center を指定することで、flexコンテナ内の全てのflexアイテムが垂直方向に中央揃えになります。 このように簡単に垂直方向を調整することができるので、ブラウザの対応に気をつけなければいけませんが、 FlexBox はとても便利です。

もし vertical-align での調整が難しい場合には、 FlexBoxの導入をぜひ検討してみてください。弊社が運用しているmamanokoでも flex を多用してます。

余談

株式会社Cluexではエンジニアの方を探しています!

cluex.co.jp