【CSS】tableのwidthが効かない原因と対処法|7パターンを徹底解説

【CSS】tableのwidthが効かない原因と対処法|7パターンを徹底解説 HTML/CSS

HTMLテーブルの<th><td>にCSSでwidthを指定しても、意図した幅にならないことがあります。

これはテーブル特有の幅計算アルゴリズムが原因です。

この記事では、幅が効かない原因を7パターンに分類し、それぞれの対処法をコード付きで解説します。

この記事で分かること
  • table-layout: auto と fixed の幅計算の違い
  • widthが効かない7つの原因と対処法
  • colgroup/col による列幅指定
  • 長いテキストやURLが列幅を押し広げる問題の解決
  • border-collapse と幅計算の関係
  • レスポンシブテーブルでの幅制御
スポンサーリンク

前提知識:テーブルの幅計算アルゴリズム

テーブルの列幅は通常のブロック要素とは異なるアルゴリズムで決定されます。まずこの仕組みを理解することが、問題解決の第一歩です。

table-layout: auto(デフォルト)

デフォルトのautoでは、ブラウザがすべてのセルの内容を読み取ってから列幅を決定します。

table {
    table-layout: auto; /* デフォルト値 */
    width: 100%;
}

この場合、セルの内容が指定した幅より大きければ、widthは無視されます。ブラウザは「すべての列が見える状態」を優先するため、指定した幅は「希望値」として扱われます。

table-layout: fixed

fixedでは、テーブルの1行目の幅指定だけを見て列幅を決定します。

table {
    table-layout: fixed;
    width: 100%; /* 必須:tableの幅も指定する */
}

内容に関係なく指定した幅が適用されるため、widthを確実に効かせたい場合はこちらを使います。

比較項目 auto(デフォルト) fixed
列幅の決定基準 全セルの内容を考慮 1行目の幅指定のみ
widthの扱い 希望値(内容が優先) 確定値(内容を無視)
レンダリング速度 遅い(全行を解析) 速い(1行目だけ解析)
はみ出し 列が広がって対応 overflow で制御が必要
使い分け 内容量が不定のとき 列幅を厳密に制御したいとき
重要:table-layout: fixedを使う場合、table自体にもwidth100%や固定値)を指定してください。width: autoのままだとfixedが正しく機能しません。

table-layout プロパティの詳細な使い分けは「【CSS】table-layout: fixedとautoの違いと使いどころ」で解説しています。

原因①:table-layoutがautoのまま

最も多い原因です。デフォルトのautoではセルの内容量に応じて列幅が自動調整されるため、width指定が無視されます。

問題のコード

/* widthが効かない */
table {
    width: 100%;
    /* table-layout: auto; がデフォルト */
}
th:first-child {
    width: 200px; /* 内容が多いと無視される */
}

対処法

/* widthが効く */
table {
    width: 100%;
    table-layout: fixed;
}
th:first-child {
    width: 200px; /* 確実に200pxになる */
}

原因②:長いテキストやURLがセルを押し広げる

table-layout: fixedにしても、セル内のテキストがはみ出して見える場合があります。列幅自体は指定通りですが、内容がオーバーフローしています。

対処法A:折り返しを許可する

table {
    table-layout: fixed;
    width: 100%;
}
td {
    word-break: break-all;  /* 任意の位置で改行 */
}

対処法B:はみ出しを隠す(省略表示)

table {
    table-layout: fixed;
    width: 100%;
}
td {
    overflow: hidden;
    text-overflow: ellipsis;  /* 「...」で省略 */
    white-space: nowrap;
}
プロパティ 効果 適した場面
word-break: break-all 任意の文字位置で改行 長いURLやコードを表示するとき
overflow-wrap: break-word 単語の途中で改行(単語単位を優先) 英文テキストを自然に折り返したいとき
overflow: hidden + text-overflow: ellipsis はみ出しを省略記号で表示 一覧表で見た目を揃えたいとき

text-overflow の詳細は「【CSS】text-overflow: ellipsisが効かない原因と解決方法」で解説しています。

word-break と overflow-wrap の違い

/* word-break: break-all は文字単位で強制改行 */
td.url-cell {
    word-break: break-all;
}

/* overflow-wrap: break-word は単語の切れ目を優先し、
   収まらない場合だけ単語途中で改行 */
td.text-cell {
    overflow-wrap: break-word;
}

日本語テキストはデフォルトで文字単位の折り返しが有効なので、問題になるのは主に英語の長い単語やURLです。

原因③:white-space: nowrap が設定されている

セルにwhite-space: nowrapが指定されていると、テキストの折り返しが禁止されます。内容が一行に収まらない場合、セルが指定幅を超えて広がります。

/* 問題:nowrapで幅が効かなくなる */
td {
    white-space: nowrap;
    width: 150px; /* 内容が150pxを超えると無視される */
}

対処法

/* nowrapを解除する */
td {
    white-space: normal; /* デフォルト値に戻す */
    width: 150px;
}

/* nowrapを維持しつつ幅を制限したい場合 */
td {
    white-space: nowrap;
    width: 150px;
    max-width: 150px;
    overflow: hidden;
    text-overflow: ellipsis;
}

原因④:colgroup / col の幅指定が競合している

HTMLの<colgroup>/<col>要素で列幅を指定している場合、CSSのwidthと競合することがあります。

<table>
  <colgroup>
    <col style="width: 100px;">  <!-- この指定が優先される場合がある -->
    <col style="width: 200px;">
    <col>
  </colgroup>
  <thead>
    <tr>
      <th>名前</th>
      <th>メール</th>
      <th>備考</th>
    </tr>
  </thead>
  <!-- ... -->
</table>

対処法

<col>のstyle属性とCSSの指定を統一します。片方に寄せるのが安全です。

/* CSSで統一する場合(推奨) */
table {
    table-layout: fixed;
    width: 100%;
}
col:nth-child(1) { width: 100px; }
col:nth-child(2) { width: 200px; }
/* 3列目は残りの幅が自動的に割り当てられる */

ポイント:table-layout: fixedでは、<col>の幅 → 1行目の<th>/<td>の幅の順で参照されます。<col>に幅が指定されていればそちらが優先されます。

原因⑤:セルの結合(colspan/rowspan)の影響

colspanで結合したセルがある行では、列幅の計算が変わります。

<table>
  <tr>
    <th colspan="2">名前(姓・名)</th>  <!-- 2列分を結合 -->
    <th>メール</th>
  </tr>
  <tr>
    <td style="width: 80px;">山田</td>
    <td style="width: 80px;">太郎</td>
    <td>taro@example.com</td>
  </tr>
</table>

table-layout: fixed1行目の幅指定を基準にするため、1行目がcolspanで結合されていると個別の列幅が正しく設定されません。

対処法

<colgroup>で列幅を明示するか、結合のない行を1行目にします。

<table>
  <colgroup>
    <col style="width: 80px;">
    <col style="width: 80px;">
    <col>
  </colgroup>
  <tr>
    <th colspan="2">名前(姓・名)</th>
    <th>メール</th>
  </tr>
  <!-- ... -->
</table>

セル結合の詳しい書き方は「【HTML】テーブルのセルを結合する方法」をご覧ください。

原因⑥:border-collapse と padding/border の影響

テーブルのデフォルトのbox-sizingborder-boxです。しかしborder-collapseの設定によってボーダーの計算方法が変わり、意図した幅にならないことがあります。

プロパティ 効果 幅への影響
border-collapse: separate(デフォルト) 各セルが独立したボーダーを持つ border-spacingの分だけ余分に幅を消費
border-collapse: collapse 隣接セルのボーダーを共有 ボーダー幅が半分ずつ分配される
/* border-spacing が幅に影響している場合 */
table {
    border-collapse: separate;
    border-spacing: 10px; /* セル間に10pxの隙間 × 列数分 */
}

/* 対処法:collapse にして余分な隙間を排除 */
table {
    border-collapse: collapse;
    /* border-spacing は無効になる */
}

計算例:4列のテーブルでborder-spacing: 10pxの場合、セル間の隙間だけで10px × 5 = 50px(列数+1箇所)が余分に消費されます。これが列幅のズレの原因になります。

原因⑦:width / min-width / max-width の使い分けミス

テーブルセルに対するwidthmin-widthmax-widthの挙動は、通常のブロック要素とは異なります。

プロパティ table-layout: auto table-layout: fixed
width 希望値(内容が優先) 確定値
min-width 尊重される widthが優先(効きにくい)
max-width 効かないことが多い 効かないことが多い
/* auto の場合:min-width で最低幅を保証 */
table {
    table-layout: auto;
    width: 100%;
}
td:first-child {
    min-width: 120px; /* 内容が少なくても120px以上を保証 */
}

/* fixed の場合:width で確定幅を指定 */
table {
    table-layout: fixed;
    width: 100%;
}
td:first-child {
    width: 120px; /* 正確に120pxになる */
}
注意:テーブルセルにmax-widthは基本的に効きません。これはCSSの仕様上、テーブルのレイアウトアルゴリズムがmax-widthを考慮しないためです。幅の上限を設けたい場合はtable-layout: fixed+widthで制御してください。

実践パターン:よくあるレイアウトの実装

パターン①:1列目を固定幅、残りを均等割り

table {
    table-layout: fixed;
    width: 100%;
}
th:first-child,
td:first-child {
    width: 200px;
}
/* 残りの列は自動的に均等割りされる */

パターン②:列ごとに割合を指定

table {
    table-layout: fixed;
    width: 100%;
}
<table>
  <colgroup>
    <col style="width: 20%;">
    <col style="width: 50%;">
    <col style="width: 30%;">
  </colgroup>
  <!-- ... -->
</table>

パターン③:レスポンシブ対応(スマホで横スクロール)

/* テーブルをラッパーで囲む */
.table-wrapper {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}
.table-wrapper table {
    min-width: 600px; /* 最低幅を保証 */
    width: 100%;
    table-layout: fixed;
}
<div class="table-wrapper">
  <table>
    <!-- ... -->
  </table>
</div>
注意:overflow<table>に直接指定しても効きません。必ず外側の<div>に指定してください。

テーブルの横スクロールについて詳しくは「【CSS】テーブルを横スクロールさせる方法」、スマホ対応については「【CSS】スマホのみテーブルを横スクロール可能にする方法」をご覧ください。

トラブルシューティング早見表

widthが効かない場合に、原因を素早く特定するためのフローチャートです。

症状 最も可能性が高い原因 対処法
列幅がすべて均等にならない table-layout: auto のまま table-layout: fixed + width: 100%
指定した幅より広くなる セルの内容が長い word-break: break-all または overflow: hidden
指定した幅より広くなる(nowrap) white-space: nowrap white-space: normal に変更
列幅がわずかにズレる border-spacing の影響 border-collapse: collapse
colspanのある行で幅がおかしい fixed が1行目を基準にする <colgroup>で列幅を定義
max-widthが効かない テーブルの仕様上の制限 table-layout: fixed + width で代替
スマホで列が潰れる テーブル幅がビューポートを超過 ラッパーdivにoverflow-x: auto
pxと%が混在して計算がおかしい 単位の混在 一つの単位(%推奨)に統一

よくある質問(FAQ)

Q. CSSでテーブルのwidth: 100%が効かない原因は?
A. tableのデフォルトはcontent幅に合わせます。width: 100%を設定しても親要素の幅を超えないよう調整されます。table-layout: fixedを合わせると列幅の制御が改善します。
Q. テーブルのセル幅が思い通りにならない場合は?
A. table-layout: fixedを設定し、th/tdの幅をwidthで指定します。colgroup/col要素でも列幅を管理できます。min-width・max-widthも活用してください。
Q. テーブルが親コンテナからはみ出る場合の対処は?
A. テーブルをdivでラップしてoverflow-x: autoを設定します。またはwidth: 100%; max-width: 100%; display: block; overflow-x: auto;をtableに設定する方法もあります。

まとめ

テーブルのwidthが効かない原因と対処法を整理します。

原因 対処法 キーとなるプロパティ
table-layout: autoのまま fixedに変更 + テーブル幅を指定 table-layout: fixed
長いテキスト/URLがはみ出す 折り返しまたは省略表示 word-break / overflow
white-space: nowrap 解除またはoverflow制御 white-space: normal
colgroup/colの競合 CSSに統一 col:nth-child()
colspan が1行目にある colgroupで列幅を定義 <colgroup>
border-spacing の影響 collapseに変更 border-collapse: collapse
width/min-width/max-widthの誤用 layoutモードに合った指定 auto→min-width / fixed→width

最も確実な方法はtable-layout: fixedwidth: 100%をテーブルに指定し、各列の幅を<colgroup>または1行目の<th>で定義することです。

関連記事