もりけん塾の課題16でタブの実装にチャレンジしています。
今までタブ切り替えでアクセシビリティに対応しないとと思いつつ、
できていなかったので、実装したまとめです。
WAI-ARIAとは?
WAI-ARIAはWeb Accessibility Initiative Accessible Rich Internet Applicationsの略で、
W3Cが取り決めた仕様です。
HTMLだけでは足りないアクセシビリティの機能を属性を使って補完します。
ちなみにWAI-ARIAはウェイアリアと読むそうです。
アクセシビリティを向上させる3つの機能
WAI-ARIAには3つの機能は提供されています。Role(ロール)、Property(プロパティ)、ステート(State)です。
Role(ロール)
Roleを指定する要素(タグ)が、なんの役割を持つのかを定義します。
今回の課題はタブの切り替えだったので、
下記のように利用しました。
<ul class="tab-list" role="tablist">
<li role="presentation">
<button role="tab">ニュース</button>
</li>
<li role="presentation">
<button role="tab">経済</button>
</li>
</ul>
<ul>が持つ本来の意味はリストなので、タブとはわかりません。
そこでrole属性を使い、role=”tablist”としてタブのリストだよと役割も持たせました。
<button>にもタブだよとrole=”tab”で役割を持たせていいます。
Property(プロパティ)
Propertyは追加の意味や用途を追加登録するために「arai-***」を使って性質を登録します。
今回の課題ではタブの部分とタブのコンテンツの部分を紐付ける必要があったため、
aria-controlsとidで紐付けを行いました。
タブのaria-controls=”panel-1″とタブのコンテンツid=”panel-1″が紐づく形です。
<button id="tab-1" aria-controls="panel-1" role="tab" tabindex="0">
ニュース
</button>
<!--タブのコンテンツ部分-->
<div id="panel-1" aria-hidden="false" aria-labelledby="tab-1" role="tabpanel">
<ul class="news-list">
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a><span class="icon-new">new</span><span class="comment-count">300</span>
</li>
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a><span class="comment-count"></span>
</li>
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a>
</li>
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a>
</li>
</ul>
</div>
State(ステート)
Stateは現在の特定の状態を「arai-***」を使って示す特別なプロパティです。
先程のPropatyとの違いはPropatyは不変なもの、(一度設定したら変更しない)に対し、StateはJavaScriptを用いて変更することができます。
今回作成したタブではaria-selectedを使用し、選択されているタブにはtrueをそれ以外はfalseを設定しています。それ以外にもタブのコンテンツ部分にはaria-hidden=”true/false”を用いて表示・非表示も操作しています。
<ul class="tab-list" role="tablist">
<li role="presentation">
<button role="tab" aria-selected="true">ニュース</button>
</li>
<li role="presentation">
<button role="tab" aria-selected="false">経済</button>
</li>
</ul>
注意が必要な暗黙のARIA
HTMLにはもともと持っているrole(定義)が存在しています。
WAI-ARIAはHTMLでは補えない部分を後から補完するためのものなので、
重複しないように設定する必要があるようです。
例えばリストやチェックボックスにはもともとリスト、チェックボックスと既に定義されています。
<!--role=checkbox-->
<input type="checkbox" name="" id="">
<!--ul role=list,li role=listitem-->
<ul>
<li>ulはrole=listがもともと定義されている</li>
<li>liはrole=listitemがもともと定義されている</li>
</ul>
既存のroleについては下記にまとめられています。
今回タブの構造をulを使って実装しました。
<ul class="tab-list" role="tablist">
<li>
<button role="tab" aria-selected="true">ニュース</button>
</li>
<li>
<button role="tab" aria-selected="false">経済</button>
</li>
</ul>
li要素の中にあるbuttonにrole=tabを設定し、liのもともとのrole=listitemが余計になってしまいました。
カテゴリーをリストのように並べたかったのですが、リストとタブボタンは違うので、
既存のroleを無効にするためliにrole=presentationを指定します。
<ul class="tab-list" role="tablist">
<li role="presentation">
<button role="tab" aria-selected="true">ニュース</button>
</li>
<li role="presentation">
<button role="tab" aria-selected="false">経済</button>
</li>
</ul>
実際に実装したコード
調べながら実装した結果、このようになりました。
<div class="news-category">
<ul class="tab-list" role="tablist">
<li class="tab-list-item" role="presentation">
<button
id="tab-1"
class="tab-button js-tabButton"
aria-selected="true"
aria-controls="panel-1"
role="tab"
tabindex="0">
ニュース
</button>
</li>
<li class="tab-list-item" role="presentation">
<button
id="tab-2"
class="tab-button js-tabButton"
aria-selected="false"
aria-controls="panel-2"
role="tab"
tabindex="-1">
経済
</button>
</li>
<li class="tab-list-item" role="presentation">
<button
id="tab-3"
class="tab-button js-tabButton"
aria-selected="false"
aria-controls="panel-3"
role="tab"
tabindex="-1">
エンタメ
</button>
</li>
<li class="tab-list-item" role="presentation">
<button
id="tab-4"
class="tab-button js-tabButton"
aria-selected="false"
aria-controls="panel-4"
role="tab"
tabindex="-1">
スポーツ
</button>
</li>
<li class="tab-list-item" role="presentation">
<button
id="tab-5"
class="tab-button js-tabButton"
aria-selected="false"
aria-controls="panel-5"
role="tab"
tabindex="-1">
国内
</button>
</li>
</ul>
</div>
<div class="news-contents">
<div
id="panel-1"
class="news-area category_illust"
aria-hidden="false"
aria-labelledby="tab-1"
role="tabpanel">
<ul class="news-list">
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a><span class="icon-new">new</span><span class="comment-count">300</span>
</li>
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a><span class="comment-count"></span>
</li>
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a>
</li>
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a>
</li>
</ul>
</div>
<div
id="panel-2"
class="news-area category_illust"
aria-hidden="true"
aria-labelledby="tab-2"
role="tabpanel">
<ul class="news-list">
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a><span class="comment-count"></span>
</li>
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a><span class="comment-count"></span>
</li>
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a>
</li>
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a>
</li>
</ul>
</div>
<div
id="panel-3"
class="news-area category_illust"
aria-hidden="true"
aria-labelledby="tab-3"
role="tabpanel">
<ul class="news-list">
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a><span class="comment-count"></span>
</li>
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a><span class="comment-count"></span>
</li>
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a>
</li>
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a>
</li>
</ul>
</div>
<div
id="panel-4"
class="news-area category_illust"
aria-hidden="true"
aria-labelledby="tab-4"
role="tabpanel">
<ul class="news-list">
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a><span class="comment-count"></span>
</li>
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a><span class="comment-count"></span>
</li>
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a>
</li>
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a>
</li>
</ul>
</div>
<div
id="panel-5"
class="news-area category_illust"
aria-hidden="true"
aria-labelledby="tab-5"
role="tabpanel">
<ul class="news-list">
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a><span class="comment-count"></span>
</li>
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a><span class="comment-count"></span>
</li>
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a>
</li>
<li class="news-item">
<a href="" class="news-link">総合ニュース Topic01</a>
</li>
</ul>
</div>
</div>
まとめ
最初は参考を読み込むだけではなかなかPropatyやStateの使い方が分からなかったですが、
実際にタブに組み込んでみて違いがわかりました。
コードは書かないと理解できないですね。
属性はCSSにも使えるので、タブの見た目の切り替えのJSやCSSがスッキリかけたのでコードの量を減らすこともできました。
今後もアクセシビリティを考えたサイト制作に取り組んでいきたいと思います。
参考にしたサイト
もりけん塾
現在もりけん塾に参加し、JavaScriptの課題に取り組んでいます!
素敵な先生と塾生に囲まれて切磋琢磨な日々を送っています。
森田先生のBLOG:無骨日記
Twetter:@terrace_tech