必見の記事

HTML5 × CSS3 × jQueryを真面目に勉強 – #16 レスポンシブWebデザインでテーブルを最適化するベストプラクティス

2013.03.18

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

業務にて担当する案件の殆どがエンタープライズ向けのアプリケーション開発(※PC向け)となると、モバイル向けにも Web コンテンツを最適化するという意識が薄れがちになったりします。とはいえ当ブログにて HTML や CSS に関する記事を執筆している手前、全く疎いのもよろしくないので、付け焼刃ですがレスポンシブ Web デザインのノウハウを学び始めることにしました。

はじめに

レスポンシブ Web デザインというキーワードも大分定着してきた感がありますが、その中でもテーブルという憎いあんちくしょうにおいては、なかなかどうしてスマートな見せ方が出来ているサイトというのが少なかったりします。それもそのはず、テーブル = 表 というだけあってエクセルに見られるような形式で表示しなくてはならないという先入観に、僕達はどうしても縛られてしまいがちなのです。

レスポンシブ Web デザインとは、PC をはじめスマートフォンやタブレットなど表示領域の異なる閲覧環境においてしかるべき情報をしかるべき形式にて表示することです。(※ やや強引な定義付けですが、だいたいはこんな感じです。)そんな訳で、テーブルをスマートフォンのような表示領域の狭い環境にて表示するためのプラクティスを調べてみました。

知っておきたい事前知識 - テーブルタグの Display 属性

そもそも Web ブラウザはテーブルレイアウトと呼ばれる形式の表示判断をどこでしているのでしょうか?テーブルを構成する<table /><thead /><tbody /><tfoot /><tr /><th /><td /> といったこれらのタグ。Web ブラウザはこのタグを見てテーブルレイアウトをディスプレイに表示するのでしょうか?

実は違います。思い出してください。Web ブラウザが HTML タグから得る情報は、その文書の構造だけのハズです。文書をどのようなレイアウトないし装飾で表示するかの情報は、全てスタイルシートで管理します。

「え?だって CSS を全く書かなくても勝手にテーブルレイアウトになるじゃあないか。」

いやいや、Web ブラウザも自前のスタイルシートをちゃんと持っています。Chrome もしくは Safari をお持ちの方は開発ツールを開いて、今見ている Web ページのスタイル情報を見てみてください。

sampleimg_useragentstylesheet

user agent stylesheet と表記された自身がオリジナルで作成したモノ以外のスタイルシートが読み込まれています。これはブラウザが標準で実装しているスタイルシートであり、このようにWebブラウザもまた自前のスタイルシートを備えているのです。

ではテーブルタグに対する user agent stylesheet の定義を見てましょう。

<table />display属性にはtableと指定されています。つまりdispaly属性にはblockinlineといったものだけでなく、ちゃんとテーブル形式で表示するための値が存在して、Web ブラウザはそれを見て表示していたということになります。

display 属性のテーブルに関する値一覧
説明
inline-table インラインテーブル値は、HTMLで直接マッピングがありません。これは、  <table> 要素と似ていますが、インラインボックスとしてではなく、ブロックレベルボックスに動作します。テーブルボックスの内部ブロックレベルのコンテキストになります。
table <table> 要素と同じように動作します。これは、ブロックレベルボックスを定義します。
table-caption  <caption> 要素と同じように動作します。
table-cell  <td> 要素と同じように動作します。
table-column 対応する <col> 要素と同じように動作します。
table-column-group 対応する <colgroup> 要素と同じように動作します。
table-footer-group 対応する <tfoot> 要素と同じように動作します。
table-header-group 対応する <thead> 要素と同じように動作します。
table-row <tr> 要素と同じように動作します。
table-row-group 対応する <tbody> 要素と同じように動作します。

dislay 属性についてもっと知りたいという方は、こちらのサイトを参照ください。

要するに何が言いたいかというと、テーブルもまたスタイルシートの display 属性によってその形状を実現しているに過ぎず、この値を色々と操作すればスマートフォンのようなスクリーンサイズの狭い環境にも最適化された表示が出来るのではないかということです。

実際に作ってみた - 下準備

今回は4パターンの表示を紹介します。まずは下準備として簡単なテーブルレイアウトと元となるスタイルを組んでいくとします。

はじめに HTML で適当なテーブルを作ります。

<table class="table table-striped table-responsive">
	<thead>
		<tr>
			<th>First Name</th>
			<th>Last Name</th>
			<th>Age</th>
			<th>Total</th>
			<th>Discount</th>
			<th>Difference</th>
			<th>Date</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>Bruce</td>
			<td>Almighty</td>
			<td>45</td>
			<td>$153.19</td>
			<td>44.7%</td>
			<td>+77</td>
			<td>Jan 18, 2001 9:12 AM</td>
		</tr>
		<tr>
			<td>Bruce</td>
			<td>Evans</td>
			<td>22</td>
			<td>$13.19</td>
			<td>11%</td>
			<td>-100.9</td>
			<td>Jan 18, 2007 9:12 AM</td>
		</tr>
		(略) 
	</tbody>
</table>

続いて CSS です。

responsive.css

.table {
  background: transparent;
  border-collapse: separate;
  border-spacing: 0;
  font-size: 85%;
  margin-bottom: 20px;
  width: 100%;
}
.table thead tr th,
.table thead tr td {
  border: 1px solid #cccccc;
  border-left-color: transparent;
  border-top-color: transparent;
  font-weight: normal;
  letter-spacing: .001em;
  line-height: 14px;
  padding: 10px 10px 5px 5px;
  text-align: right;
  vertical-align: bottom;
}
.table thead tr th:first-child,
.table thead tr td:first-child {
  padding-right: 0;
  text-align: left;
}
.table thead tr th:last-child,
.table thead tr td:last-child {
  border-right-color: transparent;
}
.table tbody tr {
  border: 1px solid #fdfdfd;
}
.table tbody tr th,
.table tbody tr td {
  border: 1px solid #cccccc;
  border-left-color: transparent;
  border-top-color: transparent;
  font-weight: normal;
  padding: 4px 10px;
  text-align: right;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}
.table tbody tr th:first-child,
.table tbody tr td:first-child {
  text-align: left;
}
.table tbody tr th:last-child,
.table tbody tr td:last-child {
  border-right-color: transparent;
}

.table-striped tbody tr:nth-child(odd) {
  background-color: #f6f6f6;
}

View demo(table layout)を開く(このサンプルはChromeブラウザでの閲覧をおすすめします。)

このシミュレータは勿論のこと、スマートフォンで表示させるとテーブルの幅がスクリーンサイズを超え、横スクロールが出てしまいます。PC のディスプレイ上でウィンドウ幅を狭めても文字が折り返されるだけで、とても見れたものではありません。どうにかして見せ方を変える必要があります。

では準備が出来たところで、ようやく本命の作成をしていくとします。

#1 | 項目を横並びから縦並びにする

そもそも Web において文字は横書きなのに、さらに項目を横に並べてしまうから狭い領域に収まりきらなくなるのです。

そこで発想を逆転させます。項目を縦に並べ替えてしまえば、余程のことが無い限りモバイル端末のような狭い領域のスクリーンサイズでも収めることができます。

responsive.css に以下のコードを追記します。

@media only screen and (max-width: 760px), (min-device-width: 768px) and (max-device-width: 1024px) {
  .table-responsive thead,
  .table-responsive tbody,
  .table-responsive th,
  .table-responsive td,
  .table-responsive tr {
    display: block;
  }
  .table-responsive thead {
    display: none;
  }
  .table-responsive tbody tr {
    border-top: 1px solid #cccccc;
  }
  .table-responsive tbody tr td {
    border: none;
    border-bottom: 1px solid #eeeeee;
    position: relative;
    padding-left: 50%;
    text-align: left;
  }
  .table-responsive tbody tr td:before {
    color: #555;
    position: absolute;
    top: 6px;
    left: 6px;
    width: 45%;
    padding-right: 10px;
    white-space: nowrap;
  }
  .table-responsive tbody tr td:nth-of-type(1):before {
    content: "First Name";
  }
  .table-responsive tbody tr td:nth-of-type(2):before {
    content: "Last Name";
  }
  .table-responsive tbody tr td:nth-of-type(3):before {
    content: "Age";
  }
  .table-responsive tbody tr td:nth-of-type(4):before {
    content: "Total";
  }
  .table-responsive tbody tr td:nth-of-type(5):before {
    content: "Discount";
  }
  .table-responsive tbody tr td:nth-of-type(6):before {
    content: "Difference";
  }
  .table-responsive tbody tr td:nth-of-type(7):before {
    content: "Date";
  }
}

View demo(table layout)を開く(このサンプルはChromeブラウザでの閲覧をおすすめします。)

まず使用しているテーブル関連のタグのdisplay属性をblockにしてしまいます。これですべての項目が縦並びになりました。次に<thead />にある項目名ですが、これをそのまま使用するのは無理があるので、display 属性をnoneにして非表示にしてしまします。しかしこれでは項目名が無いままなので、擬似要素の:beforeを使って、各項目名を擬似的に生成しています。

欠点としては、擬似要素の :before に項目名をハードコーディングしてしまうため、項目が動的に変わるような状況下では使うことが出来ないというのがあります。回避策として、CSS のクラスを JavaScript などで動的に生成するといったことが求められます。

実際に試してはいませんが、こちらの jQuery プラグインを使うことでこれらのことが実現出来るかもしれません。
Ariel Flesler: jQuery.Rule

#2 | 項目を横並びから縦並びにする2

<tbody />内に <th /> があるようなテーブルの場合には、それを各行のヘッダーと見立てることで先に紹介したサンプルとは一味違ったレイアウトにすることが出来ます。

responsive.css に以下のコードを追記します。

@media only screen and (max-width: 760px), (min-device-width: 768px) and (max-device-width: 1024px) {
  .table-responsive,
  tbody,
  th,
  tr,
  tr {
    display: block;
  }

  .table-responsive thead {
    display: none;
  }
  .table-responsive tbody tr + tr {
    margin-top: 20px;
  }
  .table-responsive tbody tr th,
  .table-responsive tbody tr td {
    border: none;
  }
  .table-responsive tbody tr th {
    font-size: 240%;
    line-height: 1em;
  }
  .table-responsive tbody tr td {
    display: list-item;
    list-style-type: square;
    margin-left: 3em;
    padding-left: 0;
    text-align: left;
  }
}

View demo(table layout)を開く(このサンプルはChromeブラウザでの閲覧をおすすめします。)

このサンプルではよりリストらしいレイアウトにしてみました。各項目名が必要な場合はやはり擬似要素:beforeを使う必要がありますが、こちらもハードコーディングするよりはJavaScriptを駆使して動的に生成出来るようにすると、より使い勝手の良いモノになります。

#3 | 必要最低限のカラムのみ表示する

現状スマートフォンは PC の代わりにはなりえていません。言い換えると PC 上で出来ていた作業の全てがスマートフォン上で出来る訳がありません。スマートフォンとは、PC が使えない状況下においてもせめて全機能の一部だけ使用出来るためのデバイスであると捉えるべきです。

この考えに基づくならば、テーブル内に沢山あるカラム全てを表示するのではなく、本当に必要な最低限のカラムだけを表示すれば良いということになります。どうしても全てを見たいならば、PC上で確認すればよいのです。

responsive.css に以下のコードを追記します。

@media only screen and (max-width: 768px), (max-device-width: 768px) {
  .table-responsive thead tr th:nth-child(7) {
    display: none;
    visibility: hidden;
  }
  .table-responsive tbody tr td:nth-child(7) {
    display: none;
    visibility: hidden;
  }
}
@media only screen and (max-width: 640px), (max-device-width: 640px) {
  .table-responsive thead tr th:nth-child(3),
  .table-responsive thead tr th:nth-child(5),
  .table-responsive thead tr th:nth-child(7) {
    display: none;
    visibility: hidden;
  }
  .table-responsive tbody tr td:nth-child(3),
  .table-responsive tbody tr td:nth-child(5),
  .table-responsive tbody tr td:nth-child(7) {
    display: none;
    visibility: hidden;
  }
}
@media only screen and (max-width: 480px), (max-device-width: 480px) {
  .table-responsive thead tr th:nth-child(3),
  .table-responsive thead tr th:nth-child(5),
  .table-responsive thead tr th:nth-child(6),
  .table-responsive thead tr th:nth-child(7) {
    display: none;
    visibility: hidden;
  }
  .table-responsive tbody tr td:nth-child(3),
  .table-responsive tbody tr td:nth-child(5),
  .table-responsive tbody tr td:nth-child(6),
  .table-responsive tbody tr td:nth-child(7) {
    display: none;
    visibility: hidden;
  }
}

View demo(table layout)を開く(このサンプルはChromeブラウザでの閲覧をおすすめします。)

このサンプルでは、あくまでもテーブルの形式はそのままに、ディスプレイの表示幅に応じて任意のカラムを非表示しています。やや重複の目立つ冗長なコードですが、やっていることは非常にシンプルです。

#4 | カラムを二分割して横スクロールにしてしまう

単純にテーブルの幅がスクリーンサイズを超えてページ全体に対して横スクロールバーが出てくるというのは、ただのレイアウト崩れでありバグです。しかしある特定の箇所のみをスクロールさせ、ページ全体が大きく動かないように制御すれば、最適なレイアウトを作ることができます。

そこでテーブルカラムを大きく2つのグループに縦分割します。左側には縦並びに組み替えたヘッダーを置き、右側には同じく縦並びに組み替えた項目値を置いて、表示しきれない場合は横スクロールさせることによって全体を見れるようにします。

responsive.css に以下のコードを追記します。

@media only screen and (max-width: 640px), (max-device-width: 640px) {
  .table-responsive {
    display: block;
    position: relative;
  }
  .table-responsive thead,
  .table-responsive tbody,
  .table-responsive th,
  .table-responsive td,
  .table-responsive tr {
    display: block;
  }
  .table-responsive thead {
    float: left;
  }
  .table-responsive thead tr {
    border: 1px solid #fdfdfd;
  }
  .table-responsive thead tr th,
  .table-responsive thead tr td {
    border-bottom-color: #e61376;
    border-right-color: #e61376;
    line-height: 20px;
    padding: 4px 10px;
  }
  .table-responsive thead tr th:last-child,
  .table-responsive thead tr td:last-child {
    border-right-color: #e61376;
  }
  .table-responsive tbody {
    overflow-x: auto;
    position: relative;
    white-space: nowrap;
    width: auto;
  }
  .table-responsive tbody tr {
    display: inline-block;
    vertical-align: top;
  }
  .table-responsive tbody tr td:first-child {
    text-align: right;
  }
}

View demo(table layout)を開く(このサンプルはChromeブラウザでの閲覧をおすすめします。)

おまけ - jQuery プラグインを使ったテクニック 2選

今回ここで紹介したプラクティスは全て CSS3 のみを使って実現させたものになりますが、以下に紹介する jQuery プラグインを使用することで、より高性能なレイアウトを実現することができます。

rwd-table.js - 表示するカラムをCheckboxで選択する

カラム一覧をドロップダウンリストが生成され、表示させたいカラムをチェックボックスで選択することができます。またディスプレイ表示幅に応じて自動的に表示するカラムを選別することもしてくれます。

sampleimg_rwd-table-js

responsive-tables.js - テーブルを縦二分割して横スクロールを表示する

#4で紹介した CSS3 のテクニックと似ていますが、こちらはテーブルそのもののレイアウトは保持したままに横スクロールでの表示を実現します。

sampleimg_responsive-table-js

おわりに

スマートフォンのような狭いスクリーンサイズにどれだけの情報を詰め込むかは、開発者の見極めが問われるところです。一方で大概のクライアント(※顧客)はできるだけ多くの情報を無理やりにでも詰め込みたがりますが、当然そこには多くのデメリットが潜んでいます。その結果、ひと通りの情報は掲載させることは出来たとしても、文字が極端に小さくなったり上下左右にスクロールさせないと見ることが出来ないような状態になっては、ちっともスマートとは言えません。

肝心なのは情報に優先度をつけて本当に見せたい情報だけを表示させ、それ以外はバッサリと切り捨ててしまう割り切りが真の使いやすさにつながることだと僕は信じています。

いかに既成概念にとらわれずこれまでとは違う見せ方を作り出すかが、僕達がレスポンシブ Web デザインをしていく上で問われていることではないでしょうか。