33
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

お題は不問!Qiita Engineer Festa 2023で記事投稿!

【CSS Tips】tableタグを使わずにテーブルレイアウトを作る

Last updated at Posted at 2023-06-15

はじめに

この記事を書いた時点では、Subgridのサポートされているブラウザが限られていましたが、2024年3月現在では主要なブラウザでサポートがされています。

そのため、方法③ Subgridを使うがおすすめの方法です。

"subgrid" | Can I use... Support tables for HTML5, CSS3, etc

これは何

Webを作っている際に、「見た目はテーブルレイアウトを使って組むと楽そう」だけど、「実際にはテーブルではない」要素を作りたいことがちょこちょことあります。

以下のようなUIです。

3つの要素が横並びになっている行が、3つ並んでいる。それぞれの行の同じ順番の要素は、開始位置が揃っている

こうした要素をtable要素を使ってデザインしてしまうと、支援技術を使用しているユーザーが意味を適切に理解できなかったり、テーブルを読み取る操作が複雑なために内容を読み取れないことがあります。

テーブル以外でも、基本的に使用するタグは「実現したい見た目」ではなく、「要素が持つ意味」に応じて適したものを使いましょう。
文字サイズを変えたいからheadingを使ったりボタンをdivで作ったりすると、支援技術などで誤った伝わり方をしたり、適切に操作できないことがあります。

こうした時にtable要素を使わずにマークアップ・スタイリングする方法をまとめてみました。

方法① Flexboxを使う

image.png

手順

  1. 各行をdivなどで囲い、display: flex;を指定する
  2. 各列にwidthflexの値を指定し、横幅が揃うようにする

:thumbsup: メリット

  • 1行ごとにマークアップできる(情報構造をマークアップで表現できる)

:thumbsdown: デメリット

  • 要素のサイズに応じて各列の横幅を決めることができない
  • 各列の位置を揃えるには、要素の内容をに応じてwidthを指定しておくか、要素の位置を取得して計算する必要がある

個人的な所感

内容に応じて柔軟に列の幅を変える必要がないのであれば、この方法で問題ないと思います。
ただしwidthで固定幅を指定する際は、要素が変わったときに表示崩れなどを起こさないよう注意が必要です。

マークアップとスタイリング

<section>
  <div class="flex-row">
    <div class="flex-item">1</div>
    <div class="flex-item">2</div>
    <div class="flex-item">3</div>
  </div>
  <div class="flex-row">
    <div class="flex-item">4</div>
    <div class="flex-item">5</div>
    <div class="flex-item">6</div>
  </div>
</section>
.flex-row {
  display: flex;
  gap: 4px;
}

.flex-row+.flex-row {
  margin-top: 4px;
}

.flex-item {
  background: #eee;
  padding: 4px;
}

.flex-item:nth-child(1) {
  width: 40px;
}

.flex-item:nth-child(2) {
  flex: 2;
}

.flex-item:nth-child(3) {
  flex: 1;
}

:arrow_down_small: サンプル

See the Pen flex by kabechiyo_shunkaaizawa (@kabechiyo) on CodePen.

方法② gridを使う

手順

  1. 要素全体をdivなどで囲い、display: grid;grid-template-columns: repeat([列の数], auto);を指定する

:thumbsup: メリット

  • 要素のサイズに応じて各列の横幅を決めることができる

:thumbsdown: デメリット

  • 1行ごとにマークアップできない(情報構造をマークアップで表現できない)

個人的な所感

1行ごとに情報の区切りがないのであれば、この方法がシンプルに実装できます。
1行ごとにマークアップできないため、1行ごとに情報の区切りがある場合は方法①を使う方が良いと思います。

マークアップとスタイリング

<div class="grid-container">
  <div class="grid-item">1</div>
  <div class="grid-item">2</div>
  <div class="grid-item">3</div>
  <div class="grid-item">4</div>
  <div class="grid-item">5</div>
  <div class="grid-item">6</div>
</div>
.grid-container {
  display: grid;
  gap: 4px;
  grid-template-columns: repeat(3, auto);
}

.grid-item {
  background: #eee;
  padding: 4px;
}

:arrow_down_small: サンプル

See the Pen grid by kabechiyo_shunkaaizawa (@kabechiyo) on CodePen.

方法②-2 griddisplay: contentsを使う

コメント@juner さんにdisplay: contentsを使う方法を教えていただいたため、追記しました

手順

  1. 要素全体をdivなどで囲い、display: grid;grid-template-columns: repeat([列の数], auto);を指定する
  2. 各行をdivなどで囲い、display: contents;を指定する

:thumbsup: メリット

  • 要素のサイズに応じて各列の横幅を決めることができる

:thumbsdown: デメリット

個人的な所感

後述のSubgridと近い挙動を実現でき、使い勝手が良いです
行をwrapするタグのロールが失われてしまうので、意味を持たせる場合は方法①を使う方が良いと思います。
この仕様自体はバグらしいので、修正を待ちたいです。

マークアップとスタイリング

<div class="grid-container">
  <div class="subgrid-container">
    <div class="grid-item">1</div>
    <div class="grid-item">2</div>
    <div class="grid-item">3</div>
  </div>
  <div class="subgrid-container">
    <div class="grid-item">4</div>
    <div class="grid-item">5</div>
    <div class="grid-item">6</div>
  </div>
</div>

.grid-container {
  display: grid;
  gap: 4px;
  grid-template-columns: repeat(3, auto);
}

.subgrid-container {
  display: contents;
}

.grid-item {
  background: #eee;
  padding: 4px;
}

:arrow_down_small: サンプル

See the Pen Untitled by kabechiyo_shunkaaizawa (@kabechiyo) on CodePen.

方法③ Subgridを使う

この方法は現在サポートされているブラウザが限られており、実用的ではありません。
2024年3月現在、主要ブラウザでサポートがされており使うことができるようになりました :tada:
"subgrid" | Can I use... Support tables for HTML5, CSS3, etc

手順

  1. 要素全体をdivなどで囲い、display: grid;grid-template-columns: repeat([列の数], auto);を指定する
  2. 各行にdisplay: grid;, grid-template-columns: subgrid;, grid-column: span [列の数];を指定する

:thumbsup: メリット

  • 1行ごとにマークアップできる(情報構造をマークアップで表現できる)
  • 要素のサイズに応じて各列の横幅を決めることができる

:thumbsdown: デメリット

  • 最初に書いた通り、サポートされているブラウザが限られているため実用的でない

個人的な所感

サポートブラウザが限られている以外は、方法①・②よりも使い勝手が良いので、早く使えるようになってほしい..と思ってます

追記:使えるようになりました!

マークアップとスタイリング

<div class="grid-container">
  <div class="subgrid-container">
    <div class="grid-item">1</div>
    <div class="grid-item">2</div>
    <div class="grid-item">3</div>
  </div>
  <div class="subgrid-container">
    <div class="grid-item">4</div>
    <div class="grid-item">5</div>
    <div class="grid-item">6</div>
  </div>
</div>
.grid-container {
  display: grid;
  gap: 4px;
  grid-template-columns: repeat(3, auto);
}

.subgrid-container {
  grid-column: span 3;
  display: grid;
  grid-template-columns: subgrid;
}

.grid-item {
  background: #eee;
  padding: 4px;
}

:arrow_down_small: サンプル(Firefoxでご覧ください)

See the Pen subgrid by kabechiyo_shunkaaizawa (@kabechiyo) on CodePen.

33
14
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
33
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?