はじめに
PCの時には見出しが上につくテーブルレイアウト、スマホの時はカードになっているデザインのやり方を見かけないので(単純にそんなレイアウトの需要がないのかもしれない)覚書として投稿します。
目標デザイン
PCブラウザーで見たときは見出しが上の表で、画面幅を縮めていくとカードデザインになり、横並びに 見出し+内容 のレイアウト。
使うもの
HTML5, CSS3
コード
<div class="table">
<div class="thead">
<div class="thead_tr">
<div class="th">Name</div>
<div class="th">Age</div>
<div class="th">Height</div>
<div class="th">Weight</div>
</div>
</div>
<!-- tbody -->
<div class="tbody__lp_block">
<div class="lp_card">
<div class="tr__lp_table">
<!-- inner -->
<div class="lp_tr">
<div class="td lp_header">Name</div>
<div class="td" id="air_code">Ken</div>
</div>
<!-- inner -->
<div class="lp_tr">
<div class="td lp_header">Age</div>
<div class="td">18</div>
</div>
<!-- inner -->
<div class="lp_tr">
<div class="td lp_header">Height</div>
<div class="td">170</div>
</div>
<!-- inner -->
<div class="lp_tr">
<div class="td lp_header">Weight</div>
<div class="td">60</div>
</div>
<!-- -->
</div>
</div>
<div class="lp_card">
<div class="tr__lp_table">
<!-- inner -->
<div class="lp_tr">
<div class="td lp_header">Name</div>
<div class="td" id="air_code">John</div>
</div>
<!-- inner -->
<div class="lp_tr">
<div class="td lp_header">Age</div>
<div class="td">22</div>
</div>
<!-- inner -->
<div class="lp_tr">
<div class="td lp_header">Height</div>
<div class="td">169</div>
</div>
<!-- inner -->
<div class="lp_tr">
<div class="td lp_header">Weight</div>
<div class="td">55</div>
</div>
<!-- -->
</div>
</div>
<div class="lp_card">
<div class="tr__lp_table">
<!-- inner -->
<div class="lp_tr">
<div class="td lp_header">Name</div>
<div class="td" id="air_code">Ben</div>
</div>
<!-- inner -->
<div class="lp_tr">
<div class="td lp_header">Age</div>
<div class="td">30</div>
</div>
<!-- inner -->
<div class="lp_tr">
<div class="td lp_header">Height</div>
<div class="td">188</div>
</div>
<!-- inner -->
<div class="lp_tr">
<div class="td lp_header">Weight</div>
<div class="td">76</div>
</div>
<!-- -->
</div>
</div>
</div>
</div>
.table {
display: table;
table-layout: fixed;
width: 100%;
}
.thead {
display: table-header-group;
}
.thead_tr {
display: table-row;
}
.thead_tr > .th {
background: #333;
color: #ffff;
width: 200px;
padding: 5px 0;
text-align: center;
}
.th {
display: table-cell;
}
.tbody__lp_block {
display: table-row-group;
}
.td {
padding: 10px;
}
@media screen and (width>=745px) {
.tr__lp_table {
display: table-row;
}
.lp_tr {
display: contents;
}
.td {
display: table-cell;
text-align: center;
background: #ccc;
}
.lp_header {
color: red;
display: none;
}
.lp_card {
display: contents;
}
}
/* ----- card -------------- */
@media screen and (width<745px) {
.table {
display: contents;
}
.thead {
display: none;
}
.tbody__lp_block {
display: flex;
flex-direction: column;
row-gap: 20px;
}
.lp_card {
border-radius: 20px;
padding: 10px 20px;
background: #fff;
box-shadow: 0px 2px 4px #00000029;
}
.tr__lp_table {
display: table;
}
.lp_tr {
display: table-row;
}
.lp_header {
display: table-cell;
width: 150px;
}
}
ポイントと解説
- ブレークポイント(今回は745px)でタグのプロパティを切り分け
- display : contents を活用
- table, tr, td... タグではなくdivタグで構築
ブレークポイント(今回は745px)でタグのプロパティを切り分け
htmlにて、タグを入れ子構造にします。ブレークポイントで、タグのスタイル:displayプロパティを切り分け:表示非表示にします。
画面横幅が745px以上の時は、テーブルレイアウトにしたいので、CSSは以下のようにします。この時、カードデザインの時にのみ使用するタグのクラス(lp_tr, lp_header, lp_card)をdisplay: contents, noneにしています。
@media screen and (width>=745px) {
.tr__lp_table {
display: table-row;
}
.lp_tr {
display: contents;
}
.td {
display: table-cell;
text-align: center;
background: #ccc;
}
.lp_header {
color: red;
display: none;
}
.lp_card {
display: contents;
}
}
745pxより小さい時は、上記の反対になるよう調整します。この時、見出し部分の .thead は不要なので、display: noneにし、.tbody__lp_blockのテーブルを解除、表の行(tr)として使っていたタグ(.tr__lp_table)をtableにします。
@media screen and (width<745px) {
.table {
display: contents;
}
.thead {
display: none;
}
.tbody__lp_block {
display: flex;
flex-direction: column;
row-gap: 20px;
}
.lp_card {
border-radius: 20px;
padding: 10px 20px;
background: #fff;
box-shadow: 0px 2px 4px #00000029;
}
.tr__lp_table {
display: table;
}
.lp_tr {
display: table-row;
}
.lp_header {
display: table-cell;
width: 150px;
}
}
display : contents を活用
要素を非表示にしたい場合、display: none も候補に上がると思いますが、noneを指定した親要素の小要素も見えなくなってしまいます。そこで、display: contents の出番です。display: contents を指定した要素が、あたかもhtml構造上いないようにでき、親要素のみが非表示、小要素は表示されます。
table, tr, td... タグではなくdivタグで構築
divタグでもdisplayプロパティをtableで使われるプロパティに設定すれば、テーブルレイアウトになります。逆にtable, tr, td...タグで構成してプロパティをブレークポイントで変更かければ良いのではないか、そっちの方がセマンティックではないかと思うかもしれませんが、最初これで実装して見ました。しかし、ブラウザー側がタグでプロパティに矯正をかけてしまうようで(?)うまく調整できませんでした。(見た目はそれっぽくなるが、デベロッパーツールで確認しとき構造が記述したコード通りになっていなかった)そのため、あえて、divタグで構成しております。
おわりに
こんなレイアウトを実装しようとしている方へ参考になれば幸いです。もっと良いコードの書き方があるかもしれません。