CSSで要素を横並びにする方法は、float・inline-block・table-cell・flexbox・gridと複数あります。「とりあえずflexboxで」という記事は多いですが、flexboxにもデメリットはありますし、用途によっては他の手法の方が適している場合もあります。この記事では2025年現在の視点から、各手法の仕組みとメリット・デメリットを解説します。


    基本となるHTML

    この記事では以下のHTMLを使って、CSSだけで横並びを実装していきます。

    <ul class="wrapper">
      <li class="item">item1</li>
      <li class="item">item2</li>
      <li class="item">item3</li>
    </ul>
    

    1. float

    floatは「テキストの横に画像を横並びにする」ための機能です。

    .item {
      float: left;
    }
    
    /* float した要素は親の高さに含まれないため clearfix が必要 */
    .wrapper::after {
      content: "";
      display: block;
      clear: both;
    }
    

    メリット

    テキストが回り込むのは float だけの特性です。「画像+テキストの横並びで、テキストが画像の下まで続く」レイアウトは float でなければ実現できません。

    ┌──────────┐ テキストテキスト
    │          │ テキストテキスト
    │  画像    │ テキストテキスト
    │          │
    └──────────┘
    テキストが画像の下まで続く
    

    デメリット

    float した要素は親要素の高さに含まれません。clearfix(::afterclear: both)か、親要素に display: flow-root を指定しないと、親要素の高さが0になります。

    また、要素の幅を明示的に指定しないと意図しないレイアウト崩れが起きやすいです。

    使いどころ

    画像+テキストの横並びにするレイアウト専用と考えると良いでしょう。。


    2. inline-block

    .wrapper {
      font-size: 0; /* 隙間対策 */
    }
    
    .item {
      display: inline-block;
      font-size: 16px; /* 子要素でリセット */
      vertical-align: top;
    }
    

    メリット

    vertical-align で縦方向の揃えを制御できます。子要素の高さがバラバラでも、vertical-align: top で上揃え、vertical-align: middle で中央揃えが可能です。

    デメリット

    HTML の改行が隙間(約4px)になります。HTMLを1行にする、コメントアウトで改行を消す、親要素に font-size: 0 を指定するなどの対処が必要で、コードが読みにくくなります。

    また、幅の制御が flex や grid より直感的ではなく、width: 33.33% のような指定が必要です。

    使いどころ

    2025年現在ではほぼ flex に代替されています。vertical-align が必要な場面でも flex の align-items で同等のことができるため、積極的に使う理由はほとんどありません。


    3. table / table-cell

    HTMLの <table> ではなく、CSSで display: table / display: table-cell を使う方法です。

    .wrapper {
      display: table;
      width: 100%;
      table-layout: fixed; /* 均等幅にするために必要 */
    }
    
    .item {
      display: table-cell;
      vertical-align: middle;
    }
    

    メリット

    table-layout: fixed を指定すると、子要素の数に応じて自動的に均等幅になります。子要素それぞれに幅を指定しなくても等分割されるのはこの手法だけの特徴です。

    また、vertical-align で上下中央揃えも簡単にできます。

    デメリット

    margin が効きませんtable-cell 間の余白は border-spacing で指定しますが、この値は全セルに均等に適用されます。

    さらに border-spacingコンテナの外側(左端・右端)にも余白が生まれるため、コンテナを margin: 0 -余白px でずらす対処が必要になります。

    /* border-spacing の欠点 */
    .wrapper {
      display: table;
      border-spacing: 20px 0; /* 列間の余白 */
      /* ↑ 左端と右端にも20pxの余白ができてしまう */
    }
    
    /* 対処: 親要素をネガティブマージンでずらす */
    .wrapper {
      overflow: hidden;
    }
    .wrapper {
      display: table;
      border-spacing: 20px 0;
      margin: 0 -20px; /* border-spacing と同じ値で相殺 */
    }
    

    使いどころ

    「子要素の幅を書かずに自動で均等分割したい」という限定的な場面。ただし余白の制御が煩雑なため、現代では flex や grid で代替するほうがシンプルです。


    4. flexbox

    現在最も広く使われる手法です。

    .wrapper {
      display: flex;
    }
    

    これだけで子要素が横並びになります(flex-direction のデフォルトが row のため)。

    基本的な幅の指定

    /* 均等幅(3分割) */
    .item {
      flex: 1; /* flex-grow:1 flex-shrink:1 flex-basis:0 の略 */
    }
    
    /* 幅をパーセントで指定 */
    .item {
      width: 33.33%;
    }
    

    flex-grow と flex-shrink の仕組み

    flex-grow:余白スペースをどの比率で子要素に分配するか。

    .item-a { flex-grow: 1; } /* 余白の1/3を受け取る */
    .item-b { flex-grow: 2; } /* 余白の2/3を受け取る */
    

    ここで重要な落とし穴flex-grow は「余白の分配比率」であって「要素の幅の比率」ではありません。

    /* 意図: item-a を25%、item-b を75% にしたい */
    .item-a { flex-grow: 1; }
    .item-b { flex-grow: 3; }
    /* → コンテンツ幅が同じなら意図通りになるが、コンテンツ幅が違うと崩れる */
    
    /* 確実に 25% / 75% にする方法 */
    .item-a { flex: 0 0 25%; }   /* grow:0 shrink:0 basis:25% */
    .item-b { flex: 1 1 auto; }  /* 残りを埋める */
    
    /* またはシンプルに width で指定 */
    .item-a { width: 25%; flex-shrink: 0; }
    .item-b { flex: 1; }
    

    flex-shrink:コンテナが縮んだとき、どの比率で子要素を縮めるか(デフォルト: 1)。

    .item-a { flex-shrink: 0; } /* 縮まない(幅が固定) */
    .item-b { flex-shrink: 1; } /* コンテナに合わせて縮む */
    

    flex-grow の落とし穴:fx-grow パターンでの幅指定

    flex-grow: 1width を組み合わせると直感と異なる挙動になります。

    /* ❌ 意図と異なる例 */
    .item-a { width: 25%; flex-grow: 1; }  /* 25% + 余白の1/2 */
    .item-b { width: 0;   flex-grow: 1; }  /* 0   + 余白の1/2 */
    /* → item-a は想定より大きくなる */
    
    /* ✅ 正しい指定 */
    .item-a { width: 25%; flex-shrink: 0; } /* 25% 固定 */
    .item-b { flex: 1; }                    /* 残り全部 */
    

    メリット

    justify-content で子要素全体の水平位置、align-items で垂直位置を制御でき、order で DOM 順序を変えずに表示順を変えられます。行ごとの幅指定が柔軟(nth-of-type で個別指定も可能)です。

    デメリット

    そのまま display: flex しただけでは等間隔になりませんjustify-content: space-betweengap の指定が必要です。また、flex-grow の動作がコンテンツ幅依存で直感的でない場面があります。

    使いどころ

    「行ごとに異なる幅を指定したい」「要素数が増減する」「SP と PC で異なる配置にしたい(order で制御)」場面で特に強みを発揮します。


    5. CSS Grid

    grid はflex の「1次元(横 or 縦)」に対して「2次元(横と縦)」を同時に制御できます。

    grid-auto-flow: column(子要素クラス不要で等間隔横並び)

    .wrapper {
      display: grid;
      grid-auto-flow: column;  /* 横方向に自動配置 */
      grid-auto-columns: 1fr;  /* 等幅 */
      gap: 20px;
    }
    

    子要素に何も指定しなくても、要素数に関わらず自動で等分割されます。

    <!-- 2要素でも3要素でも等分割 -->
    <ul class="wrapper">
      <li>item1</li>
      <li>item2</li>
      <li>item3</li>  <!-- 追加してもレイアウト崩れなし -->
    </ul>
    

    クラス名の注意grid-auto-flow: column で「横並び」になります(column = 列方向に積む)。値名と見た目が逆に感じますが、「新しい要素を列(column)に積んでいく = 横に伸びる」という理解です。

    非均等幅の指定

    /* 左25% / 右75% */
    .wrapper {
      display: grid;
      grid-auto-flow: column;
      grid-template-columns: 25% 1fr; /* auto-columns より template-columns が優先される */
      gap: 20px;
    }
    

    grid-template-columns(明示的な列定義)

    要素数が固定の場合は grid-template-columns で列を明示定義します。

    /* 3列均等 */
    .wrapper {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 20px;
    }
    
    /* 非均等:1列目固定 + 残り均等 */
    .wrapper {
      display: grid;
      grid-template-columns: 200px 1fr 1fr;
      gap: 20px;
    }
    

    メリット

    grid-auto-flow: column + grid-auto-columns: 1fr の組み合わせで、子要素に何も書かなくても等分割の横並びになるのが最大の強みです。gap で要素間の余白を指定でき、外側には余白ができません(flexbox の space-between と異なる)。

    デメリット

    「上段と下段で異なる幅を指定する」ことができません。

    ┌───────────────────────┬───────┐
    │                       │       │  ← 1行目: 2:1
    │         item1         │ item2 │
    ├────────┬──────┬───────┘       │
    │ item3  │item4 │ item5  ← 2行目: 3等分にしたい
    └────────┴──────┴───────────────┘
    

    grid は列幅が全行で共通のため、このような「行ごとに幅が違う」レイアウトは flex(nth-of-type で個別指定)のほうが柔軟です。

    使いどころ

    「要素数が変わっても等分割で横並びを維持したい」「セルが複数行にまたがる(grid-row: span 2)」場面で特に強みがあります。全行で同じカラム幅でよければ grid が最もシンプルです。


    各手法の比較まとめ

    手法 等間隔(追加設定なし) 子要素クラス不要 行ごとに異なる幅 テキスト回り込み margin が効く
    float
    inline-block
    table-cell
    flexbox
    grid(auto-flow) ✅(gap)

    使い分けの指針

    画像+テキストの横並び → float

    .image { float: left; width: 40%; }
    .text { overflow: hidden; } /* flow-root でも可 */
    

    行ごとに幅が違う / SP と PC で配置を変える → flexbox

    .wrapper { display: flex; flex-wrap: wrap; gap: 20px; }
    .item:nth-of-type(1) { width: 60%; }
    .item:nth-of-type(2) { width: calc(40% - 20px); }
    

    子要素数が変わっても等分割横並びを維持 → grid

    .wrapper {
      display: grid;
      grid-auto-flow: column;
      grid-auto-columns: 1fr;
      gap: 20px;
    }
    

    幅が不均等 / 非均等幅を grid で指定

    .wrapper {
      display: grid;
      grid-auto-flow: column;
      grid-template-columns: 25% 1fr; /* 左25%固定 + 右残り */
      gap: 20px;
    }
    

    まとめ

    「とりあえず flex」は間違いではありませんが、「flex で書いたら等間隔にならなかった」というのはよくある失敗です。

    2025年現在のおすすめは、「子要素数が固定 or 変動・等分割」なら grid、「行ごとに幅が違う・SP/PC で配置を変える」なら flexbox、「画像+テキストの横並び」なら float を使い分けることです。inline-block と table-cell は現代では積極的に選ぶ理由がほぼなくなりましたが、仕組みを知っていると既存コードの読解やデバッグに役立ちます。