CSS と JavaScript のアクセシビリティのベストプラクティス
CSS と JavaScript も、適切に使えばアクセシブルなウェブ体験を可能にしてくれる可能性がありますが、誤用すると、大幅にアクセシビリティを悪化させることがあります。本記事では、複雑なコンテンツでもできる限りアクセシブルにすることを保証するために考慮すべき、CSS と JavaScript のベストプラクティスのいくつかを概観します。
前提知識: | 基本的なコンピューターの知識、HTML と CSS と JavaScript に関する基本的な理解、 アクセシビリティとは何かに関する理解。 |
---|---|
目的: | アクセシビリティを損わず、最大化するように、自身のウェブドキュメントで CSS と JavaScript を適切に使うことに慣れること。 |
CSS と JavaScript はアクセシブルなのか
CSS と JavaScript は、アクセシビリティに関して HTML と同じだけの直接的重要性があるわけではありません。ですが、それでも使い方によっては、アクセシビリティを高めることも損うこともありえます。別の言葉で言うと、自分の CSS と JavaScript の使い方によってドキュメントのアクセシビリティを台無しにしていないと確認するために、いくつかのベスト・プラクティスを考慮することが重要です。
CSS
CSS を見ることから始めましょう。
正しい意味づけと、ユーザーの予期すること
CSS を使って、どのような HTML 要素をどのように見せかけることも可能です。しかし、このことは、そうすべきだと意味しているわけではありません。「HTML: アクセシビリティの良き基本」という記事でしばしば述べたように、可能な場合にはいつでも、役割にふさわしい意味の要素を使うべきです。そうしないと、混乱を巻き起こしかねませんし、あらゆる人にとっての——とりわけ障碍のあるユーザーにとっての——使い勝手の問題を引き起こしかねません。正しいセマンティクスを使うことは、ユーザーの予期することと大いに関係があります。つまり、要素とは、その機能にしたがって、特定の見かけをしており特定のふるまいをするものであり、こうした通常の慣習をユーザーは予期するものなのです。
一例として、開発者が見出し要素を適切に使ってコンテンツをマークアップしていなかった場合には、スクリーンリーダーのユーザーは、見出し要素を通じてページの見通しを得ることができないでしょう。同様に、見出しのようには見えないように見出しにスタイルをつけた場合には、見出しは視覚的な目的を失ってしまいます。
結論として、ページ機能のスタイル設定をデザインに合わせて更新することはできますが、見た目や動作が期待通りにできなくなるほど変更しないでください。以下の節では、考慮すべき主な HTML 機能をまとめています。
「標準的」なテキストコンテンツ構造
見出し、段落、リスト——これらは、ページの中心的テキストコンテンツです。
<h1>見出し</h1>
<p>段落</p>
<ul>
<li>わたしのリストには</li>
<li>二つの項目があるよ。</li>
</ul>
ある種の典型的な CSS は以下のようなものかもしれません。
h1 {
font-size: 5rem;
}
p,
li {
line-height: 1.5;
font-size: 1.6rem;
}
なすべきことは以下の通りです。
- 文章を筋道立っていて判読可能で心地よく読めるものにするために、フォントサイズや行高や文字間隔などは、分別のあるものを選びましょう。
- 見出しが本文と区別できる (典型的には、デフォルトのスタイル付けと同様に、大きくて太い文字になっている) ようにしましょう。リストは、リストであるように見えるべきです。
- テキストの色は、背景色と十分に異なっているべきです。
より詳しくは、HTML テキストの基礎とテキストのスタイリングを参照してください。
強調したテキスト
囲んでいるテキストに対して特定の強調を与えるインライン・マークアップは、たとえば以下のようなものです。
<p>そのお湯は<em>とても熱いよ</em>。</p>
<p>
表面に集まる水滴は、<strong>結露</strong>と呼ばれます。
</p>
強調したテキストに対して、なんらかの単純な色付けを加えたいかもしれません。
strong,
em {
color: #a60000;
}
けれども、なんらかの目立つ方法で強調要素をスタイル付けする必要はめったにないでしょう。太字とイタリック体のテキストという標準的慣習はとても認識しやすく、そのスタイルを変更することは混乱を招きかねません。強調についてのさらなる情報は、強調と重要性を参照してください。
略語
略語、頭文字語、つまり頭文字で表したものを、その展開形と関連付けることを可能とする要素は、たとえば以下のようなものです。
<p>
ウェブコンテンツは、ハイパーテキストマークアップ言語、<abbr>HTML</abbr>を使ってマークアップされています。
</p>
この場合も、なんらかの単純な方法でスタイルを付けたいかもしれません。
abbr {
color: #a60000;
}
略語に対する公認のスタイル付けの慣習は、点線の下線です。そして、点線の下線から大きく逸脱するのは愚かしいことです。略語についてのさらなる情報は、略語を参照してください。
リンク
ハイパーリンク——ウェブ上の新たな場所に行く方法——は、たとえば以下のようなものです。
<p><a href="https://www.mozilla.org">Mozilla のホームページ</a>に来てくださいね。</p>
ある種のとても簡単なリンクのスタイル付けを以下に示します。
a {
color: #ff0000;
}
a:hover,
a:visited,
a:focus {
color: #a60000;
text-decoration: none;
}
a:active {
color: #000000;
background-color: #a60000;
}
標準的なリンクの慣習は、下線を引いた、標準状態とは異なる色 (デフォルトは青) と、そのリンクを以前にたどったことがある場合の別の色変化 (デフォルトは紫) と、そのリンクがアクティブになっている場合のさらに別の色 (デフォルトは赤) です。さらに、リンクにマウスオーバーした場合には、マウスポインターがポインターアイコンに変化しますし、リンクは、(たとえばタブキーを押して) フォーカスが当たったり、アクティブ化されたりすると、ハイライトされます。以下の画像は、Firefox でのハイライト (点線の輪郭線) と Chrome でのハイライト (青い輪郭線) の双方を示したものです。
ユーザーがリンクを操作したときにフィードバックを与えつづける限り、リンクのスタイル設定に創造性を持たせることができます。ポインターカーソルや輪郭線は、どちらもキーボード操作を使用する人にとってとても重要なアクセシビリティの補助になります。
フォーム要素
ユーザーがウェブサイトにデータを入力できるようにする要素であり、たとえば以下のようなものです。
<div>
<label for="name">お名前を入力してください</label>
<input type="text" id="name" name="name" />
</div>
form-css.html の例 (ライブも見てください) において、ある種の適切な例示的 CSS が見られます。
フォーム用に書く CSS のほとんどは、要素のサイズを変更したり、ラベルと入力欄を整列したり、それらをすっきり整えたりするためのものでしょう。
しかし、フォーム要素がフォーカスを受け取ったときに期待される視覚的なフィードバックから大きく逸脱するべきではありません。フォームのフォーカス/ホバー状態をスタイル設定することで、この動作をブラウザーでより一貫したものにしたり、ページデザインにうまく対応していただくことはできますが、完全に取り除いてはいけません。繰り返しになりますが、人々は何が起こっているのかを知るために、これらの手がかりに頼っているのです。
テーブル
表データを提示するためのテーブルです。
table-css.html の例 (ライブも見てください) において、テーブルの HTML と CSS の、適切で簡潔な例を見られます。
テーブル CSS は一般に、テーブルを自分のデザインによりうまく適合させて、見苦しさを減らすのに役立ちます。テーブルの見出しが目立つようにすること (普通は太字を使います)、異なる行同士が見分けやすいようにシマウマ的配色を使うことは、良い考えです。
色とそのコントラスト
自分のウェブサイト用のカラー・スキームを選ぶときには、テキスト (前景) の色が背景色と十分に差があることを確認してください。あなたのデザインはかっこよく見えるかもしれませんが、もし色盲などの視覚障碍のある人々がコンテンツを読めなかったら、まったく良いデザインではありません。
問題を起こさない程度に十分にコントラストが大きいかどうかを調べる簡単な方法があります。前景色と背景色を入力して調べることができる、コントラストのチェック用ツールが、オンライン上にいくつもあります。たとえば、WebAIM の Color Contrast Checker は、簡単に使えますし、色のコントラストに関して WCAG の基準に適合するためには何を行えば良いのかについて、説明もしてくれます。
メモ: コントラスト比を高くすることによって、光沢のある画面のスマートフォンまたはタブレットを使う人が陽光のような明るい環境でページを読みやすくもなるでしょう。
もう一つ別のコツは、標識や案内について色だけに頼らないことです。というのも、色だけに頼るのは、色が見えない人々にとってまったく良くないからです。必須のフォーム・フィールドを赤でマークする代わりに、たとえば、アスタリスクと赤でマークしましょう。
ものごとを隠す
視覚的なデザインでは、すべてのコンテンツを一度に表示させないことが要求される場合が多くあります。たとえば、Tabbed info box example の例 (ソースコードを参照) では、 3 つの情報パネルがありますが、それらをお互いの上に配置しており、クリックするとそれぞれの情報パネルを表示できるタブを設けています (これはキーボード・アクセシブルでもあります。つまり、情報パネルを選ぶのに、クリックする代わりに、タブキーとエンターキー / リターンキーとを使うこともできます)。
スクリーンリーダーのユーザーは、このようなことは気にしません。彼らは、ソースの順序が意味を持ち、すべて取得することができれば、コンテンツに満足します。絶対位置指定(この例で用いている)は、スクリーンリーダーがコンテンツを取得するのを止めないので、視覚的効果のためにコンテンツを隠す最良のメカニズムの 1 つと一般的に考えられています。
一方で、 visibility
:hidden
も display
:none
も、スクリーンリーダーからコンテンツを隠してしまうので、使うべきではありません。もちろん、スクリーンリーダーからこのコンテンツを隠したいと思う然るべき理由がない限りは、ということですが。
メモ: Invisible Content Just for Screen Reader Users には、この話題をめぐる多くのさらに有用な詳細があります。
ユーザーがスタイルを上書きできることを受け入れる
ユーザーは、自分のカスタムスタイルでスタイルを上書きできます。たとえば以下のとおりです。
- Firefox において手動でスタイルを上書きする方法を含む有用なガイドとしては、 Sarah Maddox の How to use a custom style sheet (CSS) with Firefox を参照のこと。
- 拡張機能を使ってスタイルを上書きするのは、おそらくもっと簡単です。たとえば、 Stylus 拡張機能が Firefox で利用でき、 Stylish (Chrome) と同等のものです。
ユーザーは様々な理由から、スタイルの上書きを行うかもしれません。視覚障碍のあるユーザーは、すべての訪問先のウェブサイトでテキストを大きくしたいかもしれませんし、あるいは、重度の色覚障碍のあるユーザーは、すべてのウェブサイトを自分でも見やすい高コントラストの色にしたいかもしれません。その必要性がいかなるものであるにせよ、(スタイルの上書きという) この事態にはなじんでおくべきですし、そうした変更が自分のデザインにおいてうまく機能するように、自分のデザインを十分に柔軟なものとしておくべきです。例として、主なコンテンツ領域がより大きいテキストを扱えて (その領域は、全体を見られるようにスクロールし始めるかもしれません)、ただ隠したり完全に破綻したりしないように、気をつけると良いでしょう。
JavaScript
JavaScript も、その使い方によっては、アクセシビリティをぶち壊しにする可能性があります。
モダンな JavaScript は強力な言語です。簡単なコンテンツと UI の更新から、本格的な 2D ゲームや 3D ゲームに至るまで、近頃では JavaScript を使ってとても多くのことができます。すべてのコンテンツがすべての人々にとって 100% アクセシブルであるべきだ、といった決まりはありません。自分にできることをし、自分のアプリをできる限りアクセシブルにする必要があるだけなのです。
単純なコンテンツと機能——たとえば、テキスト、画像、テーブル、フォーム、関数を起動する押しボタン——は、まず間違いなく、アクセシブルにするのが簡単です。HTML: アクセシビリティの良き基本 の記事で見たように、考慮すべき重要な事項は以下のとおりです。
- 正しい目的に正しい要素を使うことが良い意味づけです。たとえば、見出しと段落を使い、
<button>
要素と<a>
要素を使うようにします。 - コンテンツを、テキストとして利用可能にすること——テキスト・コンテンツや、フォーム要素に対する適切なテキストラベルの形で、直接的に利用可能とするか、あるいは、たとえば画像に対する alt テキストのような代替テキストとして、利用可能にすること。
機能が欠けているところに機能を盛り込むように JavaScript を使う方法の例も見ました (キーボードアクセシビリティを呼び戻すように盛り込む を参照)。この例は理想的ではありません。実際、ただふさわしい要素をふさわしい役割に使うべきなのです。が、この例は、使われるマークアップを何らかの理由で統制できない状況においては、こうしたこともあり得るのだと示しています。非意味的な、 JavaScript で実装されたウィジェットについて、アクセシビリティを向上させる別の方法は、WAI-ARIA を用いて追加的な意味づけをスクリーンリーダーのユーザーに提供することです。次の記事では、このことも詳しく扱います。
3D ゲームのような複雑な機能は、アクセシブルにするのがそう簡単ではありません。WebGL を使って作られた複雑な 3D ゲームは <canvas>
要素上に描画されるでしょうが、今のところ <canvas>
要素には、重度の視覚障碍のあるユーザーが利用できるように代替テキストもしくは他の情報を提供する手段がないのです。 そうしたゲームは、こうした人々のグループを実際に主要な対象者の一部としてはいないのだ、というのはもっともです。それに、そのゲームを、目の見えない人々にとって 100% アクセシブルにせよ、と期待するのも不合理でしょう。しかし、マウスを使わないユーザーにとって利用可能なようにキーボードコントロールを実装することや、 色覚障碍のある人々にとって利用可能なようにカラー・スキームに十分なコントラストを持たせることならできるでしょう。
過度の JavaScript にともなう問題
JavaScript に頼りすぎると、しばしば問題が起きます。ときどき、何でもかんでも JavaScript で行われたウェブサイト—— HTML が JavaScript により生成され、CSS が JavaScript により生成され、といった調子のもの——を見るでしょう。これには、あらゆる種類のアクセシビリティの問題および付随するその他の問題があり、お勧めできません。
ふさわしい役割にふさわしい要素を使うのと同様に、ふさわしい役割にふさわしい技術を使っていることも確認しておくべきです! JavaScript で実装されたキラキラの 3D 情報ボックスが必要なのか、あるいは、プレーンな古めかしいテキストでも用が足りそうか、ということについて注意深く考えてください。複雑で非標準的なフォーム・ウィジェットが必要なのか、あるいは、テキスト入力でも用が足りそうか、ということについて注意深く考えてください。そして、とにかく可能な場合に JavaScript を使ってすべての HTML コンテンツを生成する、などということはしないでください。
ひかえめに保つこと
コンテンツを作成する際には、控えめな JavaScript を念頭に置くべきです。控えめな JavaScript の考えは、 JavaScript は可能な限り機能を強化するために使用すべきであり、完全に組み込むべきでないということです。基本的な機能は JavaScript なしで動作するのが理想的ですが、常にこのオプションがあるわけではないことは理解しています。しかし繰り返しますが、その大部分は可能な限りブラウザー内蔵の機能を使用することです。
ひかえめな JavaScript の適切な使用例には、次のものが含まれます。
- クライアント側のフォーム検査を提供すること。これは、サーバーがデータを調べるのを待つ必要なしに、フォーム入力にともなう問題をユーザーに対して素早く警告してくれます。もしクライアント側のフォーム検査が利用できなくても、フォームは依然として動作するでしょうが、検査は遅くなるかもしれません。
- キーボードのみのユーザーにとって操作可能な 、HTML の
<video>
用のカスタムコントロールを提供すること。それとともに、JavaScript が利用できない場合にその動画にアクセスするのに使える、動画への直接リンクも提供すること(ほとんどのブラウザーでは、既定の<video>
ブラウザーコントロールは、キーボードで操作可能ではありません)。
一例として、やっつけ仕事のクライアント側のフォーム検査の例を書きました。form-validation.html を参照してください(ライブデモも参照してください)。ここでは、単純なフォームが見えます。一方または双方のフィールドを空にしたままフォームを送信しようとすると、送信が失敗し、エラーメッセージボックスが現れて、何が間違っているのかを教えてくれます。
この種のフォーム検証は控えめで、 JavaScript が利用できなくてもフォームを全く問題なく使用することができます。また、良識あるフォーム実装であればサーバー側の検証も有効にします。悪意のあるユーザーが(例えば JavaScript をブラウザーでオフにすることで)クライアント側の検証を回避することはあまりにも簡単にできるからです。クライアント側の検証は、エラーを報告するのに実に有益です。ユーザーは、サーバーとのやり取りや ページの再読み込みを待つ必要がなく、自分が犯した間違いを即座に知ることができます。これは間違いなくユーザビリティの向上です。
メモ: この単純なデモではサーバー側の検査を実装していません。
このフォーム検査も、とてもアクセシブルにしておきました。 <label>
要素を用いて、フォームラベルがそのラベルの入力欄に曖昧な点なしに紐付けられるようにして、それによってスクリーンリーダーがラベルを一緒に読み上げられるようにしました。
<label for="name">名前を入力してください:</label>
<input type="text" name="name" id="name" />
フォームが送信されるときにだけ検査をしています。これは、UI をあまりに頻繁に更新しないようにするため、そして、スクリーンリーダーのユーザーを (また、おそらくは他のユーザーも) 潜在的に混乱させることがないようにするためです。
form.onsubmit = validate;
function validate(e) {
errorList.innerHTML = "";
for (let i = 0; i < formItems.length; i++) {
const testItem = formItems[i];
if (testItem.input.value === "") {
errorField.style.left = "360px";
createLink(testItem);
}
}
if (errorList.innerHTML !== "") {
e.preventDefault();
}
}
メモ: この例では、絶対的な位置指定を用いてエラーメッセージボックスを隠したり見せたりしています。 visibility や display などの他の方法を使っているわけではありません。なぜなら、絶対的な位置指定は、スクリーンリーダーがコンテンツを読めるようにしておくことを妨げないからです。
現実のフォーム検査は、これよりもっと複雑でしょう。入力された名前が実際に名前のようであることを確認したいかもしれませんし、入力された年齢が実際に数値であり、かつ現実的である (たとえば、負数ではなく、4 桁でもない、など) ということを確認したいかもしれません。ここでは、各入力フィールドに値が入れられたことを確認する (if (testItem.input.value === '')
という) 簡単な検査を実装しただけです。
検査が実行された際に、もしテストに通れば、フォームが送信されます。もしエラーがあれば (つまり if (errorList.innerHTML !== '')
であれば)、 (preventDefault()
を用いて) フォームの送信を中止し、生成されたエラーメッセージをすべて表示します (下記参照)。この仕組みは、エラーが存在するときにだけエラーが表示される、ということを意味します。そしてそのことは、使い勝手のうえで、より良いことなのです。
フォームが送信される際に値が入れられていない入力それぞれについて、リンクを有するリスト項目を作って、それを errorList
に挿入しています。
function createLink(testItem) {
const listItem = document.createElement("li");
const anchor = document.createElement("a");
const name = testItem.input.name;
anchor.textContent = `${name} field is empty: fill in your ${name}.`;
anchor.href = `#${name}`;
listItem.appendChild(anchor);
errorList.appendChild(listItem);
}
各リンクは二つの役割を果たします。つまり、何のエラーなのかを教えてくれますし、さらに、そのリンクをクリックする / アクティブにすると問題の入力要素へ直接ジャンプして入力を訂正できるようになっています。
さらに、ソース順における先頭に errorField
を置いてあります (CSS を使って、UI 上では別のところに配置してありますが)。これが意味することは、ユーザーが、ページの最初に戻ることで、自分のフォーム送信でまさに何が間違っているのかも分かるし、問題の入力要素にも行ける、ということです。
最後の注記ですが、このデモではいくつか WAI-ARIA 属性を使いました。ページリロードをともなわずに絶えず更新するコンテンツの領域が引き起こすアクセシビリティの問題を、解決する手助けとするためです (スクリーンリーダーは、デフォルトでは、こうしたコンテンツを拾い上げたり、ユーザーにこうしたコンテンツを警告したりはしないでしょう)。
<div class="errors" role="alert" aria-relevant="all">
<ul></ul>
</div>
もっと詳細に WAI-ARIA を扱う次の記事で、これらの属性について説明します。
メモ:
HTML フォームには required
属性や min
/minlength
属性や max
/maxlength
属性のような組み込みの検査の仕組みがあること (より詳しくは、<input>
要素のリファレンスを参照) について考える読者もおそらくいることでしょう。このデモでは、結局これらの属性は使いませんでした。これらの属性についてのブラウザー間での対応が当てにならないからです(たとえば IE10 以上のみでの対応だったり、Safari が対応していなかったりします)。
メモ: WebAIM の Usable and Accessible Form Validation and Error Recovery は、アクセシブルなフォーム検査についてのさらに有用な情報をいくつか教えてくれます。
JavaScript のアクセシビリティのその他の問題
JavaScript で実装しつつアクセシビリティについて考えるときに意識すべきことは他にもあります。見つけ次第、さらなる事項を追加するつもりです。
マウスに特有のイベント
お気づきのとおり、ユーザーとの対話的動作のほとんどは、イベントハンドラーを使ってクライアント側の JavaScript で実装されます。イベントハンドラーによって、特定のイベントが起きるのに応じて関数を実行できるようになります。ある種のイベントには、アクセシビリティの問題があるかもしれません。読者が見つけることになるであろう主な例は、mouseover や mouseout や dblclick などの、マウスに特有のイベントです。これらのイベントに応じて動作する機能は、キーボードコントロールのような他の仕組みを用いていると、アクセシブルではなくなります。
こうした問題を軽減するには、これらのイベントと、他の手段によってアクティブにできるような類似のイベントとの二重化をすべきです (いわゆるデバイスとは独立なイベントハンドラーです)。focus と blur は、キーボードのユーザーに対するアクセシビリティを提供してくれることでしょう。
これが有用になりうる場合においてハイライトを行う事例を見てみましょう。ときにはサムネイル画像を設けたいことがあります。そのサムネイル画像にマウスオーバーした場合またはフォーカスが当たった場合に、その画像の、より大きなバージョンを表示するものです (電子商取引の商品カタログ上で見受けられるようなものです)。
とても簡単な例を作りました。これは、mouse-and-keyboard-events.html で見られます (ソースコード も参照)。このコードは、ズームインした画像を表示する関数と隠す関数という、二つの関数を特徴としています。これらの関数は、これらの関数をイベントハンドラーとして設定する以下の行により実行されます。
imgThumb.onmouseover = showImg;
imgThumb.onmouseout = hideImg;
imgThumb.onfocus = showImg;
imgThumb.onblur = hideImg;
最初の 2 行は、それぞれ、マウスポインターがサムネイル上にホバーしたときと、マウスポインターがサムネイル上にホバーするのをやめたときに、関数を動作させます。しかしこれだと、ズームしたビューにキーボードを通じてアクセスすることはできません。それをできるようにするために、後ろの方の 2 行を含めました。この 2 行は、画像にフォーカスが当たったときと、画像からフォーカスが外れた (フォーカスが停止した) ときに、関数を動作させます。こうしたことは、タブキーで画像上に移動することでできることです。なぜなら、画像に tabindex="0"
を含めておいたからです。
click クリックイベントは興味深いものです。マウス依存のように聞こえる名前ですが、ほとんどのブラウザーは、フォーカスの当たっているリンクまたはフォーム要素上でエンター/リターンが押された後に、あるいは、そうした要素がタッチ画面装置上でタップされたときに、 onclick イベントハンドラーを起動します。しかしこれは、 tabindex を用いて、既定ではフォーカス可能ではないイベントがフォーカスを持つようにしていると、既定のままではうまく機能しません。そうした場合では、まさにそのキーが具体的にはいつ押されたのかを検出する必要があります (キーボードアクセシビリティを呼び戻すように盛り込む を参照)。
スキルをテストしましょう
この記事の終わりまで来ましたが、最も重要な情報を覚えていますか?先に進む前に、スキルテスト: CSS と JavaScript のアクセシビリティ を参照して、この情報を覚えているかどうかを確認しましょう。