レイアウトをしなければならなかった多くの人は、要素を垂直に揃える必要に直面し、要素を中央に揃えるときにどんな困難が生じるかを知っていると思います。
はい。CSSの垂直方向の配置には、 多くの値を持つ特別な
vertical-align
プロパティがあります 。 ただし、実際には、期待どおりに機能しません。 これを理解してみましょう。
以下のアプローチを比較してください。 との整列:
- テーブル
- くぼみ
-
line-height
- ストレッチング
- 負の
margin
、 -
transform
- 擬似要素
-
flexbox
例として、次の例を考えてみましょう。
2つの
div
要素があり、一方が他方にネストされています。 それらに対応するクラス、
outer
と
inner
与えましょう。
<div class="outer"> <div class="inner"></div> </div>
課題は、内側の要素を外側の要素の中心に揃えることです。
まず、外部ブロックと内部ブロックの寸法がわかっている場合を考えます。
display: inline-block
ルールを内部要素に追加し、
text-align: center
および
vertical-align: middle
外部要素に追加し
display: inline-block
。
整列は、
inline
または
inline-block
表示モードを持つ要素にのみ適用されることを思い出します。
ブロックのサイズと背景色を設定して、境界線を確認します。
.outer { width: 200px; height: 200px; text-align: center; vertical-align: middle; background-color: #ffc; } .inner { display: inline-block; width: 100px; height: 100px; background-color: #fcc; }
スタイルを適用すると、屋内ユニットが水平ではなく垂直に整列していることがわかります。
http://jsfiddle.net/c1bgfffq/
なぜこれが起こったのですか? 事実、
vertical-align
プロパティは、 その内容ではなく要素自体の配置に影響します(テーブルセルに適用される場合を除く)。 したがって、このプロパティを外部要素に適用しても何も生成されませんでした。 さらに、このプロパティを内部要素に適用しても何も行われません。
inline-block
ブロックは隣接するブロックに対して垂直に配置されるため、この例では1つのラインブロックがあります。
この問題を解決するには、いくつかの手法があります。 以下では、それらのそれぞれをより詳細に検討します。
テーブルの配置
頭に浮かぶ最初の解決策は、外部ブロックを1つのセルのテーブルに置き換えることです。 この場合、セルの内容、つまり室内ユニットに位置合わせが適用されます。
<table class="outer-wrapper"> <td class="outer"> <div class="inner"></div> </td> </table>
http://jsfiddle.net/c1bgfffq/1/
このソリューションの明らかなマイナス点は、セマンティクスの観点から、アライメントにテーブルを使用することは正しくないことです。 2番目のマイナスは、テーブルを作成するために、外部ブロックの周りにもう1つの要素を追加する必要があることです。
最初のマイナスは、
table
タグと
td
タグを
div
置き換え、CSSでテーブル表示モードを設定することにより、部分的に削除できます。
<div class="outer-wrapper"> <div class="outer"> <div class="inner"></div> </div> </div>
.outer-wrapper { display: table; } .outer { display: table-cell; }
それにもかかわらず、外部ブロックは、結果として生じるすべての結果を保持するテーブルのままです。
インデント
屋内ユニットと屋外ユニットの高さがわかっている場合は、(H outer -H inner )/ 2の式を使用して、屋内ユニットの垂直インデントを使用して位置合わせを設定できます。
.outer { height: 200px; } .inner { height: 100px; margin: 50px 0; }
http://jsfiddle.net/c1bgfffq/6/
解決策-両方のブロックの高さがわかっている限られた場合にのみ適用できます。
行の高さによる整列
内側のブロックがテキストの1行しか占めないことがわかっている場合は、
line-height
を使用して、外側のブロックの高さに等しく設定できます。 内側のブロックのコンテンツは2行目にラップされるべきではないため、
white-space: nowrap
および
overflow: hidden
ルールも追加することをお勧めします。
.outer { height: 200px; line-height: 200px; } .inner { white-space: nowrap; overflow: hidden; }
http://jsfiddle.net/c1bgfffq/12/
また、内部ブロックの
line-height
値をオーバーライドし、
display: inline-block
および
vertical-align: middle
ルールを追加する場合、この手法を使用して複数行のテキストを揃えることもできます。
.outer { height: 200px; line-height: 200px; } .inner { line-height: normal; display: inline-block; vertical-align: middle; }
http://jsfiddle.net/c1bgfffq/15/
この方法の欠点は、外部ユニットの高さを知る必要があることです。
ストレッチアライメント
この方法は、外部ユニットの高さが不明であるが、内部ユニットの高さがわかっている場合に適用できます。
これを行うには、次のものが必要です。
- 外部ブロックの相対位置を設定し、内部-絶対位置を設定します。
-
top: 0
およびbottom: 0
ルールを内側ブロックに追加しtop: 0
その結果、外側ブロックの高さ全体に伸びます。 -
auto
を室内ユニットの垂直パディングに設定します。
.outer { position: relative; } .inner { height: 100px; position: absolute; top: 0; bottom: 0; margin: auto 0; }
http://jsfiddle.net/c1bgfffq/4/
この手法の本質は、引き伸ばされ絶対位置にあるブロックの高さを設定すると、値が
auto
設定されている場合、ブラウザーは垂直のインデントを等しい比率で計算することです。
http://www.w3.org/TR/CSS2/visudet.html#abs-non-replaced-height
この方法の欠点は、室内ユニットの高さを知る必要があることです。
負のマージン上部に揃える
この方法は広く知られており、非常に頻繁に使用されます。 前のブロックと同様に、外部ブロックの高さが不明であるが、内部ブロックの高さがわかっている場合に適用されます。
外部ユニットの相対的な配置と内部-絶対を設定する必要があります。 次に、内側のブロックを外側のブロック
top: 50%
半分の高さである
top: 50%
下に移動し、それ自体の高さの
margin-top
半分を上に上げる必要があります。
.outer { position: relative; } .inner { height: 100px; position: absolute; top: 50%; margin-top: -50px; }
http://jsfiddle.net/c1bgfffq/13/
この方法の欠点は、室内ユニットの高さを知る必要があることです。
変換との整合
この方法は前の方法と似ていますが、室内ユニットの高さが不明な場合に適用できます。 この場合、ピクセルで負のマージンを設定する代わりに、
transform
関数と値
-50%
を使用して
transform
プロパティを使用し、内部ブロックを上げることができます。
.outer { position: relative; } .inner { position: absolute; top: 50%; transform: translateY(-50%); }
http://jsfiddle.net/c1bgfffq/9/
以前の方法では、値をパーセントで設定することが不可能だったのはなぜですか?
margin
プロパティのパーセンテージ値は親要素に対して計算されるため、50%の値は外側のブロックの高さの半分に等しくなり、内側のブロックを自身の高さの半分に上げる必要がありました。
transform
プロパティはこれに最適です。
この方法の欠点は、古いバージョンのIEブラウザによる
transform
プロパティのサポートが制限されている
transform
です。
擬似要素の配置
これは、両方のブロックの高さが不明な場合に適用できる最も普遍的な方法です。
この方法の本質は、外部ブロック内に高さ
100%
inline-block
ライン
inline-block
を追加し、それを垂直方向の配置に設定することです。 この場合、追加されたブロックの高さは外部ブロックの高さと等しくなります。 屋内ユニットは、追加されたユニット、つまり外部ユニットに対して垂直に配置されます。
セマンティクスに違反しないように、
before
または
after
疑似要素を使用して行ブロックを追加することをお勧めします。
.outer:before { display: inline-block; height: 100%; vertical-align: middle; content: ""; } .inner { display: inline-block; vertical-align: middle; }
http://jsfiddle.net/c1bgfffq/10/
この方法の欠点は、室内ユニットに絶対位置がある場合には適用できないことです。
Flexboxとの調整
垂直方向の配置の最も現代的な方法は、 Flexible Box Layout (一般に
Flexbox
として知られて
Flexbox
)を使用することです。 このモジュールを使用すると、ページ上の要素の配置を柔軟に制御し、ほとんどあらゆる方法で要素を配置できます。 Flexboxの中心を合わせるのは非常に簡単な作業です。
外側のブロックは
display: flex
設定する必要があり、内側のブロックは
margin: auto
設定する必要があります。 そしてそれだけです! いいですね
.outer { display: flex; width: 200px; height: 200px; } .inner { width: 100px; margin: auto; }
http://jsfiddle.net/c1bgfffq/14/
この方法の欠点は、Flexboxが最新のブラウザーでのみサポートされることです。
どちらを選ぶか?
問題のステートメントから続行する必要があります。
- テキストの垂直方向の配置には、垂直インデントまたは
line-height
を使用することをお勧めしline-height
。 - 高さが既知の絶対配置要素(アイコンなど)の場合、負の
margin-top
プロパティを持つメソッドが理想的です。 - ブロックの高さが不明なより複雑な場合には、擬似要素または
transform
プロパティを使用する必要があります。 - 幸運なことに、IEブラウザの古いバージョンをサポートする必要がないほど幸運なら、もちろん、
Flexbox
を使用する方が良いでしょう。