【CSS】vertical-alignの使い方:効かない原因と上下中央揃え

css-vertical-align
ポートフォリオ向けサーバー
HTML/CSSスキルが活きる!
学んだ知識を活かして、
自分だけのブログを始めませんか?

WordPressブログなら、あなたのコーディング知識でデザインのカスタマイズが自由自在。
ブログデビューに最適な初心者向けサーバー環境を徹底比較しました。

CSSのvertical-alignは、アイコンのズレ解消やテーブルの縦揃えに欠かせないプロパティですが、「ブロック要素には効かない」という罠も潜んでいます。

本記事では、基本仕様と効かない原因、FlexboxやGridを用いたモダンな中央揃えの代替テクニックまで解説します。

HTML/CSS学習者の方へ
「学んだコード、自分のブログで試してみませんか?」
多くのブロガーがデザインでつまずく中、コードが読めるあなたは圧倒的に有利です。
自由自在なサイト構築の第一歩となる、初心者向けサーバーを分かりやすく比較しました。

\ スキルを活かして情報発信 / ブログ向けレンタルサーバー4選を読む▶︎
目次

vertical-alignとは?基本仕様と効かない原因

Webデザインにおいて、要素を「縦方向に中央揃えしたい」という要望は多いです。

その際、初心者が真っ先に使おうとして挫折するのがvertical-alignです。

vertical-alignとは、本来は「テキストや画像などのインライン要素やテーブルセル(<td>)内のコンテンツ」の縦位置を微調整するプロパティです。

vertical-alignを使いこなすには、このプロパティが持つ本来の役割と限界を理解する必要があります。

ここでは、vertical-alignの基本、なぜ初心者がvertical-alignの例を真似しても意図通りにならないのか、原因と解決策について解説します。

vertical-alignとは?基本仕様と効かない原因
  • インライン要素とテーブルセル専用!ブロック要素には効かない
  • baselinemiddletopbottomなど値の違いと基準線

インライン要素とテーブルセル専用!ブロック要素には効かない

実務で多いトラブルが、<div><p>といった「ブロック要素」の縦位置を揃えようとしてvertical-align: middle;を指定し、「vertical-alignが効かない」と頭を抱えるケースです。

縦方向揃えには、ブロック要素を縦中央揃えにしたいなら、vertical-alignは捨てて、現代の標準であるFlexboxalign-items: center;)やGridを使うことです。

vertical-alignはあくまで『行の中のインライン要素』や『テーブルのセル』の微調整のために温存しておくことです。

⭕️ 「ブロック要素」にvertical-alignは効かない!Flexboxを使うのが正解だ!

❌ 罠(効かない)

ブロック要素は無視される

⭕️ 成功(Flexbox)

Flexboxで縦中央揃え
/* ❌ 罠:ブロック要素に指定しても何も起きない */
.block-fail {
  vertical-align: middle; /* 🚨 無視される */
}

/* ⭕️ Flexboxで制御する */
.flex-success {
  display: flex;
  align-items: center; /* 💡 縦中央揃えの決定版 */
  justify-content: center; /* 横中央も揃える */
}
HTMLコード表示
<div class="va-basic-wrapper">
  
  <p class="va-basic-caption">⭕️ 「ブロック要素」にvertical-alignは効かない!Flexboxを使うのが正解だ!</p>

  <div class="va-demo-area">
    
    <div class="va-box">
      <p class="va-title">❌ 罠(効かない)</p>
      <div class="block-fail">
        <div class="content">ブロック要素は無視される</div>
      </div>
    </div>

    <div class="va-box">
      <p class="va-title">⭕️ 成功(Flexbox)</p>
      <div class="flex-success">
        <div class="content">Flexboxで縦中央揃え</div>
      </div>
    </div>

  </div>

  <div class="va-code-area">
    <span class="hl-comment">/* ❌ 罠:ブロック要素に指定しても何も起きない */</span><br>
    <span class="hl-blue">.block-fail</span> {<br>
      <span class="hl-green">vertical-align:</span> <span class="hl-red">middle;</span> <span class="hl-comment">/* 🚨 無視される */</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ Flexboxで制御する */</span><br>
    <span class="hl-blue">.flex-success</span> {<br>
      <span class="hl-green">display:</span> <span class="hl-red">flex;</span><br>
      <span class="hl-green">align-items:</span> <span class="hl-red">center;</span> <span class="hl-comment">/* 💡 縦中央揃えの決定版 */</span><br>
      <span class="hl-green">justify-content:</span> <span class="hl-red">center;</span> <span class="hl-comment">/* 横中央も揃える */</span><br>
    }
  </div>

</div>
CSSコード表示
.va-basic-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.va-basic-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.va-demo-area {
  display: flex;
  flex-direction: column;
  gap: 30px;
  background-color: #e9ecef;
  padding: 30px 20px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
  align-items: center;
}

.va-box {
  width: 100%;
  max-width: 300px;
  background-color: #ffffff;
  padding: 15px;
  border: 1px solid #ced4da;
  border-radius: 4px;
}

.va-title {
  margin: 0 0 10px 0;
  font-size: 13px;
  font-weight: bold;
  color: #dc3545;
  border-bottom: 1px dashed #ced4da;
  padding-bottom: 5px;
}

.va-box:last-child .va-title {
  color: #198754;
}

/* === 💡 罠のコンテナ === */
.block-fail {
  height: 80px;
  background-color: #f8d7da;
  vertical-align: middle; /* 効かない */
}

/* === 💡 成功のコンテナ === */
.flex-success {
  height: 80px;
  background-color: #d1e7dd;
  display: flex;
  align-items: center;
  justify-content: center;
}

.content {
  background: #fff;
  padding: 5px;
  font-size: 12px;
  border: 1px solid #333;
}

/* =コード解説エリア(エディタ風)= */
.va-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}
.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }

FlexboxやGridの使い方を詳しく知りたい人は以下から一読ください。

baseline・middle・top・bottomなど値の違いと基準線

vertical-alignは、対象となるインライン要素やセルの中での「基準線(ベースライン)」に対する位置を指定します。

基準線を理解すると、アイコンとテキストを綺麗に並べるような微調整が可能になります。

  • baseline
    親要素のベースラインに揃える(初期値)。
  • middle
    インライン要素の「高さの中間」を親要素の「ベースライン+親要素のx-heightの半分」に揃える。
  • top
    要素の上端をその行の要素全体の上端に揃える。
  • bottom
    要素の下端をその行の要素全体の下端に揃える。
  • text-top/text-bottom
    テキストの上端/下端に揃える。
  • sub/super
    下付き/上付き文字。

値を使い分けるには、vertical-align: middle;はあくまでインライン要素(アイコンと文字など)の微調整に使うことです。

中央揃えが求められるUI設計では、vertical-alignに頼らず、Flexboxalign-items: center;を使用することです。

⭕️ vertical-alignの「値」による微妙なズレを理解して使い分けろ!

文字 top middle bottom
/* 💡 アイコンや小さい要素を並べる際に使用 */
.is-top { vertical-align: top; }
.is-middle { vertical-align: middle; }
.is-bottom { vertical-align: bottom; }
HTMLコード表示
<div class="va-value-wrapper">
  
  <p class="va-value-caption">⭕️ vertical-alignの「値」による微妙なズレを理解して使い分けろ!</p>

  <div class="va-value-demo-area">
    
    <div class="va-value-box">
      <span class="txt">文字</span>
      <span class="icon is-top">top</span>
      <span class="icon is-middle">middle</span>
      <span class="icon is-bottom">bottom</span>
    </div>

  </div>

  <div class="va-value-code-area">
    <span class="hl-comment">/* 💡 アイコンや小さい要素を並べる際に使用 */</span><br>
    <span class="hl-blue">.is-top</span> { <span class="hl-green">vertical-align:</span> <span class="hl-red">top;</span> }<br>
    <span class="hl-blue">.is-middle</span> { <span class="hl-green">vertical-align:</span> <span class="hl-red">middle;</span> }<br>
    <span class="hl-blue">.is-bottom</span> { <span class="hl-green">vertical-align:</span> <span class="hl-red">bottom;</span> }
  </div>

</div>
CSSコード表示
.va-value-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.va-value-demo-area {
  background-color: #fff;
  padding: 20px;
  border: 1px solid #adb5bd;
  font-size: 20px; /* 文字を大きくして見やすく */
  line-height: 3;
}

.icon {
  background-color: #0d6efd;
  color: #fff;
  padding: 5px;
  font-size: 10px;
  margin: 0 5px;
}

.is-top { vertical-align: top; }
.is-middle { vertical-align: middle; }
.is-bottom { vertical-align: bottom; }

.va-value-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  margin-top: 20px;
}

アイコンや画像とテキストの縦ズレを直す

Web制作の現場において、「テキストの横にアイコンを置いたらアイコンだけが少し上に浮いて見える」「入力欄とラベルが微妙にズレている」という現象は、誰もが経験する悩みです。

アイコンや画像の調整は、フォントの特性やベースライン(文字の基準線)の仕組みが深く関わっており、初心者にとっては迷宮入りしやすいポイントです。

ここでは、画像やテキストに対してレイアウトを揃える実装を解説します。

アイコンや画像とテキストの縦ズレを直す
  • アイコンと横の文字の縦位置を揃える
  • spanタグやボタン・入力欄の高さ合わせ

アイコンと横の文字の縦位置を揃える

アイコン画像(imgsvg)と横並びのテキストを揃える際、デフォルトのままでは、アイコンの下端がテキストのベースラインに揃えられてしまいます。

これによってアイコンが不自然に浮き上がって見えます。

アイコンと文字を揃えるには、vertical-alignは『親』ではなく、『アイコン』そのものに直接指定することです。

また、フォントの特性で微妙なズレが残る場合は、CSSのposition: relative; top: -1px;等で数ピクセル単位の微調整を行うのがよいです。

⭕️ アイコンを揃えるなら「画像」自体に指定しろ!親に書いても効かない!

❌ 罠(親に指定)

アイコンが上に浮いている

⭕️ 成功(アイコンに直接指定)

アイコンが中央で揃っている
/* ❌ 罠:親要素に指定しても、子要素の画像は全く動かない */
.align-fail {
  vertical-align: middle; /* 🚨 親に書いても無視される */
}

/* ⭕️ 対象の要素(画像やアイコン)に直接指定する! */
.is-aligned {
  vertical-align: middle; /* 💡 アイコン自体を中央へ下ろす */
  /* ※さらに微調整が必要な場合は position: relative; top: -1px; 等を使う */
}
HTMLコード表示
<div class="icon-align-wrapper">
  
  <p class="icon-align-caption">⭕️ アイコンを揃えるなら「画像」自体に指定しろ!親に書いても効かない!</p>

  <div class="icon-demo-area">
    
    <div class="demo-item">
      <p class="demo-title">❌ 罠(親に指定)</p>
      <div class="align-fail">
        <span class="icon-demo-img">★</span> アイコンが上に浮いている
      </div>
    </div>

    <div class="demo-item">
      <p class="demo-title">⭕️ 成功(アイコンに直接指定)</p>
      <div class="align-success">
        <span class="icon-demo-img is-aligned">★</span> アイコンが中央で揃っている
      </div>
    </div>

  </div>

  <div class="icon-code-area">
    <span class="hl-comment">/* ❌ 罠:親要素に指定しても、子要素の画像は全く動かない */</span><br>
    <span class="hl-blue">.align-fail</span> {<br>
      <span class="hl-green">vertical-align:</span> <span class="hl-red">middle;</span> <span class="hl-comment">/* 🚨 親に書いても無視される */</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ 対象の要素(画像やアイコン)に直接指定する! */</span><br>
    <span class="hl-blue">.is-aligned</span> {<br>
      <span class="hl-green">vertical-align:</span> <span class="hl-red">middle;</span> <span class="hl-comment">/* 💡 アイコン自体を中央へ下ろす */</span><br>
      <span class="hl-comment">/* ※さらに微調整が必要な場合は position: relative; top: -1px; 等を使う */</span><br>
    }
  </div>

</div>
CSSコード表示
.icon-align-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.icon-align-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.icon-demo-area {
  display: flex;
  flex-direction: column;
  gap: 30px;
  background-color: #e9ecef;
  padding: 30px 20px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
  align-items: center;
}

.demo-item {
  width: 100%;
  max-width: 350px;
  background-color: #ffffff;
  padding: 15px;
  border: 1px solid #ced4da;
  border-radius: 4px;
}

.demo-title {
  margin: 0 0 10px 0;
  font-size: 13px;
  font-weight: bold;
  color: #dc3545;
  border-bottom: 1px dashed #ced4da;
  padding-bottom: 5px;
}

.demo-item:last-child .demo-title {
  color: #198754;
}

/* === 💡 画像(img/svg)と同じ振る舞いをするアイコン === */
.icon-demo-img {
  display: inline-block;
  width: 32px;
  height: 32px;
  background-color: #0d6efd;
  color: #ffffff;
  border-radius: 4px;
  text-align: center;
  line-height: 32px;
  font-size: 16px;
  
  /* 💡 必須:overflow: hidden をかけることで、
     中の文字のベースラインが無視され、箱の下端が基準(=画像と同じ状態)になる */
  overflow: hidden; 
}

/* === ❌ 罠のコンテナ(親指定) === */
.align-fail {
  font-size: 15px;
  color: #333;
  line-height: 1.5;
  border-bottom: 1px solid #ccc; /* 足元(ベースライン付近)を可視化 */
  
  /* 🚨 親に指定してもアイコンは動かない */
  vertical-align: middle; 
}

/* === ⭕️ 成功のコンテナ === */
.align-success {
  font-size: 15px;
  color: #333;
  line-height: 1.5;
  border-bottom: 1px solid #ccc; /* 足元(ベースライン付近)を可視化 */
}

/* 💡 アイコン自体に指定する */
.is-aligned {
  vertical-align: middle; 
}

/* =コード解説エリア(エディタ風)= */
.icon-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}
.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }

imgタグやpositionプロパティの使い方を詳しく知りたい人は以下から一読ください。

spanタグやボタン・入力欄の高さ合わせ

フォーム周りでspanタグやボタン・入力欄を使おうとするケースも多いです。

特に、ボタンの中に小さなアイコンを入れたり、入力欄の横にヘルプテキストを置く際に高さが合わない問題が頻発します。

これらはすべて「インラインレベル要素」であるためvertical-alignで並べることが多いですが、要素ごとに持っているデフォルトの高さ(line-heightborder)が異なるため、middleを指定しても微妙にズレます。

高さ合わせには、vertical-alignは微調整用として割り切り、根本的な高さ合わせは『Flexbox』で行うことです。

ボタンも入力欄もコンテナ(親)に入れてalign-items: center;を指定すれば、内部のフォント設定やボーダーの太さに左右されず100%縦位置が揃います。

⭕️ ボタンと入力欄は「vertical-align」ではなく「Flexbox」で中央揃えにせよ!

※ヘルプテキスト
/* ⭕️ 親をFlexにするだけで全て解決する */
.form-container {
  display: flex;
  align-items: center; /* 💡 高さに関係なく中央揃え */
  gap: 10px;
}
HTMLコード表示
<div class="form-align-wrapper">
  
  <p class="form-align-caption">⭕️ ボタンと入力欄は「vertical-align」ではなく「Flexbox」で中央揃えにせよ!</p>

  <div class="form-demo-area">
    
    <div class="form-container">
      <input type="text" placeholder="テキスト入力">
      <button>送信</button>
      <span>※ヘルプテキスト</span>
    </div>

  </div>

  <div class="form-code-area">
    <span class="hl-comment">/* ⭕️ 親をFlexにするだけで全て解決する */</span><br>
    <span class="hl-blue">.form-container</span> {<br>
      <span class="hl-green">display:</span> <span class="hl-red">flex;</span><br>
      <span class="hl-green">align-items:</span> <span class="hl-red">center;</span> <span class="hl-comment">/* 💡 高さに関係なく中央揃え */</span><br>
      <span class="hl-green">gap:</span> <span class="hl-red">10px;</span><br>
    }
  </div>

</div>
CSSコード表示
.form-align-wrapper { background-color: #f8f9fa; padding: 30px; border-radius: 8px; }
.form-demo-area { background: #fff; padding: 20px; border: 1px solid #ccc; }
.form-container { display: flex; align-items: center; gap: 10px; }
input { padding: 8px; }
button { padding: 8px 15px; }
span { font-size: 12px; color: #666; }

.form-code-area {
  background-color: #282c34; color: #abb2bf; padding: 20px; border-radius: 6px;
  font-family: monospace; font-size: 13px; margin-top: 20px;
}

align-itemsの使い方を詳しく知りたい人は「【CSS】flexの使い方:justify-content・align-items・gap」を一読ください。

テーブルのセル内で要素を上下中央・上揃えにする

インライン要素に対して使われることが多いvertical-alignですが、もう一つの本来の主戦場が「テーブル(表組み)」です。

テーブルは、ブラウザが標準でサポートしている仕様であり、正しく理解することで美しいデータ表を直感的に作成できます。

前章で「ブロック要素には効かない」と解説しましたが、テーブルのセル内では話が全く異なります。

ここでは、表組み特有の挙動と応用した「divのテーブル化」まで解説します。

テーブルのセル内で要素を上下中央・上揃えにする
  • tdth要素に対してvertical-alignを適用する
  • display: table-cellを使ってdivをテーブル化する

tdやth要素に対してvertical-alignを適用する

HTMLのテーブル要素において、セルの高さを広げた際に中身のテキストがどこに配置されるかはvertical-alignによって決定されます。

初期値はmiddle(中央揃え)になっていることが多いですが、文章量が多いセルと少ないセルが並んだ場合、top(上揃え)に変更して読みやすくする調整が実務で頻発します。

テーブルにおける縦揃えは、vertical-alignはセルの中のテキストや要素に対して指定するのではなく、枠そのものである<td><th>に対して直接指定することです。

これにより、セル全体というハコの中でコンテンツが綺麗に配置されます。

⭕️ テーブルの縦揃えは「中身」ではなく「td(セル)」自体に指定しろ!

❌ 罠(中身のpタグに指定) ⭕️ 成功(tdにtopを指定) ⭕️ 成功(tdにmiddleを指定)

罠:pタグへの指定
(中央のまま動かない)

成功:tdへの指定
(上に揃う)

成功:tdへの指定
(中央に揃う)

/* ❌ 罠:セルの中の要素に指定してしまう */
.text-fail {
  vertical-align: top; /* 🚨 ブロック要素なので完全に無視される! */
}

/* ⭕️ 枠である td に対して直接指定する! */
.td-success-top {
  vertical-align: top; /* 💡 セル内の余白を使って上揃えになる */
}
.td-success-middle {
  vertical-align: middle; /* 💡 セル内の余白を使って中央揃えになる */
}
HTMLコード表示
<div class="table-align-wrapper">
  
  <p class="table-align-caption">⭕️ テーブルの縦揃えは「中身」ではなく「td(セル)」自体に指定しろ!</p>

  <div class="table-demo-area">
    
    <table class="custom-demo-table">
      <thead>
        <tr>
          <th class="th-style">❌ 罠(中身のpタグに指定)</th>
          <th class="th-style">⭕️ 成功(tdにtopを指定)</th>
          <th class="th-style">⭕️ 成功(tdにmiddleを指定)</th>
        </tr>
      </thead>
      <tbody>
        <tr class="tall-row">
          
          <td class="td-fail">
            <p class="text-fail">罠:pタグへの指定<br>(中央のまま動かない)</p>
          </td>
          
          <td class="td-success-top">
            <p class="text-success">成功:tdへの指定<br>(上に揃う)</p>
          </td>
          
          <td class="td-success-middle">
            <p class="text-success">成功:tdへの指定<br>(中央に揃う)</p>
          </td>
          
        </tr>
      </tbody>
    </table>

  </div>

  <div class="table-code-area">
    <span class="hl-comment">/* ❌ 罠:セルの中の要素に指定してしまう */</span><br>
    <span class="hl-blue">.text-fail</span> {<br>
      <span class="hl-green">vertical-align:</span> <span class="hl-red">top;</span> <span class="hl-comment">/* 🚨 ブロック要素なので完全に無視される! */</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ 枠である td に対して直接指定する! */</span><br>
    <span class="hl-blue">.td-success-top</span> {<br>
      <span class="hl-green">vertical-align:</span> <span class="hl-red">top;</span> <span class="hl-comment">/* 💡 セル内の余白を使って上揃えになる */</span><br>
    }<br>
    <span class="hl-blue">.td-success-middle</span> {<br>
      <span class="hl-green">vertical-align:</span> <span class="hl-red">middle;</span> <span class="hl-comment">/* 💡 セル内の余白を使って中央揃えになる */</span><br>
    }
  </div>

</div>
CSSコード表示
.table-align-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.table-align-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.table-demo-area {
  background-color: #ffffff;
  padding: 20px;
  border: 1px dashed #adb5bd;
  border-radius: 8px;
  margin-bottom: 20px;
  overflow-x: auto;
}

/* === デモ用テーブルのスタイル === */
.custom-demo-table {
  width: 100%;
  border-collapse: collapse;
  min-width: 600px;
}

.custom-demo-table th,
.custom-demo-table td {
  border: 1px solid #ced4da;
  padding: 15px;
  font-size: 14px;
  line-height: 1.5;
}

.th-style {
  background-color: #e9ecef;
  color: #495057;
  text-align: center;
}

/* 💡 違いを見せるためにセルの高さを強制的に広げる */
.tall-row td {
  height: 150px; 
}

/* === ❌ 罠:pタグへの指定 === */
.td-fail {
  background-color: #f8d7da;
  /* 🚨 td側には何も指定していないため、デフォルトのmiddleになる */
}
.text-fail {
  color: #842029;
  margin: 0;
  font-weight: bold;
  /* 🚨 ブロック要素への指定なので無視される */
  vertical-align: top; 
}

/* === ⭕️ 成功:tdへの直接指定 === */
.td-success-top {
  background-color: #d1e7dd;
  /* 💡 セルに対して上揃え */
  vertical-align: top;
}

.td-success-middle {
  background-color: #cfe2ff;
  /* 💡 セルに対して中央揃え */
  vertical-align: middle;
}

.text-success {
  margin: 0;
  font-weight: bold;
  color: #0f5132;
}
.td-success-middle .text-success {
  color: #084298;
}

/* =コード解説エリア(エディタ風)= */
.table-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}
.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }

テーブルの作り方を詳しく知りたい人は「【HTML】tableタグ(テーブル)の使い方:枠線・セル結合・レスポンシブ」を一読ください。

display: table-cellを使ってdivをテーブル化する

Flexboxが普及する前のWebデザインにおいて、div内の要素を上下中央にするを実現する裏技として君臨していたのがdisplay: table-cell;を使ったテクニックです。

ただの<div>要素をCSSの力で強制的にテーブルのセル(<td>)として振る舞わせることで、ブロック要素の弱点を克服しvertical-alignを有効化させます。

このテクニックは、現在でも堅牢なフォールバックとして、あるいはHTMLメールのコーディングなど特定の環境で を行う際に重宝されています。

divをテーブル化するには、『親要素にdisplay: table;』と『子要素にdisplay: table-cell;』をセットで記述することです。

また、テーブルレイアウトはコンテンツの量に幅が依存しやすいため、親要素にはwidth: 100%;などの明確な幅を持たせてレイアウトの崩壊を防ぐことです。

⭕️ divをセル化する裏技!親の「display: table」を絶対に忘れるな!

❌ 罠
親に display: table がない
⭕️ 成功
これが css vertical align middle div の伝統的で強固な裏技です。
/* ❌ 罠:子要素だけに table-cell を指定してしまう */
.cell-fail {
  display: table-cell;
  vertical-align: middle;
  /* 🚨 親が table ではないため、幅の計算などが狂いやすい */
}

/* ⭕️ 親(table) と 子(table-cell) を必ずセットにする! */
.parent-table {
  display: table; /* 💡 必須:親をテーブル化 */
  width: 100%; /* 💡 レイアウト崩れ防止 */
  height: 150px;
}
.child-cell {
  display: table-cell; /* 💡 必須:子をセル化 */
  vertical-align: middle; /* 💡 これで完璧な上下中央揃えが発動 */
  text-align: center;
}
HTMLコード表示
<div class="table-cell-wrapper">
  
  <p class="table-cell-caption">⭕️ divをセル化する裏技!親の「display: table」を絶対に忘れるな!</p>

  <div class="table-cell-demo-area">
    
    <div class="pseudo-table-fail">
      <div class="pseudo-cell-fail">
        ❌ 罠<br>親に display: table がない
      </div>
    </div>

    <div class="pseudo-table-success">
      <div class="pseudo-cell-success">
        ⭕️ 成功<br>これが css vertical align middle div の伝統的で強固な裏技です。
      </div>
    </div>

  </div>

  <div class="table-code-area">
    <span class="hl-comment">/* ❌ 罠:子要素だけに table-cell を指定してしまう */</span><br>
    <span class="hl-blue">.cell-fail</span> {<br>
      <span class="hl-green">display:</span> <span class="hl-red">table-cell;</span><br>
      <span class="hl-green">vertical-align:</span> <span class="hl-red">middle;</span><br>
      <span class="hl-comment">/* 🚨 親が table ではないため、幅の計算などが狂いやすい */</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ 親(table) と 子(table-cell) を必ずセットにする! */</span><br>
    <span class="hl-blue">.parent-table</span> {<br>
      <span class="hl-green">display:</span> <span class="hl-red">table;</span> <span class="hl-comment">/* 💡 必須:親をテーブル化 */</span><br>
      <span class="hl-green">width:</span> <span class="hl-red">100%;</span> <span class="hl-comment">/* 💡 レイアウト崩れ防止 */</span><br>
      <span class="hl-green">height:</span> <span class="hl-red">150px;</span><br>
    }<br>
    <span class="hl-blue">.child-cell</span> {<br>
      <span class="hl-green">display:</span> <span class="hl-red">table-cell;</span> <span class="hl-comment">/* 💡 必須:子をセル化 */</span><br>
      <span class="hl-green">vertical-align:</span> <span class="hl-red">middle;</span> <span class="hl-comment">/* 💡 これで完璧な上下中央揃えが発動 */</span><br>
      <span class="hl-green">text-align:</span> <span class="hl-red">center;</span><br>
    }
  </div>

</div>
CSSコード表示
.table-cell-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.table-cell-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.table-cell-demo-area {
  display: flex;
  flex-direction: column;
  gap: 30px;
  background-color: #e9ecef;
  padding: 30px 20px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
  align-items: center;
}

/* === ❌ 罠:親がただのdiv === */
.pseudo-table-fail {
  width: 100%;
  max-width: 400px;
  height: 120px;
  background-color: #ffffff;
  border: 1px solid #ced4da;
  border-radius: 4px;
  /* 🚨 親に display: table; がない */
}

.pseudo-cell-fail {
  /* 子要素だけ table-cell にしている */
  display: table-cell;
  vertical-align: middle;
  background-color: #f8d7da;
  color: #842029;
  padding: 20px;
  font-weight: bold;
  /* 幅が100%に広がらず、レイアウトが不自然になる */
}

/* === ⭕️ 成功:親と子の連携 === */
.pseudo-table-success {
  width: 100%;
  max-width: 400px;
  height: 120px;
  background-color: #ffffff;
  border: 1px solid #ced4da;
  border-radius: 4px;
  
  /* 💡 親をテーブルにする */
  display: table; 
}

.pseudo-cell-success {
  /* 💡 子をセルにする */
  display: table-cell;
  
  /* 💡 セルなので vertical-align が完璧に効く */
  vertical-align: middle;
  text-align: center;
  
  background-color: #d1e7dd;
  color: #0f5132;
  padding: 20px;
  font-weight: bold;
}

/* =コード解説エリア(エディタ風)= */
.table-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}
.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }

divタグの使い方を詳しく知りたい人は「【HTML】divタグの使い方:横並びや中央寄せ・CSS装飾」を一読ください。

Flexbox・Grid・Absoluteでの上下中央揃え

前章まで解説したvertical-alignは、インライン要素やテーブルセルといった「行の中の微調整」には強力ですが、Webサイト全体のレイアウト構築には不向きです。

現代のWeb制作において、上下左右の配置をコントロールする主役は「Flexbox」や「Grid」、「Absolute(絶対配置)」です。

画像とテキストを中央に配置する、ブロック要素全体を画面の中央に置くなど、実務で100%使うモダンな解決策を解説します。

Flexbox・Grid・Absoluteでの上下中央揃え
  • Flexboxでdivの中身を上下左右の中央揃えにする
  • Gridを使った中央配置とposition: absoluteでの絶対配置
  • Flexboxを使わない古き良きline-heightハック

Flexboxでdivの中身を上下左右の中央揃えにする

現在、Flexboxを使った上下中央揃えは、Webデザインにおける標準的な手法です。

親要素に役割を持たせることで、中身が画像であれ、テキストであれ、複数のdiv要素であれ、いとも簡単に中央へ配置できます。

また、上揃えにしたい場合はalign-items: flex-start;に変えるだけという柔軟性も魅力です。

Flexboxで上下中央揃えをするには、display: flex;justify-content: center;(左右中央)、align-items: center;(上下中央)の3点セットを記述することです。

何より、親要素にheight: 100vh;min-height: 200px;などの『十分な高さ』を持たせることです。

⭕️ Flexboxで上下中央にしたいなら、親要素に「動けるだけの高さ」を与えろ!

❌ 罠(height指定なし)

中央?

⭕️ 成功(height指定あり)

完全な中央
/* ❌ 罠:高さがないと、子要素の高さに親が縮んでしまうため中央揃えが機能しない */
.parent-fail {
  display: flex;
  justify-content: center;
  align-items: center;
  /* 🚨 heightがない! */
}

/* ⭕️ 高さをしっかり持たせ、3点セットでど真ん中へ! */
.parent-success {
  display: flex;
  justify-content: center; /* 💡 左右の中央 */
  align-items: center; /* 💡 上下の中央 */
  height: 150px; /* 💡 必須:動くための余白(高さ) */
}
HTMLコード表示
<div class="modern-flex-wrapper">
  
  <p class="modern-flex-caption">⭕️ Flexboxで上下中央にしたいなら、親要素に「動けるだけの高さ」を与えろ!</p>

  <div class="modern-flex-demo-area">
    
    <div class="flex-box-container">
      <p class="flex-demo-title">❌ 罠(height指定なし)</p>
      <div class="flex-parent-fail">
        <div class="flex-child">中央?</div>
      </div>
    </div>

    <div class="flex-box-container">
      <p class="flex-demo-title">⭕️ 成功(height指定あり)</p>
      <div class="flex-parent-success">
        <div class="flex-child">完全な中央</div>
      </div>
    </div>

  </div>

  <div class="modern-flex-code-area">
    <span class="hl-comment">/* ❌ 罠:高さがないと、子要素の高さに親が縮んでしまうため中央揃えが機能しない */</span><br>
    <span class="hl-blue">.parent-fail</span> {<br>
      <span class="hl-green">display:</span> <span class="hl-red">flex;</span><br>
      <span class="hl-green">justify-content:</span> <span class="hl-red">center;</span><br>
      <span class="hl-green">align-items:</span> <span class="hl-red">center;</span><br>
      <span class="hl-comment">/* 🚨 heightがない! */</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ 高さをしっかり持たせ、3点セットでど真ん中へ! */</span><br>
    <span class="hl-blue">.parent-success</span> {<br>
      <span class="hl-green">display:</span> <span class="hl-red">flex;</span><br>
      <span class="hl-green">justify-content:</span> <span class="hl-red">center;</span> <span class="hl-comment">/* 💡 左右の中央 */</span><br>
      <span class="hl-green">align-items:</span> <span class="hl-red">center;</span> <span class="hl-comment">/* 💡 上下の中央 */</span><br>
      <span class="hl-green">height:</span> <span class="hl-red">150px;</span> <span class="hl-comment">/* 💡 必須:動くための余白(高さ) */</span><br>
    }
  </div>

</div>
CSSコード表示
.modern-flex-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.modern-flex-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.modern-flex-demo-area {
  display: flex;
  flex-wrap: wrap;
  gap: 30px;
  background-color: #e9ecef;
  padding: 30px 20px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
  justify-content: center;
}

.flex-box-container {
  width: 100%;
  max-width: 300px;
}

.flex-demo-title {
  margin: 0 0 10px 0;
  font-size: 13px;
  font-weight: bold;
  color: #dc3545;
}

.flex-box-container:last-child .flex-demo-title {
  color: #198754;
}

/* === ❌ 罠:高さのないFlex親 === */
.flex-parent-fail {
  background-color: #f8d7da;
  border: 2px dashed #dc3545;
  
  display: flex;
  justify-content: center;
  align-items: center;
  /* 🚨 heightがないため、子要素の高さに依存する */
}

/* === ⭕️ 成功:高さのあるFlex親 === */
.flex-parent-success {
  background-color: #d1e7dd;
  border: 2px dashed #198754;
  
  display: flex;
  justify-content: center;
  align-items: center;
  /* 💡 必須:高さを指定する */
  height: 150px; 
}

/* === 共通の子要素 === */
.flex-child {
  background-color: #0d6efd;
  color: #ffffff;
  padding: 15px 25px;
  border-radius: 4px;
  font-weight: bold;
  font-size: 14px;
}

/* =コード解説エリア(エディタ風)= */
.modern-flex-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}

display: flex;の使い方を詳しく知りたい人は「【CSS】flexの使い方:justify-content・align-items・gap」を一読ください。

Gridを使った中央配置とposition: absoluteでの絶対配置

Flexboxと並んで現代のレイアウトを支えるのがGridと重ね合わせ表現に必須のAbsolute(絶対配置)です。

Gridは、Flexboxよりもさらに短いコードで中央揃えを実現できるモダンな手法です。

一方、画像の上に「NEW」といったバッジを重ねたり、画面全体にモーダルウィンドウを被せたりする際には、要素を通常の文書フローから切り離して配置するabsoluteが解決策となります。

GridとAbsoluteは、「手っ取り早く中央揃えしたいなら、親要素にdisplay: grid; place-items: center;のたった2行を書くのが現代のショートカット」です。

一方、要素を上に被せる『絶対配置』で中央揃えにするなら、top: 50%; left: 50%;に加えてtransform: translate(-50%, -50%);を記述し、自分自身のサイズの半分だけ左上に引き戻すことです。

⭕️ 要素を被せるなら Absolute と Transform!ただの中央揃えなら Grid が最速!

💡 Grid(たった2行で中央)

Grid Center

💡 Absolute(バッジなどを重ねる)

ダミー画像
NEW
/* ⭕️ 現代の最速中央揃えは Grid を使う */
.parent-grid {
  display: grid;
  place-items: center; /* 💡 この2行だけで上下左右の中央揃えが完了! */
  height: 150px;
}

/* ⭕️ Absoluteは translate で左上に引き戻す! */
.parent-abs {
  position: relative; /* 💡 親を基準点にする */
}
.child-abs {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%); /* 💡 これがないと右下にズレる!必須! */
}
HTMLコード表示
<div class="grid-abs-wrapper">
  
  <p class="grid-abs-caption">⭕️ 要素を被せるなら Absolute と Transform!ただの中央揃えなら Grid が最速!</p>

  <div class="grid-abs-demo-area">
    
    <div class="layout-demo-box">
      <p class="layout-demo-title">💡 Grid(たった2行で中央)</p>
      <div class="grid-parent">
        <div class="grid-child">Grid Center</div>
      </div>
    </div>

    <div class="layout-demo-box">
      <p class="layout-demo-title">💡 Absolute(バッジなどを重ねる)</p>
      <div class="abs-parent">
        <img src="data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22200%22%20height%3D%22150%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20200%20150%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_18900000000%20text%20%7B%20fill%3A%23999%3Bfont-weight%3Anormal%3Bfont-family%3Avar(--bs-font-sans-serif)%2C%20sans-serif%3Bfont-size%3A12pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_18900000000%22%3E%3Crect%20width%3D%22200%22%20height%3D%22150%22%20fill%3D%22%23e9ecef%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%2275.5%22%20y%3D%2280.5%22%3EImage%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E" alt="ダミー画像" class="abs-image">
        <div class="abs-child">NEW</div>
      </div>
    </div>

  </div>

  <div class="grid-abs-code-area">
    <span class="hl-comment">/* ⭕️ 現代の最速中央揃えは Grid を使う */</span><br>
    <span class="hl-blue">.parent-grid</span> {<br>
      <span class="hl-green">display:</span> <span class="hl-red">grid;</span><br>
      <span class="hl-green">place-items:</span> <span class="hl-red">center;</span> <span class="hl-comment">/* 💡 この2行だけで上下左右の中央揃えが完了! */</span><br>
      <span class="hl-green">height:</span> <span class="hl-red">150px;</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ Absoluteは translate で左上に引き戻す! */</span><br>
    <span class="hl-blue">.parent-abs</span> {<br>
      <span class="hl-green">position:</span> <span class="hl-red">relative;</span> <span class="hl-comment">/* 💡 親を基準点にする */</span><br>
    }<br>
    <span class="hl-blue">.child-abs</span> {<br>
      <span class="hl-green">position:</span> <span class="hl-red">absolute;</span><br>
      <span class="hl-green">top:</span> <span class="hl-red">50%;</span><br>
      <span class="hl-green">left:</span> <span class="hl-red">50%;</span><br>
      <span class="hl-green">transform:</span> <span class="hl-red">translate(-50%, -50%);</span> <span class="hl-comment">/* 💡 これがないと右下にズレる!必須! */</span><br>
    }
  </div>

</div>
CSSコード表示
.grid-abs-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.grid-abs-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.grid-abs-demo-area {
  display: flex;
  flex-wrap: wrap;
  gap: 30px;
  background-color: #e9ecef;
  padding: 30px 20px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
  justify-content: center;
}

.layout-demo-box {
  width: 100%;
  max-width: 250px;
}

.layout-demo-title {
  margin: 0 0 10px 0;
  font-size: 13px;
  font-weight: bold;
  color: #0d6efd;
}

/* === 💡 CSS Gridによる中央揃え === */
.grid-parent {
  background-color: #ffffff;
  border: 1px solid #ced4da;
  border-radius: 4px;
  height: 150px;
  
  /* 💡 現代の最強ショートカット */
  display: grid;
  place-items: center;
}

.grid-child {
  background-color: #6f42c1;
  color: #fff;
  padding: 10px 20px;
  border-radius: 4px;
  font-weight: bold;
}

/* === 💡 Absoluteによる絶対配置 === */
.abs-parent {
  position: relative; /* 💡 基準点 */
  border-radius: 4px;
  overflow: hidden;
  height: 150px;
}

.abs-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.abs-child {
  /* 💡 被せて中央に配置 */
  position: absolute;
  top: 50%;
  left: 50%;
  /* 💡 自分自身のサイズの半分だけ引き戻す */
  transform: translate(-50%, -50%);
  
  background-color: #dc3545;
  color: #fff;
  padding: 10px 20px;
  border-radius: 30px;
  font-weight: bold;
  font-size: 16px;
  box-shadow: 0 4px 6px rgba(0,0,0,0.3);
}

/* =コード解説エリア(エディタ風)= */
.grid-abs-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}

Grid・positiontransformなどの使い方を詳しく知りたい人は以下から一読ください。

Flexboxを使わない古き良きline-heightハック

古いブラウザへの対応が必要な案件やHTMLメールのコーディングなど、Flexboxが使えない環境での対応を迫られることもあります。

そんな時にdivの中の要素を中央にする伝統的な解決策として使われてきたのが、line-height(行の高さ)を親要素のheightと同じ値に設定するハックです。

これを使えば、シンプルなボタンやバッジの文字を古いブラウザでも上下中央に揃えることができます。

line-heightハックを使うには、『絶対に改行されない1行だけのテキスト(ボタンや小さなバッジなど)』にのみ限定して使用することです。

ユーザーが入力した長いタイトルやスマホで改行される可能性が1%でもある要素には絶対に使用せず、FlexboxかGridに任せることです。

⭕️ line-heightハックは強力だが、「絶対に1行」の要素にしか使ってはいけない!

⭕️ 成功(1行のテキスト)

ボタンテキスト

❌ 罠(改行されて大崩壊)

長いテキストが入ってしまい、
改行された途端に箱を突き破る!
/* ⭕️ 1行のボタンなどには非常に有効なハック */
.button-success {
  height: 60px;
  line-height: 60px; /* 💡 heightと同じ値にすると中央になる */
  text-align: center;
}

/* ❌ 罠:改行される可能性がある場所で使うとレイアウトが壊滅する */
.box-fail {
  height: 100px;
  line-height: 100px; /* 🚨 2行になると合計200pxになってハミ出す! */
}
HTMLコード表示
<div class="lh-hack-wrapper">
  
  <p class="lh-hack-caption">⭕️ line-heightハックは強力だが、「絶対に1行」の要素にしか使ってはいけない!</p>

  <div class="lh-hack-demo-area">
    
    <div class="lh-demo-box">
      <p class="lh-demo-title">⭕️ 成功(1行のテキスト)</p>
      <div class="lh-success">
        ボタンテキスト
      </div>
    </div>

    <div class="lh-demo-box">
      <p class="lh-demo-title">❌ 罠(改行されて大崩壊)</p>
      <div class="lh-fail">
        長いテキストが入ってしまい、<br>改行された途端に箱を突き破る!
      </div>
    </div>

  </div>

  <div class="lh-hack-code-area">
    <span class="hl-comment">/* ⭕️ 1行のボタンなどには非常に有効なハック */</span><br>
    <span class="hl-blue">.button-success</span> {<br>
      <span class="hl-green">height:</span> <span class="hl-red">60px;</span><br>
      <span class="hl-green">line-height:</span> <span class="hl-red">60px;</span> <span class="hl-comment">/* 💡 heightと同じ値にすると中央になる */</span><br>
      <span class="hl-green">text-align:</span> <span class="hl-red">center;</span><br>
    }<br><br>

    <span class="hl-comment">/* ❌ 罠:改行される可能性がある場所で使うとレイアウトが壊滅する */</span><br>
    <span class="hl-blue">.box-fail</span> {<br>
      <span class="hl-green">height:</span> <span class="hl-red">100px;</span><br>
      <span class="hl-green">line-height:</span> <span class="hl-red">100px;</span> <span class="hl-comment">/* 🚨 2行になると合計200pxになってハミ出す! */</span><br>
    }
  </div>

</div>
CSSコード表示
.lh-hack-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.lh-hack-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.lh-hack-demo-area {
  display: flex;
  flex-wrap: wrap;
  gap: 30px;
  background-color: #e9ecef;
  padding: 30px 20px 80px 20px; /* 突き抜ける分の余白を下に確保 */
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
  justify-content: center;
}

.lh-demo-box {
  width: 100%;
  max-width: 280px;
}

.lh-demo-title {
  margin: 0 0 10px 0;
  font-size: 13px;
  font-weight: bold;
}

.lh-demo-box:first-child .lh-demo-title {
  color: #198754;
}

.lh-demo-box:last-child .lh-demo-title {
  color: #dc3545;
}

/* === ⭕️ 成功:1行だけのline-heightハック === */
.lh-success {
  background-color: #0d6efd;
  color: #fff;
  border-radius: 4px;
  font-weight: bold;
  
  /* 💡 heightとline-heightを同じにする */
  height: 60px;
  line-height: 60px;
  text-align: center;
}

/* === ❌ 罠:複数行による崩壊 === */
.lh-fail {
  background-color: #f8d7da;
  color: #842029;
  border: 2px solid #dc3545;
  border-radius: 4px;
  font-weight: bold;
  text-align: center;
  font-size: 14px;
  
  /* 🚨 2行になると行間が広がりすぎて突き抜ける */
  height: 100px;
  line-height: 100px; 
}

/* =コード解説エリア(エディタ風)= */
.lh-hack-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}

行間を調整するline-heightの使い方を詳しく知りたい人は「【CSS】行間を調整:line-heightの使い方と詰める・広げる方法」を一読ください。

リスト(ul/li)の縦揃え

箇条書きリスト(<ul>/<li>)は、記事の要点をまとめたり、ナビゲーションメニューを作ったりする際に欠かせないHTML要素です。

しかし、フォントサイズを大きくしたり、行間(line-height)を広げたりした途端、「箇条書きの黒い丸(・)が、テキストの高さとズレて上に浮いて見える…」という細かなデザインの破綻が起こります。

ここでは、初心者がつまずきやすいリストの罠とマーカーを1pxの狂いもなく揃える実装を解説します。

リスト(ul/li)の縦揃え
  • リストのマーカー(・)とテキストの縦位置を微調整する

リストのマーカー(・)とテキストの縦位置を微調整する

ブラウザが標準で用意しているリストのマーカー(list-style-type: disc;など)は、フォントの種類やサイズによって縦位置が微妙にズレるという厄介な仕様を持っています。

これを直そうとしてマーカーの調整方法を検索する制作者は後を絶ちません。

リストマーカーの縦位置を調整するには、ブラウザ標準のマーカーは制御不能なのでlist-style: none;で即座に削除し、疑似要素(::before)を使ってマーカーを自作することです。

li要素をdisplay: flex;にし、align-items: baseline;またはcenter;を使ってテキストとマーカーの高さを完璧に同期させることです。

⭕️ 標準マーカーは制御不能!「疑似要素+Flexbox」で自作して揃えろ!

❌ 罠(標準マーカー)

  • 行間(line-height)を広げると、
    標準マーカーはこのように上へ取り残され、
    CSSで縦位置を直せません。

⭕️ 成功(疑似要素+Flexbox)

  • 自作マーカーなら計算式を使えるため、
    どれだけ行間が広くても「1行目の中央」に
    完璧に合わせることが可能です。
/* ❌ 罠:行間を広げた途端、マーカーが上にズレる */
.list-fail li {
  line-height: 2.5; /* 行間を広く設定 */
  vertical-align: middle; /* 🚨 ブロック要素なので無視される!直せない! */
}

/* ⭕️ 標準を消し、liをFlex化してマーカーを自作! */
.list-success li {
  line-height: 2.5;
  display: flex; /* 💡 マーカーとテキストを横並びにする */
  align-items: flex-start; /* 💡 複数行対応のため上端基準 */
}

.list-success li::before {
  content: “”;
  display: block;
  width: 10px; /* 💡 マーカーの高さ */
  height: 10px;
  border-radius: 50%;
  background-color: #0f5132;
  /* 💡 (1行の高さ – マーカーの高さ) ÷ 2 で完璧な中央余白を出す */
  margin-top: calc((1em * 2.5 – 10px) / 2);
  margin-right: 12px;
  flex-shrink: 0; /* 💡 マーカーが潰れるのを防ぐ */
}
HTMLコード表示
<div class="ul-align-wrapper">
  
  <p class="ul-align-caption">⭕️ 標準マーカーは制御不能!「疑似要素+Flexbox」で自作して揃えろ!</p>

  <div class="ul-demo-area">
    
    <div class="ul-demo-box">
      <p class="ul-demo-title">❌ 罠(標準マーカー)</p>
      <ul class="list-fail">
        <li>行間(line-height)を広げると、<br>標準マーカーはこのように上へ取り残され、<br>CSSで縦位置を直せません。</li>
      </ul>
    </div>

    <div class="ul-demo-box">
      <p class="ul-demo-title">⭕️ 成功(疑似要素+Flexbox)</p>
      <ul class="list-success">
        <li>自作マーカーなら計算式を使えるため、<br>どれだけ行間が広くても「1行目の中央」に<br>完璧に合わせることが可能です。</li>
      </ul>
    </div>

  </div>

  <div class="ul-code-area">
    <span class="hl-comment">/* ❌ 罠:行間を広げた途端、マーカーが上にズレる */</span><br>
    <span class="hl-blue">.list-fail li</span> {<br>
      <span class="hl-green">line-height:</span> <span class="hl-red">2.5;</span> <span class="hl-comment">/* 行間を広く設定 */</span><br>
      <span class="hl-green">vertical-align:</span> <span class="hl-red">middle;</span> <span class="hl-comment">/* 🚨 ブロック要素なので無視される!直せない! */</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ 標準を消し、liをFlex化してマーカーを自作! */</span><br>
    <span class="hl-blue">.list-success li</span> {<br>
      <span class="hl-green">line-height:</span> <span class="hl-red">2.5;</span><br>
      <span class="hl-green">display:</span> <span class="hl-red">flex;</span> <span class="hl-comment">/* 💡 マーカーとテキストを横並びにする */</span><br>
      <span class="hl-green">align-items:</span> <span class="hl-red">flex-start;</span> <span class="hl-comment">/* 💡 複数行対応のため上端基準 */</span><br>
    }<br><br>

    <span class="hl-blue">.list-success li::before</span> {<br>
      <span class="hl-green">content:</span> <span class="hl-red">"";</span><br>
      <span class="hl-green">display:</span> <span class="hl-red">block;</span><br>
      <span class="hl-green">width:</span> <span class="hl-red">10px;</span> <span class="hl-comment">/* 💡 マーカーの高さ */</span><br>
      <span class="hl-green">height:</span> <span class="hl-red">10px;</span><br>
      <span class="hl-green">border-radius:</span> <span class="hl-red">50%;</span><br>
      <span class="hl-green">background-color:</span> <span class="hl-red">#0f5132;</span><br>
      <span class="hl-comment">/* 💡 (1行の高さ - マーカーの高さ) ÷ 2 で完璧な中央余白を出す */</span><br>
      <span class="hl-green">margin-top:</span> <span class="hl-red">calc((1em * 2.5 - 10px) / 2);</span><br>
      <span class="hl-green">margin-right:</span> <span class="hl-red">12px;</span><br>
      <span class="hl-green">flex-shrink:</span> <span class="hl-red">0;</span> <span class="hl-comment">/* 💡 マーカーが潰れるのを防ぐ */</span><br>
    }
  </div>

</div>
CSSコード表示
.ul-align-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.ul-align-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.ul-demo-area {
  display: flex;
  flex-direction: column;
  gap: 30px;
  background-color: #e9ecef;
  padding: 30px 20px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
  align-items: center;
}

.ul-demo-box {
  width: 100%;
  max-width: 400px;
  background-color: #ffffff;
  padding: 20px;
  border: 1px solid #ced4da;
  border-radius: 4px;
}

.ul-demo-title {
  margin: 0 0 15px 0;
  font-size: 13px;
  font-weight: bold;
  color: #dc3545;
  border-bottom: 1px dashed #ced4da;
  padding-bottom: 5px;
}

.ul-demo-box:last-child .ul-demo-title {
  color: #198754;
}

/* === ❌ 罠:標準マーカー === */
.list-fail {
  padding-left: 20px;
  margin: 0;
}

.list-fail li {
  color: #842029;
  font-size: 16px; /* 少し大きめに */
  
  /* 🚨 バグを誘発させる広い行間 */
  line-height: 2.5; 
  
  /* 🚨 効かない vertical-align */
  vertical-align: middle; 
  
  /* 視覚化のためのボーダー(1行目の高さが分かりやすいように) */
  border-left: 3px solid #f8d7da;
  padding-left: 10px;
}

/* === ⭕️ 成功:疑似要素+Flexbox+calc === */
.list-success {
  /* 💡 標準マーカーを消す */
  list-style: none;
  padding-left: 0;
  margin: 0;
}

.list-success li {
  color: #0f5132;
  font-size: 16px;
  
  /* 💡 同じく広い行間 */
  line-height: 2.5; 
  
  /* 💡 Flexboxでレイアウト */
  display: flex;
  align-items: flex-start;
  
  border-left: 3px solid #d1e7dd;
  padding-left: 10px;
}

.list-success li::before {
  /* 💡 マーカーを自作する */
  content: "";
  display: block;
  width: 10px;  /* 💡 今回は10pxの丸 */
  height: 10px;
  border-radius: 50%;
  background-color: #0f5132;
  
  /* 💡
     (フォントサイズ × 行間 - マーカーの高さ) ÷ 2 
     これで「1行目のど真ん中」の余白が算出される */
  margin-top: calc((1em * 2.5 - 10px) / 2); 
  
  margin-right: 12px;
  
  /* 💡 マーカーが潰れないように死守 */
  flex-shrink: 0; 
}

/* =コード解説エリア(エディタ風)= */
.ul-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}
.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }

リスト・疑似クラス::beforedisplay: flex;の使い方を詳しく知りたい人は以下から一読ください。

まとめ

分かりやすいようにまとめを記載します。

本記事のまとめ
  • 適用対象
    インライン要素(img,span,inline-block等)とテーブルセル(td,th)にのみ有効。
  • 無効な対象
    divpなどのブロックレベル要素には一切機能しない。
  • アイコンとテキストの揃え
    親要素に指定するのではなく、画像やアイコン(img,svg等)自身に直接指定する。
  • フォーム部品の揃え
    ボタンや入力欄の根本的な高さ合わせは、親要素へのFlexbox(align-items: center;)の使用を推奨。
  • テーブルでの指定
    セルの中の要素(p等)ではなくtdまたはthタグ自体に指定する。
  • divのセル化
    親にdisplay: table;、子にdisplay: table-cell;vertical-align: middle;をセットで指定する。
  • モダンな上下中央揃え
    Flexbox(align-items: center;)やGrid(place-items: center;)を使用する(※親要素に十分な高さの指定が必須)。
  • 絶対配置の中央揃え
    position: absolute;top: 50%;left: 50%;に加え、transform: translate(-50%, -50%);を指定する。
  • line-heightハック
    親の高さと同じ値を指定する手法は、絶対に改行されない「1行のテキスト」に限定して使用する。
  • リストマーカーの調整
    標準マーカー(・)は制御不可。
    疑似要素(::before)でマーカーを自作し、liをFlexbox化して縦位置を合わせる。

よくある質問(FAQ)

vertical-align: middle;を指定したのに縦中央揃えになりません。なぜですか?

最も多い原因は、指定した要素が<div><p>などの「ブロックレベル要素」であるためです。

vertical-alignは、インライン要素(<img><span>など)やテーブルセル(<td>)にしか効果がありません。

ブロック要素の中身を縦中央に揃えたい場合は、このプロパティではなく親要素にdisplay: flex;align-items: center;を指定してください。

画像の横にあるテキストの縦位置が上にズレてしまいます。どう揃えればいいですか?

親要素(囲んでいるdivなど)に指定しているのが原因かもしれません。

テキストと画像を揃えたい場合は、親ではなく画像やアイコン(<img><svg>)自身に対して直接vertical-align: middle;を指定してください。

これにより、横にあるテキストの中央付近と画像の縦の中央がピタッと揃います。

divの中のテキストを「上下左右の中央」に配置する一番簡単な方法は何ですか?

現代のWeb制作ではFlexboxを使うのが主流かつ最も簡単です。

テキストを囲んでいる親の<div>に対して、display: flex; justify-content: center; align-items: center;の3つを指定してください。

※注意点として、親要素にheight: 100px;などの「動くための高さ」を忘れずに指定してください。

テーブル(表)のセルの中で、テキストを「上揃え」にするにはどうすればいいですか?

対象のセルである<td>または<th>タグに対して、直接vertical-align: top;を指定してください。

テーブルセルの場合はインライン要素と同様にこのプロパティが有効に働き、セル内の余白を使って文字が上端に綺麗に揃えられます。

セルの中の<p>タグ等に指定しても効かないので注意してください。

baselineとmiddleの違いは何ですか?

基準とする線が異なります。

baseline(初期値)は、要素の足元をテキストの「ベースライン(英字のaやxが乗っている見えない線)」に揃えます。

一方middleは、要素の縦方向のど真ん中を、親要素のベースラインより少し上(小文字のxの高さの半分)に揃えます。

アイコンを文字の中央に置きたい時はmiddle、大小異なる文字の足元を揃えたい時はbaselinebottomを使い分けます。

CONTACT

サイト制作でお困りの人はお気軽にご連絡ください。
どんなお悩み事も丁寧に返信させて頂きます。

WordPress移行
Webサイトを公開しよう!

「どのサーバーを選べばいいか分からない…」そんな悩みを解決!
WordPressデビューに最適なサーバーを徹底比較しました。

この記事を書いた人

sugiのアバター sugi Site operator

【経歴】玉川大学工学部卒業→新卒SIer企業入社→2年半後に独立→プログラミングスクール運営/受託案件→フリーランスエンジニア&SEOコンサル→Python特化のコンテンツサイトJob Code&UIコピペサイトCode Stock運営中

目次