ダークモード / ライトモードを任意で切り替える
ウェブコンテンツのダークモード対応は、必ずしもアクセシビリティの必須要件ではありませんが、ユーザー体験に寄った視点で考えると一定の意義はあると言えます。先の記事「ウェブコンテンツのダークモード対応」では、CSS のメディアクエリで prefers-color-scheme
を用いることで、ダークモード対応の実装ができることをご紹介しました。
@media (prefers-color-scheme: dark) {
// OS でダークモードが有効になったときのスタイルをここに記述。
}
これにより、ユーザーがデバイス (OS) の設定でダークモード / ライトモードのどちらを選択しているかに連動した形で、ウェブコンテンツの表示も自動的にダークモードまたはライトモードにすることができますが、Stéphanie Walter さん (アクセシビリティにも造詣が深い UX デザイナーで、Inclusive Design 24 (#id24) 2022 の登壇 でご一緒したのをきっかけにフォローさせていただいています) の記事「Dark mode & accessibility myth」によると、「ダークモード対応に際してはデバイス (OS) の設定に従うことをユーザーに強制しないこと」とあって、なるほどと思いました。
The solution is to give users the choice, if possible, offer the 2 modes and let them choose. Also, don’t force users to follow their operating system settings. Some people are okay with a dark OS, while being not able to read light to dark text.
(解決策は、ユーザーに選択肢を与え、可能であれば二つのモードを提供して選択させることです。また、ユーザーにオペレーティングシステムの設定に従うことを強制しないでください。ダークな OS 表示は大丈夫でも、ライトなテキストがダークなテキストになると読むことができない人もいます。)
以前に共訳した「インクルーシブデザインの原則」(執筆者 : Henny Swan、Ian Pouncey、Heydon Pickering、Léonie Watson) を改めて見ると、「利用者に制御させる」「選択肢を提供する」という原則が掲げられています。ダークモード対応に際して、単に prefers-color-scheme
を用いるだけでなく、ユーザーの任意で都度、モード (テーマ) を切り替えやすくしておくことは、これらの原則に照らし合わせても理にかなっていると言えるでしょう。
この記事では、ウェブコンテンツのダークモード / ライトモードを任意で切り替えるユーザーインターフェースについて検討してみたいと思います。観点としては「任意の設定をどう保持するか」「どのような形の UI にするか」の二つがあると考えています。
任意の設定をどう保持するか
ウェブコンテンツをダークモード / ライトモードのどちらで表示させるかの任意の設定は、一定期間、保持しておきたいものです。あるウェブページでダークモードに設定したにも関わらず、同じサイトの別ページにリンクで移動したらライトモードでの表示になってしまった...となると、ページ遷移のたびにユーザーの切り替え操作が発生することになり、ストレスになるからです。
この設定の保持には、ブラウザに備わっているデータ保管領域 (Web Storage といいます) を使うことができますが、「ローカルストレージ (Local Storage)」と「セッションストレージ (Session Storage)」という2種類の仕組みがあります。
ローカルストレージ
同一サイトにおいて、基本的に設定は永続的に保持されます。セッションが途切れても保持されるのが利点ですが、意図的にリセットしない限り保持され続けてしまうという側面もあります。ここに設定が保持されている限りは、デバイス (OS) のダークモード / ライトモードの設定が無視されてしまうため、場合によっては混乱を招くかもしれません。
ローカルストレージのリセットは、ブラウザの開発者ツールでできるものの、ブラウザのキャッシュの消去では (私が試した限りでは) できなさそうです。このため、ローカルストレージを使う場合は、ダークモード / ライトモードの切り替えに加えて、リセットする (デバイスの設定に合わせる) ための UI もあるとよいかもしれません。
セッションストレージ
同一サイトにおいて、セッションが続いている間、設定は保持されます。つまり、ブラウザのタブを閉じるなどしてサイトを離脱すると、設定がリセットされます。ユーザーが当該サイトに改めてアクセスするたびに、ダークモード / ライトモードの任意選択をし直す手間がかかるという側面はあるものの、デバイス (OS) のダークモード / ライトモードの設定に連動した表示を基本としつつ任意の切り替えが可能、というふるまいであるため、ユーザーのメンタルモデルとの齟齬は生じにくいかもしれません。
どのような形の UI にするか
ウェブコンテンツのダークモード / ライトモードを任意で切り替えるための UI としては、チェックボックス、ラジオボタン、ボタンがよく見られます。また、ボタンの場合、複数のボタンを並べてオプションを選択させるか、あるいは一つのボタンでトグルさせるか、というバリエーションもあります。
チェックボックス? ラジオボタン? ボタン?
たとえば、「ダークモードで表示する」というチェックボックス (<input type="checkbox">
) があると想定しましょう。チェックが入るとダークモード状態になり、チェックが外れるとライトモード状態になる、という具合です。一見よさそうですが、チェックボックスというのはラベルで記述されている事項の Yes / No を切り替える、という意味合いになるため、厳密には「ダークモードかライトモードか」ではなく「ダークモードにするかしないか」という選択になり、意味的にやや違和感があると個人的には思います。
ダークモード / ライトモードのオプションが並んだラジオボタン (<input type="radio">
) はどうでしょうか。意味的にはフィットしそうですが、サブミット (送信) ボタンを伴わずに、ラジオボタンの選択だけでデザインを変えてしまうインタラクションは (上述のチェックボックスもそうなのですが)、WCAG 2 の達成基準 3.2.2「入力時」の観点から慎重に考えたいところです。
ボタン (<button>
) はどうでしょうか。押したら即、ダークモード / ライトモードをアクティブにできる、という意味で妥当な UI なのかな、という気がします。
オプションを並べて選択させるか? 一つのボタンでトグルさせるか?
ダークモード / ライトモードの切り替えをボタン (<button>
) で提示する場合、オプション (ダークモード、ライトモード) を個別のボタンとして並べて選択させるか、あるいは一つのボタンだけにして押すたびにダークモードとライトモードの間をトグルさせるか、というバリエーションが考えられます。
オプションを個別のボタンとして並べる場合、選択肢が展開されて見えるので、その点ではわかりやすいと言えます。その一方で、ボタンを押したときにフィードバックがないケースも想定されるため (たとえば、ウェブページがダークモード状態のときに「ダークモード」ボタンを押す、など)、混乱の予防として、現在アクティブなボタンはあらかじめ明示的にしておくといった配慮があるとよいと思います。
一つのボタンでトグルさせる場合、UI がシンプルになるという利点があります。ダークモード / ライトモードの切り替えは、ウェブサイトのメイン機能ではないがゆえに極力コンパクトにしたい、といった与件にフィットしやすいでしょう。ボタンを押したときのフィードバックも必ずあるので (ライトモード状態でボタンを押せばダークモードになるし、ダークモード状態でボタンを押せばライトモードになる)、その点で混乱も少なそうです。
アイコンにするか? ラベルを記述するか?
ダークモード / ライトモードの切り替えボタンには、アイコンが用いられることがあります。ダークモードを示すのに「月」、ライトモードを示すのに「太陽」という具合です。
ボタンをアイコンのみで表現した場合、アイコンの意味するところに馴染みがないユーザーを結果的に排除してしまう可能性があるほか、特にトグルボタンの場合、フリップフロップ問題 (機能を切り替えるボタンの表現が「現在の状態」「ボタンを押した後の状態」のどちらを表わしているのかわかりにくい現象) を引き起こす恐れがあります。
ウェブサイトのメイン機能ではないがゆえに、ダークモード / ライトモードの切り替えボタンはできるだけコンパクトにまとめたいところではありますが、多くのユーザーに伝わるように、基本的にはラベルを記述するのがよいでしょう。一瞥したときの識別性を高めるためにアイコンを用いるのは有効ですが、アイコンのみでボタンを表現する場合は上述の懸念を踏まえて慎重に検討しましょう。
デモ
ダークモード / ライトモードを任意で切り替える UI を、CodePen で簡単なデモとして作ってみました。デフォルトではメディアクエリ (prefers-color-scheme
) によってデバイス設定に連動したダークモード / ライトモードの表示がなされ、ユーザーが設定を変更すると、ローカルストレージまたはセッションストレージに、その設定が保持されます。
ローカルストレージを用いる例
See the Pen ダークモード / ライトモードの任意の切り替え (Local Storage に設定を保持) by @caztcha (@caztcha) on CodePen.
ローカルストレージに設定を保持する場合、後でユーザーが「ダークモード / ライトモードの設定はデバイス設定に連動させたい」と思ったときのことを想定して、リセットボタンも配置するのがよいと思います。
ダークモード / ライトモードの任意の切り替えをトグルボタンにすると、リセットボタンとの兼ね合いで収まりが悪そうなので、ここでは「ダークモード」「ライトモード」「OS の設定を適用」という具合に、オプションを個別のボタンとして並べてみました。
各ボタンをアイコンにすることも検討できますが、ダークモード (月) やライトモード (太陽) はともかく、リセットを端的に示す馴染みのアイコンはなさそうなので、全体のバランスを鑑みてここではラベルを記述しています。
なお、「ボタンを押してもフィードバックがない」という混乱を予防するために、アクティブなボタンはそのようにスタイリングしておくとよいでしょう。併せて、スクリーンリーダーを併用するロービジョンのユーザーを想定して、どのボタンがアクティブであるかを音声でも知覚できるように、アクティブなボタンには aria-pressed="true"
が適用されるようにしています。
セッションストレージを用いる例
See the Pen ダークモード / ライトモードの任意の切り替え (Session Storage に設定を保持) by @caztcha (@caztcha) on CodePen.
セッションストレージに設定を保持する場合、リセットボタンを配置する必要がないので、よりシンプルな UI にできます。オプション (ダークモード / ライトモード) を個別のボタンとして並べてもよいですが、敢えてここでは UI を極力シンプルにする試みとして、トグルボタンを採用してみました。prefers-color-scheme
によるデバイス設定に連動した表示か、ユーザーが任意選択した表示か、を問わず、とにかくライトモード状態であればダークモードに切り替え、ダークモード状態であればライトモードに切り替えます。
ボタンのラベルは、フリップフロップ問題を避けるため、ボタンを押した後の状態、つまりボタンを押すことで何が起こるかを、動詞で記述しています。
併せて、スクリーンリーダーを併用するロービジョンのユーザーを想定して、ボタン領域をライブリージョン (aria-live="polite"
) にしています。ダークモード / ライトモードの切り替えに伴ってボタンのラベルが差し替わると、更新されたラベルが音声で読み上げられ、音声でもモード (テーマ) が切り替わったという手がかりを得ることができます。
当サイトでも試験的に、上記「セッションストレージを用いる例」の実装を用いて、ダークモード / ライトモードの切り替えができるトグルボタンをフッター領域に設置していますので、使ってみていただければと思います。