th、tdにFlexboxを使うとwidth指定がきかない

この記事は最終更新から4年以上が経過しています。情報が古くなっている可能性があります。

tableタグにFlexboxを適用したところ、Edgeではセル幅がちゃんと確保できず、内容に応じて狭くなってしまう事態が発生。
table-layout:fixedでは対応できなかったので、この事象の原因と対処法をまとめました!

事象

外部システムから発行したHTMLコードを改変せずそのまま使わなきゃいけない箇所があり、以下のHTMLコードを

  • はじめの4つの見出し&コンテンツ→横幅50%で横並び
  • 後ろ2つの見出し&コンテンツ→横幅100%で縦並び

このように並ばせようとしました。

やりたいレイアウト

適用コード

<table><tbody>
 <tr><th>th1</th><td>td1</td></tr>
 <tr><th>th2</th><td>td2</td></tr>
 <tr><th>th3</th><td>td3</td></tr>
 <tr><th>th4</th><td>td4</td></tr>
 <tr><th>th5</th><td>td5</td></tr>
 <tr><th>th6</th><td>td6</td></tr>
</tbody></table>
tbody { display:flex; flex-wrap:wrap; width: 100%; }
tr { width: 100%; } 
tr:nth-child(1),tr:nth-child(2),tr:nth-child(3),tr:nth-child(4) { width: 50%; }
th { width:30%; }
td { width:30%; }

上記を各ブラウザで表示確認したところ、

  • (Mac)safari、firefox→問題なし
  • (Win)Chrome→問題なし
  • (Win)Edge/IE→崩れが発生!

どうやらEdge/IEだけth、tdで指定したwidthがちゃんと効いていない模様。
trのwidth幅は指定通り確保されていましたが、th、tdだけ内容量によって横幅が変わってしまいました。

調べてみると「tableタグでwidth幅が確保できない時はtable-layout:fixedで解決する」という事例が多くありましたが、こちらを試してみても解消せず。

原因

テストコードで各ブラウザの表示を検証してみました。

テストコード

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>テスト</title>
</head>
<body>
<style>
 .wrap1,
 .wrap2 {display: flex;width: 500px;}
 .wrap1 .a,
 .wrap1 .b {display: block;}
 .wrap2 .a,
 .wrap2 .b {display: table-cell;}
 .a {width: 30%;background: #ccc;}
 .b {width: 70%;background: #aaa;}
</style>
<h1>テスト</h1>
<h2>普通にブロック指定</h2>
<div class="wrap1">
 <div class="a">a1a1a1a1a1a1a1a1</div>
 <div class="b">b1b1b1b1b1b1b1b1</div>
</div>
<h2>子要素をtable-cell指定</h2>
<div class="wrap2">
 <div class="a">a2a2a2a2a2a2a2a2</div>
 <div class="b">b2b2b2b2b2b2b2b2</div>
</div>
</body></html>

子要素divを2つ持つ、親要素divのセットを2セット用意。
この事象がtableタグならではかどうかの切り分けをするため、後者のdivの子要素には「display: table-cell;」を指定してみました。

結果


(Mac)safari、chrome、firefox、(Win)chrome→問題なし


(Win)Edge→横幅とれず!

つまり、flex-itemがtable-cellの場合、Edge/IEではwidth指定がきかなくなるということのようです。

解決

この崩れが起きた場合は、display: table-cellになっている子要素をdisplay:blockにすることで解消することができました。

基本的に横並びにしたい!という時にフレックスボックスとテーブルレイアウトを同時に使うことはないと思います。
なので、特にtableタグをflexでこねくり回したいという時にはご注意ください。