開発ブログ

WWWクリエイターズが送る、Git、CSS、HTML、コマンドライン、Macの便利機能など、開発に関する役立ち情報発信します。気まぐれに更新。

CSS:上下左右への中央寄せ方法、全部まとめ。

最終更新:2017-11-14 by Joe

HTMLとCSSで、テキストや画像を縦方向(上下方向)に中央寄せ(=センタリング)したい事があります。この課題は簡単そうに見えて、意外と厄介です。

実際のところ、実現方法にはいくつかの選択肢がありますが、いずれも、HTML、CSSの初学者にとってはちょっとだけトリッキーです。さっそく見ていきます。

テキスト(インライン要素)の中央寄せ

テキスト(文字列)のような、文書に流れ込むように配置される要素は「インラインレベル」の要素と呼ばれます。これらは、要素の横幅を満たすように配置される「ブロックレベル」の要素と区別されます。インラインとブロックの概念はここれでは詳しくは追求しませんが、この記事の補足セクションに解説を加えましたので、興味のある方はぜひご覧ください。

1行のテキストの場合

これはあまり細かい説明は不要かもしれませんが、CSSで、line-heightプロパティは、1行あたりの高さを大きく定めれば、内包されたテキストは縦方向の中央付近に配置されます。

また、「text-align: center」によって、横方向にも中央寄せしています。親のdiv要素がブロックレベル要素であることに注意して下さい。text-alignはブロック要素に対して有効で、その要素が内包するインライン要素の振る舞いを定めるためのプロパティです。(ブロックに内包されたプレーンテキストはインラインとして振る舞います。)

<div class="container">
  行の高さ中央付近に配置。
</div>

<style>
.container{
  line-height:300px;
  text-align:center;
  background-color:#efd;
}
</style>

CSSの「line-height」プロパティは、その値にpxやpt値、もしくは、%や少数などの割合を指定できます。割合を指定すれば、font-sizeプロパティで指定されるフォントサイズに対する割合として解釈されます。上記のように、line-heightの値を極端に大きくすることで、自動的にテキストが縦方向の中央寄せに配置されます。

ちなみに、通常のウェブサイトでは、line-height は1.2〜2程度の割合の値が読みやすい範囲です。ブラウザ(Chrome)のデフォルトは normal キーワードで指定され、おおよそ1.2程度です。

複数行のテキストの場合

2行以上のテキストの縦方向の中央寄せは少しトリッキーで、直感的には理解し難いかもしれません。実際の所、複数行のテキストのセンタリングにはいくつかの選択肢があります。下記に紹介する方法はいずれも「vertical-align: middle」という指定を利用しますが、アプローチが少し違います。

[方法1] インラインブロック化する

1行だろうと2行だろうと中央に配置できる、一番おすすめの方法です。displayプロパティの「inline-block」を利用します。CSSの、inline-blockプロパティは、2017年現在では、ほとんどのブラウザで完璧にサポートされていますので、恐れる必要はありません。

<div class="container">
  <span class="target">ブロックの<br>高さが変わっても<br>自動的に中央付近に。</span>
</div>

<style>
.container{
  line-height:300px;
  background-color:#fec;
  text-align:center;
}
.container .target{
  display:inline-block;
  vertical-align: middle;
  line-height:normal;
}
</style>

親要素で「line-height:300px」と高さを固定することで、対象(と、そのプロパティを継承する子要素)内のテキストは自動的にその行内で、高さ方向の中央付近に配置されます。ポイントは、その子要素(.target)に指定したスタイルで、line-heightの値を元に戻している点です。上記はnormalでブラウザのデフォルト値を取るように指定していますが、任意の値で構いません。

この「vertical-align」プロパティが有効な要素には、display:inline、display:inline-block、display:table-cell などがあります。逆に、display:blockである要素自体は、このvartical-alignプロパティの関与を受けませんので、このことを知らないと「あれ〜、middleにしているのに、なんで上下にセンタリングされないんだろ〜?」と時間を浪費してしまいがちです。vertical-alignは、「その行内でのテキスト配置(縦方向)」を決めるので、要素ブロックの高さ(height)とは無関係です。

この「inline-block」を使った上下中央寄せの方法には、上記の他にも「親要素の高さをどのようにして指定するか?」において、いくつかの亜種がありますが、今回は代表的なものとしてこちらをご紹介しています。

[方法2] テーブルセル作戦

これも一般的な方法で、CSSの「display:table-cell」を使います。特に親要素の「display: table」は「width: auto」の振る舞いが、「display: block」のときと異なりますので、width値を宜しく設定下さい。

仕組みとしては上述のインラインブロックと同じで「display: table-cell」なお嘘には、「vertical-align:middle」が有効ですので、これによって上下に中央寄せします。「display:table-cell」は、tableの中のみで有効ですから、親要素にもまた「display:table」の指定が必要です。

見た目は全然テーブル(表)ではないのですが、CSSをはテーブル化するという、若干の気持ち悪さが残りらなくも無いですが、スタイル(=表現)の問題だけですので、まあ問題ないでしょう。

<div class="container">
  <span class="target">テーブルセルは<br>vertical-align可能。</span>
</div>
<style>
.container{
  display:table;
  width:100%;
  height:300px;
  background-color:#eef;
  text-align:center;
}
.container .target{
  display:table-cell;
  vertical-align:middle;
}
</style>
CSS「vertical-align」プロパティについて

「行」と含まれるテキストにおいて、厳密に「縦方向の中央位置とはどこか?」の定義を話をすると、かなり話が細かくなりますので、ここでは深くは追求しませが、少しだけ触れると「vertical-align: middle」は、「その要素の縦方向の中央と、ベースラインの高さに、x-heightの半分の高さを加えた位置と合わせる」です。

参考まで、フォントには「x-height」と呼ばれる高さが定義されています。x-heightは英字フォントの小文字の高さで、フォントデータに依存します。

line-heightとフォントのライン

「baselineにx-heightの高さの半分を加えた位置(下図赤線)」は、その要素自体の中央線と必ずしも一致しません。(フォントデータ次第です。)

vertical-align:middleで利用される基準線

これは「アルファベット文字の(見た目的な)中央」と要素を揃えて見せるための計算方法ですが、要素に指定されたフォントサイズが大きければ大きいほど「要素の中央線からのズレ」は大きくなります。場合によっては、このことが問題になることもあるでしょう。

Mozila Developer Networkのページで、CSSプロパティ「vertical-align」の詳細な定義に言及しています。

ブロック要素の中央寄せ

[1] 絶対配置 + 自動マージン

ブロックレベルの要素の中央寄せで、最も直感的なのは「position:absolute」を使った方法です。このプロパティと「margin:auto」を組み合わせれば、自動的に、上下、もしくは左右がそれぞれのバランスを取るようにマージンが自動計算されます。下記の例をご覧ください。

対象となる div が初期値がブロックレベルですが、span, img, a, などのインライン要素も「display:block」でブロック化すれば同じ方法が適応できます。

<div class="container">
   <div class="target">このブロックは中央に揃えました。</div>
</div>
<style>
.container {
  height: 300px;
  background-color: #def;
  position: relative;
}
.container .target {
  height:100px;
  width: 200px;
  margin: auto;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color:rgba(255, 255, 255, 0.6);
}
</style>

絶対配置の要素が自分の座標の基準値を見つけられるよう、親要素のpositionを、relative, absolute, fixed など、initial以外の値となるようにして下さい。また、親要素の高さを明示的に固定してやる必要があります。(height: auto(初期値)では、親要素の上下に張り付くように高さが自動計算されてしまうでしょう。)

なお、対象要素のアクペクト比(縦横比)を指定してたり、画像のアスペクト比を固定したい時は、このような方法もあります。ご参考まで。

[2] 絶対配置 + 負のマージン

対象要素が絶対配置される際の基準点を、要素のマージン値を負の値にすることで、ずらす手法です。マージン値を要素の高さ、要素の幅のちょうど半分の値にすると、上下左右それぞれ中央に配置されます。

<div class="container">
   <div class="target">このブロックは中央に揃えました。</div>
</div>
<style>
.container {
  width: 100%;
  height: 300px;
  position: relative;
  background-color: #ebf;
}
.container .target {
  position: absolute;
  left: 50%;
  top: 50%;
  height:100px;
  width:200px;
  margin-top: -50px;
  margin-left: -100px;
  background-color:rgba(255, 255, 255, 0.6);
}
</style>

[3] 絶対配置 + calc() 関数

負のマージンの手法と似ていますが、こちらは、CSS「calc関数」を使った方法です。縦、横方向にそれぞれ半分をマイナスしてずらします。

<div class="container">
  <div class="target">このブロックは中央に揃えました。</div>
</div>
<style>
.container {
  width: 100%;
  height: 300px;
  position: relative;
  background-color: #cef;
}
.container .target {
  height: 100px;
  width:200px;
  position: absolute;
  top: calc(50% - 50px);
  left: calc(50% - 100px);
  background-color:rgba(255, 255, 255, 0.6);
}
</style>

基本的にcalc() 関数を用いれば、いままで難しかったレイアウトの多くが容易に実現できるようになります。ただし、対象要素の縦幅、横幅大きさを固定してやる必要があります。なお、calc() 関数は、現在ではほとんどのモダンブラウザでサポートされています。これは便利ですね。

Internet Explorerだと9以降でないとサポートがないようですが、果たして、IE8のようなユーザを対象としたウェブサイトかどうか・・・というところは考えてみてもよいでしょう。

[4] 絶対配置 + transform

「transform:translate()」によって、対象要素の表示をずらす事ができます。その要素の縦・横それぞれ50%ずらす、という指定が可能ですので、この特性をうまく利用します。transformで入力する%値は、要素自身の幅と高さを基準に相対的に計算されますので、「自分の50%」といった表現が容易に可能です。

<div class="container">
  <div class="target">このブロックは中央に揃えました。</div>
</div>
<style>
.container {
  width: 100%;
  height: 300px;
  background-color: #fca;
  position: relative;
}
.container .target {
  width:200px;
  height:100px;
  margin: auto;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  background-color:rgba(255, 255, 255, 0.6);
}
</style>

CSSは非常にすっきり記述できます。ただし、transform プロパティは、IE10以降のサポートとなります。同様にIEのサポートに関してはそもそもサポートするかどうかが判断基準ですが、これよりは上記のcalc関数の方が、サポート範囲が広いでしょうか。

[5] flexbox を利用

こちらはグリッドレイアウトで重宝するFlexboxを利用した方法です。本来は、複数の要素をグリッド状に並べるためのものですが、1つだけの要素にも適応できます。

<div class="container">
  <div class="target">このブロックは中央に揃えました。</div>
</div>
<style>
 .container{
  width:100%;
  height:300px;
  background-color:#efc;
  display:flex;
}
.container .target{
  flex:0 1 auto;
  width:200px;
  height:100px;
  margin:auto;
  background-color:rgba(255, 255, 255, 0.6);
}
</style>

FlexboxもIE10以降のサポートとなります。

Flexboxのプロパティに関しては、こちらで網羅的に解説していますので、興味のある方はぜひご覧ください:

画像の中央寄せ

基本的には画像もimg要素であれば、上記で解説した方法が適応できますが、要素の背景として設定する「background-image」を使った方法もありますので、改めてこのセクションにまとめます。

インラインのIMG要素の場合

imgタグは、デフォルトではdisplay:inlineのインライン要素です。つまり、上述のline-height作戦でも、ある程度中央寄せが可能です。(正確には、imgタグは「replaced-element」と呼ばれる種類の要素で、配置と描画はブラウザ実装依存となります。多くブラウザでは、inline-blockのような振る舞いをします)


<div class="container">
  <img class="target" src="http://www-creators.com/wp-content/uploads/2017/05/1.png">
</div>
<style>
.container {
  width: 100%;
  line-height: 300px;
  text-align: center;
  position: relative;
  background-color: #fcd;
}
.container .target {
  vertical-align:middle;
  height:120px;
}
</style>

ただし、上述のように、line-heighと vertical-align:middle の組み合わせでは、ベースラインの高さの分だけずれるため、厳密に正確な「中央寄せ」とはなりません。特にこのような画像は明確な四角形ですので、微妙なズレが問題になることもあるでしょう。

正確な中央寄せを実現するために、ひと手間増えますが、imgタグをblock化し、あとは、ブロック要素を中央寄せするための一般的な方法を適応すればOKです。下記に続きます。

ブロック化したIMG要素の場合

IMGタグを使って画像をセンタリングする場合は、上記で紹介した、絶対配置を使った方法のほうが、おすすめです。IMG要素の縦・横のいずれか片方を「auto」のままにしておくと、画像のアクペクト比(縦横比)が崩れることはありません。

<div class="container">
   <img class="target" src="http://www-creators.com/wp-content/uploads/2017/05/1.png">
</div>

<style>
.container {
  height:300px;
  background-color: #efc;
}
.container .target {
  display:block;
  position:absolute;
  height:100px; /* widthの値はデフォルトがauto */
  top:0;
  bottom:0;
  right:0;
  left:0;
  margin:auto;
}
</style>

背景画像(background-image)の場合

画像を配置する時は(特別な強い理由がない限りは)IMGタグよりも、CSSの background-imageプロパティを利用するのが、レイアウトにおいては便利です。「background-repeat: none」を追記して、背景画像の繰り返しを抑制している点に注意して下さい。

<div class="container"></div>
<style>
.container{ 
  display:block;
  height:300px;
  background-image: url(http://www-creators.com/wp-content/uploads/2017/05/1.png);
  background-position: center;
  background-size:150px;
  background-repeat: no-repeat;
  background-color:#fec;
}
</style>

このようなケースで特に使用頻度が高いのは、background-size の設定値、「cover」「contain」です。これらのキーワドのいずれかで、画像の自動サイズ調整を行うことができます。

background-size の設定値

設定値解説
cover要素に空白ができないように拡大します。はみ出した部分を切り落とします。
contain縦、横のいずれかで、要素の長さを満たすように拡大します。(要素をはみ出しません)

「background-size」と、「background-position: center」を組み合わせれば、画像の中央配置で必要となる配置方法のほとんどは実現できるでしょう。

<div class="container"></div>
<style>
.container{ 
  display:block;
  height:300px;
  background-image:url(http://www-creators.com/wp-content/uploads/2017/05/1.png);
  background-position:center center;
  background-size:contain;
  background-repeat:no-repeat;
  background-color:#fef;
}
</style>

background-positionを使った、背景画像の中央寄せ

一方で、このbackgroundプロパティを使うと、img タグのaltのような値を設定できないため、SEO観点で不利だと言われています。ですが、もしそのページが十分にテキストを配置できる限りは、画像の近くに十分なテキストを配置することで、十分カバーできこともあるはずです。alt 値は、そのページの価値の全てを左右するような魔法のキーワードではないからです。

[補足] CSSでの中央寄せの基礎知識

インラインレベルとブロックレベル

CSSでの中央寄せ配置を考える際に、その要素の「display」プロパティがどのように指定されているのか、意識する必要があります。displayプロパティが取りうる値は複数ありますが、その値によって要素は下記の2つに大きく分類されます。

  • インライン(inline)レベルの要素
  • ブロック(block)レベルの要素

これらは、その要素や、その要素が内包するテキストがどのように描画されるかを左右します。これらの概念は、CSSLevel 2 Containing Block で定義され、その後、CSS Display Module Level 3  ではCSS2の定義を置き換えるように再定義されています。

詳細な概念の理解を追求すれば逆に混乱しやすいですので、開発者は「どの値であれば、どのように描画されるか」にフォーカスして理解したほうが良さそうです。CSS仕様は基本的に後方互換を保つように設計されていますので、ここでは理解しやすさのため、CSS Level 2 にもとづいて解説します。

レイアウトにおける違い

それぞれのHTML要素(=タグ)の種類には、CSSプロパティのdisplay値の初期値として、inline、block、table、inline-block, …, など、なんらかの値が割り振られています。例えば、img要素、a要素、span要素は「inline」がデフォルトです。また、div要素、p要素は「block」がデフォルト値です。また「display: table」と指定された要素も、その描画において「ブロックレベルの要素」として扱われます。

displayの値と要素の種類(CSS2)

要素displayの値
ブロックレベルblock, list-item, table, inline-table, table-xxx(種々のtable内の値(省略))
インラインレベルinline, inline-table, inline-block

必要に応じて、これらのデフォルト値を上書きするように、CSSからdisplay 値を設定する事もあるでしょう。こちら、インラインとブロックの描画の違いをイメージで表したものです。

ブロックとインライン

インラインはテキストの文字が(左寄せであれば)左側に、行内に次々に流れ込むように表示されます。一方で、ブロックは見た目的に「あたかもブロックように」描画されます。また、ブロックレベルの要素に内包された、タグで囲まれていないテキストはすべて、インライン要素として振る舞います。

中央寄せの概念

上記の概念を踏まえると、例えば、インラインレベルのテキスト要素に対して「text-align: center」が意味を持たないことが分かります。「text-align」は、「そのブロック要素が内包するインライン要素の上下方向の配置方法」指定ですので、インライン要素自体にこの設定値は無効です。また別の例では、「width」プロパティは、ブロックレベル要素には有効ですが、インラインには意味を持ちません。

このように、要素がインラインとブロックかを理解する事は、CSSでの中央寄せを正しく理解するためは、必要不可欠といえるでしょう。

関連情報

CSSプロパティ「vertical-align」の詳細です。

閉じる