マークアップシリーズの第2回は、前回のよくある3つのデザインから考える、マークアップの最適解と同じく、html5jマークアップ部主催のイベント「MarkupCafe」で出題された3つのお題から最適なマークアップを探ります。
イベントではAからDの4つのチームにわかれてマークアップを考えました。それぞれのチームごとに違ったマークアップへの考えが表れていてとても興味深いです。また今回はイベント終了後に「HTML5 Experts.jp」のエキスパート兼マークアップ部の部長でもある村岡正和氏に、氏自身ならこうするといったマークアップを公開してもらいました。
本記事ではWebサイト制作の際にありがちな”ページング”、”フォーム”、”データテーブル”の3つについて要素の使いどころや仕様、アクセシビリティやユーザビリティといった観点からマークアップを考えていきます。
1.ページングの中身と重要度
最初のお題はページング。
ブログのページ送りや検索結果でページが多い場合に使われますが、あまり深く考えてマークアップしたことはないのではないでしょうか。
このお題で注目したポイントは以下の3つです。
- 現在地をどう示すか
- 重要と強調の違い
- 前へと次への扱い
それぞれのチームのマークアップから考えていきます。
各チームのマークアップ
1 2 3 4 5 6 7 8 9 10 11 |
<div class="pagination"> <p class="prev"><a rel="prev">前へ</a> <p class="next"><a href="/next" rel="next">次へ</a> <ol class="sequential"> <li><a class="current">1</a> <li><a href="/page2">2</a> <li><a href="/page3">3</a> <li><a href="/page4">4</a> <li><a href="/page5">5</a> </ol> </div> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<div class="paginate"> <p> <a href="" rel="prev" class="prev"><<前へ</a> </p> <ol> <li><em>1</em> <li><a href="2">2</a> <li><a href="3">3</a> <li><a href="4">4</a> <li><a href="5">5</a> </ol> <p> <a href="" rel="next" class="next">次へ>></a> </p> </div> |
1 2 3 4 5 6 7 8 9 10 11 |
<nav> <a href="#"><<前へ</a> <ol> <li><a href="#">1</a></li> <li><a href="#">2</a></li> <li><a href="#">3</a></li> <li><a href="#">4</a></li> <li><a href="#">5</a></li> </ol> <a href="#">次へ>></a> </nav> |
1 2 3 4 5 6 7 8 9 10 11 |
<nav> <strong><a><<</a></strong> <ul> <li><span>1</span></li> <li><a>2</a></li> <li><a>3</a></li> <li><a>4</a></li> <li><a>5</a></li> </ul> <strong><a>>></a></strong> </nav> |
現在地の表し方
チームAは <li><a class="current">1</a> と、href属性を外しています。a要素はアンカーとしての意味がありますが、href属性がないa要素はプレースホルダーを表すという仕様を考えてのことです。
チームBは <li><em>1</em> とem要素で現在地を強調することで表しています。
現在どこのページにいるのかをページングで表現する場合、主に視覚的な観点からスタイルを変えるというアプローチを取ることが多いと思います。ですがセマンティクスを考える場合には、こういった表し方も意識する必要があるのではないでしょうか。
重要か強調か、strongとemの違いは?
チームDは前へと次へのリンクに対してstrong要素でマークアップしています。
strong要素はHTML5の仕様では強調ではなく強い重要性を表す要素とされています。
em要素はニュアンスとしての強調ですがstrong要素を使った場合そのコンテンツの中でその部分が重要であると意味付けしていることになります。
ページングというコンテキストにおいて、重要かどうかといった意味付けをするのが適しているかは、判断するのがかなり難しいと思います。
リンク先との関係から考えられるもの
チームAとチームBは
<a href="#" rel="prev">前へ</a> <a href="#" rel="next">次へ</a> といったように、a要素に対してrel属性を付けています。
rel属性は参照元のドキュメントからみた参照先のリンクとの関係性(relationship)を示す属性です。
rel="prev" とすることでリンクが示す先のページが前のページであると意味をつけることができます。
ブラウザの中にはrel属性を解釈してブラウザ自体のナビゲーションに前のページや次のページへのリンクを表示するといった実装をしているものもあります。(prestoの頃のOperaなど)
普段外部CSSの読み込みの際に rel="stylesheet" と記述することが多いと思いますが、ユーザビリティやアクセシビリティといった観点からrel属性を使用するというのも一つの考えです。
視覚的・構造的順番の分離がもたらす効果
またチームAは他のチームと大きく違い、”次へ”のリンクをページ番号のリストより前にマークアップしています。
これはスクリーンリーダなど音声による読み上げを考えた場合に「”前へ”の次に数字が読みあげられるよりも”次へ”を読み上げたほうが良いと考えた」という観点からでした。
視覚的な構造をスタイルシートで表すようにすることで、アクセシビリティを意識するといった違った視点からマークアップをすることができると、とても考えさせられるマークアップです。
部長はこう書く!
このお題に対しての村岡氏のマークアップです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<head> <link rel="next" href="p2.html"> </head> <body> <div> <p><a class="prev">前へ</a></p> <ol> <li><a class="current-page">1</a></li> <li><a href="p2.html">2</a></li> <li><a href="p3.html">3</a></li> <li><a href="p4.html">4</a></li> <li><a href="p5.html">5</a></li> </ol> <p><a class="next" href="p2.html">次へ</a> </div> </body> |
マークアップ自体はチームAとチームBに似ていますが、”<<”や”>>”はスクリーンリーダなどで読み上げてほしくないといったことから、CSSの擬似要素で視覚的に挿入しています。
アクセシビリティを意識したとき、順番を考えるのも大事ですが、そのコンテンツ自身も意識することが大事だと考えられます。
2.進化するフォームに対応できるか
2つ目のお題はフォームです。
このお題で注目したポイントは以下の3つです。
- アスタリスク
- label要素の使い方
- input要素の属性
各チームのマークアップ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<section class="reservation"> <h1>バスタイム商事 会議室予約フォーム</h1> <p class="note"><span class="mark-req">*</span>は必須入力です</p> <form> <table> <tr><th><label for="room">会議室名</label> <td><input id="room" required aria-label="会議室名(必須)"> <span class="mark-req">*</span> <tr><th><label for="date">ご利用日</label> <td><input id="date" type="date" required aria-label="ご利用日(必須)"> <span class="mark-req">*</span> <tr><th><label for="time">ご利用時刻</label> <td><input id="time" type="time" required aria-label="利用開始時刻(必須)"> 〜 <input type="time" required aria-label="利用終了時刻(必須)"> <span class="mark-req">*</span> <tr><th><label for="number">ご利用人数</label> <td><input id="number" type="number" min="1" step="1" required aria-label="ご利用人数(必須)"> <span class="mark-req">*</span> <tr><th><label for="name">代表者氏名</label> <td><input id="name" required aria-label="代表者氏名(必須)"> <span class="mark-req">*</span> <tr><th><label for="name-reading">代表者氏名ローマ字<br><span class="note-label">(半角英字)</span></label> <td><input id="name-reading" pattern="[A-Za-z\. ]+" required aria-label="代表者氏名ローマ字(必須、半角英字)"> <span class="mark-req">*</span> <tr><th><label for="email">E-Mail</label> <td><input id="email" type="email" required aria-label="E-Mail(必須)"> <span class="mark-req">*</span> <tr><th><label for="tel">TEL</label> <td><input id="tel" type="tel"> <tr><th><label for="url">URL</label> <td><input id="url" type="url" pattern="^https?\:\/\/.+"> </table> <button>予約する</button> </form> </section> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<form action=""> <p> <strong> <label for="f1">会議室名</label><input type="text" name="f1" id="f1" required autofocus="autofocus"><span>*</span> </strong> <p> <strong> <label for="f2">ご利用日</label><input type="date" name="f2" id="f2" required><span>*</span> </strong> <p> <strong> <label for="f3">ご利用時刻</label><input type="time" name="f3" id="f3" required>〜 <label for="f4"></label><input type="time" name="f4" id="f4" required><span>*</span> </strong> <p> <strong> <label for="f5">ご利用人数</label><input type="number" name="f5" id="f5" required><span>*</span> </strong> <p> <strong> <label for="f6">代表者氏名</label><input type="text" name="f6" id="f6" required><span>*</span> </strong> <p> <strong> <label for="f7">代表者氏名ローマ字</label><input type="text" pattern="^[A-Za-z]+$" name="f7" id="f7" required><span>*</span> </strong> <p> <strong> <label for="f8">E-Mail</label><input type="email" name="f8" id="f8" required><span>*</span> </strong> <p><label for="f9">TEL</label><input type="tel" name="f9" id="f9"> <p><label for="f10">URL</label><input type="url" name="f10" id="f10"> <p><input type="submit" value="予約する"> </form> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
<header> <h1>バスタイム商事 会議室予約フォーム</h1> </header> <p><span>※</span>は入力必須です</p> <form action="#"> <div> <label for="muraoka1">会議室名</label> <input id="muraoka1" type="text" name="btf1"><span>※</span> </div> <div> <label for="muraoka2">ご利用日</label> <input id="muraoka2" type="date" name="btf2"><span>※</span> </div> <div> <label>ご利用時刻 <input id="muraoka3" type="time" name="btf31">〜 <input type="time" name="btf32"><span>※</span> </label> </div> <div> <label for="muraoka4">ご利用人数</label> <input id="muraoka4" type="number" name="btf4"><span>※</span> </div> <div> <label for="muraoka5">代表者氏名</label> <input id="muraoka5" type="text" name="btf5"><span>※</span> </div> <div> <label for="muraoka6">代表者氏名ローマ字(半角英字)</label> <input id="muraoka6" type="text" name="btf6"><span>※</span> </div> <div> <label for="muraoka7">E-Mail</label> <input id="muraoka7" type="email" name="btf7"><span>※</span> </div> <div> <label for="muraoka8">TEL</label> <input id="muraoka8" type="tel" name="btf8"> </div> <div> <label for="muraoka9">URL</label> <input id="muraoka9" type="url" name="btf9"> </div> <input type="submit" value="予約する"> </form> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<h1>バスタイム商事 会議予約フォーム</h1> <p><small><i>*</i>は入力必須です</small></p> <form action=""> <ul> <li><label>会議室名 <input type="text" required></label><i>*</i></li> <li><label>ご利用日 <input type="date" required></label><i>*</i></li> <li><label>ご利用時刻 <input type="time" required></label><i>*</i></li> <li><label>ご利用人数 <input type="number" min="1" required></label><i>*</i></li> <li><label>代表者氏名 <input type="text" required><i>*</i></label></li> <li><label>代表者氏名ローマ字<small>(半角英字)</small> <input type="text" pattern="^[0-9A-Za-z]+$" required></label><i>*</i></li> <li><label>E-Mail <input type="email" required></label><i>*</i></li> <li><label>TEL <input type="tel"></label></li> <li><label>URL <input type="url"></label></li> </ul> <input type="submit" value="予約する"> </form> |
i要素は日本語に合わない?
チームDは必須項目を表しているアスタリスクをi要素でマークアップしています。i要素は最近ですとスプライトアイコンを使用する際に使われていることが多いように思います。
仕様的にはi要素は文章中で他と区別したいテキストや印刷の際に斜体になるテキストに対して使うとされています。
ただこの仕様は欧文の文章慣習に拠っている部分が大きいので「そもそも日本語の文章慣習には合っていないのではないか」という意見もありました。
そう考えるとi要素を使わずにem要素やb要素でマークアップするといったことも考えられるかもしれません。
アスタリスクじゃ伝わらない
Webのフォームにおいて、赤いアスタリスクで”入力必須項目”であることを表しているページが多いと思います。
しかしこれについて「赤いアスタリスク自体には必須項目であるという意味はないので、そもそもこういった使い方がよくないのでは」という意見がありました。
また、このお題ではデザイン的にアスタリスクが後ろに来ていることから、アスタリスクを項目の後ろにマークアップすると思います。ですが読み上げされる場合を考えると、項目名の読み上げを行なった後にその項目が必須であるかどうかがわかります。
アクセシビリティやユーザビリティをしっかり考えた場合、項目の前に”(必須項目です)”といったような記述をすることが望ましいのではないかと筆者は考えます。
囲むか分けるか、label要素の使い方
label要素はinput要素を内包する書き方と、for属性によって対象のinput要素を指定する書き方の二通りあり、マークアップ的にはどちらの書き方も正しいです。
今回の場合デザイン的にラベルの右側にマージンが空いてる様に見えるので、スタイル付けがしやすいようにlabel要素とinput要素を分けて書く方が適していると考えることができます。
type=”?”
HTML5ではinput要素のtype属性に色々なtypeが設定できるようになっています。
数字にはnumber、メールアドレスにはemailなど、JavaScriptを使わずに入力項目のフォーマットを指定することができます。
typeを上手く使い分けることで、ユーザが入力の際に迷わないフォームが作れるのではないでしょうか。
なお、これらのtypeに対応していないブラウザでは type="text" を指定したのと同等に扱われます。
input要素で使える便利な属性たち
いくつかのチームでinput要素の属性にrequired属性やautofocus属性といった指定をしています。
requiredはその項目が必須であることを表し、送信ボタンを押した際にはその項目が未入力であった場合に未入力であると警告して送信処理を行いません。
autofocus属性はそのページを開いた際に自動的に入力欄にフォーカスされ、ユーザーが項目を選択することなく入力を開始することができます。
ほかにもautocomplete属性やstep属性、またpattern属性といったものもあり、これらを使えばJavaScriptを書かずに入力内容に制約をかけることもできます。
入力チェックは万全に
input要素の属性を使う上で注意しておきたい点があります。required属性やpattern属性といった属性は確かに便利なのですが、データの入力チェックをこれだけで済ましてはいけません。
これらの属性はあくまでも入力の補助的な機能であって、送信されてくるデータは保証していません。
悪意のある第三者が、入力フォームを通さずにフォームの送信先に直接データを送ることも十分に考えられます。そういった場合これらの属性は無力です。
フォームで入力必須にしてあるし正規表現で形式指定してあるから送られてくるデータは必ず正しい、と思わずに、送信されてきたデータはしっかりとサーバサイドで整合性をチェックする必要がある、ということを覚えておいてください。
部長はこう書く!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
<h1>バスタイム商事 会議室予約フォーム</h1> <p class="note"><span class="mark-req">*</span>は必須入力です</p> <form> <div> <label for="room-name">会議室名</label> <input id="room-name" required placeholder="A会議室"> <span class="required">*</span> </div> <div> <label for="date">ご利用日</label> <input id="date" type="date" required placeholder="2013/01/23"> <span class="required">*</span> </div> <div> <label for="time">ご利用時刻</label> <input id="time" type="time" required placeholder="01:13"> 〜 <input type="time" required placeholder="02:34"> <span class="required">*</span> </div> <div> <label for="number">ご利用人数</label> <input id="number" type="number" placeholder="1"> <span class="required">*</span> </div> <div> <label for="name">代表者氏名</label> <input id="name" required placeholder="神戸 太郎"> <span class="required">*</span> </div> <div> <label for="name-roma"> 代表者氏名ローマ字<br> <span class="notes">(半角英字)</span> </label> <input id="name-roma" pattern="[A-Za-z/ .]+" required placeholder="Taro Kobe"> <span class="required">*</span> </div> <div> <label for="email">E-Mail</label> <input id="email" type="email" required placeholder="kobe@bathtimeshoji.com"> <span class="required">*</span> </div> <div> <label for="tel">TEL</label> <input id="tel" type="tel" placeholder="0123456789"> </div> <div> <label for="url">URL</label> <input id="url" type="url" placeholder="http://bathtimeshoji.com"> </div> <input type="submit" value="予約する"> </form> |
前述したように、ブラウザが対応していないtypeが指定されている場合には
type="text" として扱われます。
対応していないブラウザでフォームを開いた場合に、ユーザーが少しでも迷わないようにplaceholder属性で入力する項目の内容を示すのも有効な手段です。
3.tableを見直す
最後のお題は業績の表です。
このお題で注目したポイントは以下の2つです。
- tableの構造
- scope属性
お題のデザインをHTMLとCSSで見た目的に表すのにそれほど時間はかからないと思います。 table要素でマークアップして見出しのセルをcolspanで適宜結合すれば数分で終わる作業です。 ですが各データと見出しの関係性をしっかりとマークアップで表そうとした場合、table要素への理解が必要になります。
各チームのマークアップ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
<table border> <thead> <tr> <th> <th>2012年3月 <th>2013年3月 </thead> <tbody> <tr><th colspan="3" scope="rowgroup">連結経営成績 <tr><th scope="row">営業収益 <td>1,000 <td>1,000 <tr><th scope="row">営業利益 <td>1,000 <td>1,000 <tr><th scope="row">税引前利益 <td>1,000 <td>1,000 <tr><th scope="row">当期利益 <td>1,000 <td>1,000 </tbody> <tbody> <tr><th colspan="3" scope="rowgroup">連結財政状態 <tr><th scope="row">資産合計 <td>1,000 <td>1,000 <tr><th scope="row">資本合計 <td>1,000 <td>1,000 <tr><th scope="row">帰属持分比率(%) <td>10.0 <td>10.0 </tbody> <tbody> <tr><th colspan="3" scope="rowgroup">キャッシュフローの状況 <tr><th scope="row">営業活動によるキャッシュフロー <td>1,000 <td><span class="mark">△</span>1,000 <tr><th scope="row">投資活動によるキャッシュフロー <td><span class="mark">△</span>1,000 <td><span class="mark">△</span>1,000 <tr><th scope="row">財務活動によるキャッシュフロー <td>1,000 <td>1,000 <tr><th scope="row">現金及び現金同等物<br>期末残高 <td>1,000 <td>1,000 </tbody> </table> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
<div> <table> <caption>連結経営成績</caption> <thead class="thead"> <tr> <th>項目</th> <th>2012年3月</th> <th>2013年3月</th> </tr> </thead> <tbody> <tr> <td>営業収益</td><td>237,409</td><td>203,423</td> </tr> <tr> <td>営業利益</td><td>237,409</td><td>203,423</td> </tr> <tr> <td>税引前利益</td><td>237,409</td><td>203,423</td> </tr> <tr> <td>当期利益</td><td>237,409</td><td>203,423</td> </tr> </tbody> </table> </div> <div> <table> <caption>連結財政状態</caption> <thead> <tr> <th>項目</th> <th>2012年3月</th> <th>2013年3月</th> </tr> </thead> <tbody> <tr> <td>営業収益</td><td>237,409</td><td>203,423</td> </tr> <tr> <td>営業利益</td><td>237,409</td><td>203,423</td> </tr> <tr> <td>税引前利益</td><td>237,409</td><td>203,423</td> </tr> <tr> <td>当期利益</td><td>237,409</td><td>203,423</td> </tr> </tbody> </table> </div> <div> <table> <caption>キャッシュフローの状況</caption> <thead> <tr> <th>項目</th> <th>2012年3月</th> <th>2013年3月</th> </tr> </thead> <tbody> <tr> <td>営業収益</td><td>237,409</td><td>203,423</td> </tr> <tr> <td>営業利益</td><td>237,409</td><td>203,423</td> </tr> <tr> <td>税引前利益</td><td>237,409</td><td>203,423</td> </tr> <tr> <td>当期利益</td><td>237,409</td><td>203,423</td> </tr> </tbody> </table> </div> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
<table border="1"> <thead> <th></th> <th>2012/3</th> <th>2013/3</th> </thead> <tbody> <tr><th colspan="3">連結経営成績</th></tr> <tr> <th>AAA</th> <td>123,456</td> <td>7,890</td> </tr> <tr> <th>AAA</th> <td>123,456</td> <td>7,890</td> </tr> <tr> <th>AAA</th> <td>123,456</td> <td>7,890</td> </tr> <tr><th colspan="3">連結財政状態</th></tr> <tr> <th>AAA</th> <td>123,456</td> <td>7,890</td> </tr> <tr> <th>AAA</th> <td>123,456</td> <td>7,890</td> </tr> <tr> <th>AAA</th> <td>123,456</td> <td>7,890</td> </tr> <tr><th colspan="3">キャッシュフローの状況</th></tr> <tr> <th>AAA</th> <td>123,456</td> <td>7,890</td> </tr> <tr> <th>AAA</th> <td>123,456</td> <td>7,890</td> </tr> <tr> <th>AAA</th> <td>123,456</td> <td>7,890</td> </tr> </tbody> </table> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
<table border="1"> <thead> <tr> <th></th> <th id="year2012" scope="col">2012年3月</th> <th id="year2013" scope="col">2013年3月</th> </tr> </thead> <tbody> <tr> <th colspan="3" scope="col" class="title">連結経営成績</th> </tr> <tr> <th scope="row">営業収益</th> <td headers="year2012">2000円</td> <td headers="year2013">2000円</td> </tr> <tr> <th scope="row">営業収益</th> <td headers="year2012">2000円</td> <td headers="year2013">2000円</td> </tr> <tr> <th scope="row">営業収益</th> <td headers="year2012">2000円</td> <td headers="year2013">2000円</td> </tr> <tr> <th scope="row">営業収益</th> <td headers="year2012">2000円</td> <td headers="year2013">2000円</td> </tr> <tr> <th colspan="3" scope="col" class="title">連結経営成績</th> </tr> <tr> <th scope="row">営業収益</th> <td headers="year2012">2000円</td> <td headers="year2012">2000円</td> </tr> <tr> <th scope="row">営業収益</th> <td headers="year2012">2000円</td> <td headers="year2013">2000円</td> </tr> <tr> <th scope="row">営業収益</th> <td headers="year2012">2000円</td> <td headers="year2013">2000円</td> </tr> <tr> <th scope="row">営業収益</th> <td headers="year2012">2000円</td> <td headers="year2013">2000円</td> </tr> <tr> <th colspan="3" scope="col" class="title">連結経営成績</th> </tr> <tr> <th scope="row">営業収益</th> <td headers="year2012">2000円</td> <td headers="year2012">2000円</td> </tr> <tr> <th scope="row">営業収益</th> <td headers="year2012">2000円</td> <td headers="year2013">2000円</td> </tr> <tr> <th scope="row">営業収益</th> <td headers="year2012">2000円</td> <td headers="year2013">2000円</td> </tr> <tr> <th scope="row">営業収益</th> <td headers="year2012">2000円</td> <td headers="year2013">2000円</td> </tr> <tr> <th colspan="3" scope="col" class="title">連結経営成績</th> </tr> <tr> <th scope="row">営業収益</th> <td headers="year2012">2000円</td> <td headers="year2012">2000円</td> </tr> <tr> <th scope="row">営業収益</th> <td headers="year2012">2000円</td> <td headers="year2013">2000円</td> </tr> <tr> <th scope="row">営業収益</th> <td headers="year2012">2000円</td> <td headers="year2013">2000円</td> </tr> <tr> <th scope="row">営業収益</th> <td headers="year2012">2000円</td> <td headers="year2013">2000円</td> </tr> </tbody> </table> |
みんなが悩んだscope属性
参加者を大いに悩ませたのは右上にある年月の表示です。年月の見出しはデータ的に列方向のセルに掛かっています。しかし先頭に空行の見出しセルがあったり、”連結経営成績”などのカラム全体にまたがるセルが存在してたりと、見出しとセルの関連付けが一見してやりづらそうな見た目です。
こういった単純ではない表で有効とされているのがscope属性の指定です。
“年月”の見出しには
scope="col" として列方向の見出しであることを、”営業収益”などの見出しは
scope="row" として行方向の見出しであることを明示します。
scope属性の指定によってデータ的に曖昧だった見出しの対象範囲を指定することができます。
また、scope属性を指定することでユーザーエージェントに見出しの方向を正しく伝えることができるので、データをよりアクセシブルにするために有効であるという見方もできます。データの関係性をしっかりとマークアップすることで、アクセシビリティ的にもより良いマークアップにすることができると考えられます。
CSS is Power !?
チームBはこのデザインを3つの表の集まりとして捉えてマークアップしています。「年月の見出しなどで一つの表に見えるだけで、それぞれ独立した表である」と考えてのことでした。3つの表では見出しセルとしてtheadに年月を入れていますが、CSSによって1つ目の表の見出しだけを表示するようにしています。
見た目と構造の分離という観点から見ると、スタイリングによって解決することも一つの手法なのではと筆者は考えます。
部長はこう書く!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
<section> <table border="1"> <thead> <tr> <th></th> <th scope="col">2012年3月</th> <th scope="col">2013年3月</th> </tr> </thead> <tbody> <tr> <th scope="rowgroup" colspan="3" class="group"> 連結経営成績 </th> </tr> <tr > <th scope="row">営業収益</th> <td>237,409</td> <td>203,423</td> </tr> <tr> <th scope="row">営業利益</th> <td>15,530</td> <td>14,577</td> </tr> <tr> <th scope="row">税引前利益</th> <td>13,600</td> <td>10,213</td> </tr> <tr> <th scope="row">当期利益</th> <td>2,562</td> <td>7,962</td> </tr> <tr> <th scope="rowgroup" colspan="3"> 連結財政状態 </th> </tr> <tr > <th scope="row">資産合計</th> <td>2,455,368</td> <td>7,793,387</td> </tr> <tr> <th scope="row">資本合計</th> <td>320,905</td> <td>330,535</td> </tr> <tr> <th scope="row">帰属持分比率(%)</th> <td>17.9</td> <td>12.2</td> </tr> <tr> <th scope="rowgroup" colspan="3"> キャッシュフローの状況 </th> </tr> <tr > <th scope="row">営業活動によるキャッシュフロー</th> <td>9,618</td> <td>△32,954</td> </tr> <tr> <th scope="row">投資活動によるキャッシュフロー</th> <td>△13,021</td> <td>△16,160</td> </tr> <tr> <th scope="row">財務活動によるキャッシュフロー</th> <td>7,487</td> <td>23,699</td> </tr> <tr> <th scope="row">現金および現金同等物<br>期末残高</th> <td>129,833</td> <td>110,362</td> </tr> </tbody> </table> </section> |
table要素に border="1" を指定しています。これはこのtable要素がレイアウト目的で使われているものではないと明示したいという意図での指定です。
テーブルレイアウトは一般的に推奨されていませんが、レイアウト目的でtable要素を使いたい場合には role="presentation" といった属性を指定して、ユーザーエージェントにこの表がレイアウト目的で使用されているということを明示すべきだとされています。合わせて border="0"や cellspacing="0" cellpadding="0"を指定することでも、その表がレイアウト目的だと伝えるための手がかりとすることができます。
マークアップの奥深さ
前回同様に今回のイベントでも各お題に対して30分の考察時間が設けられましたが、どのお題も30分ではまとめられないほどの議論がありました。
いろいろな考えがありますが、人それぞれに違ったマークアップがあり、どれが一番といった答えはありません。
要素の使い方や属性への理解など、より良いマークアップをする際には相応の知識が求められます。また、知識だけでなくユーザビリティやアクセシビリティといったことも考慮する必要があると思います。
誰にとって、何にとって良いマークアップなのか、マークアップをする際に考えてみてください。