見出し画像

10年ものアプリのダークモード化プロジェクト、カラー設計の舞台裏

こんにちは、ニューズピックスのプロダクトデザイナー、吉川(よっしー)です。

先日、ニューズピックスアプリがダークモードに対応しました。以前からご要望を多くいただいており、昨年末から取り組みはじめ 9月にAndroid版リリース、10月にiOS版もリリースが完了しました。

2013年から今年で10周年を迎えたニューズピックスアプリ。その10年間の歴史を持つアプリをダークモード対応するためのカラー設計についてお伝えしていきたいと思います。

対応範囲

  1. アプリの全階層すべて適用する、ただし記事面は維持

  2. デフォルトで黒背景になっている箇所を維持する

10年もののサービスなので、コード上にはカラーパレットがいくつも残っていましたし、深い階層には共通化せずに作られた複雑な構造の画面があり、それらを網羅したトークンにしていく必要がありました。

ただ、記事面は外部記事を取り込んでおり自社でコントロールできないことや Web View であることから今回のダークモード化の範囲外です。

特定のセクションや画面は、目立たせるためあえて黒背景にしていました。それらが広告販売しているエリアであったり、番組再生画面など没入感を演出したりしており、既存の見た目を残しておくことになります。

必要な色の定義

グローバルカラーとは

まずはすべてのカラーの参照元となるパレットを用意します。各カラーを10段階の濃淡レベル別に用意し Blue50、Blue100…など、50から900までの値をつけて定義したものです。このパレットを、Web / App 共通で利用しているため「グローバルカラー」と呼んでいます。

セマンティックカラーとは

次に、ダークモードで意図通りの色に切り替わるよう個別のクラス名を追加します。これを「セマンティックカラー」といいます。

セマンティック(semantics)は意味やコンテキストを表す概念のことで、セマンティックカラーは特定のカラーが要素に与える視覚的な意味や情報を示すものです。例えば、赤色は通常警告やエラーを示すために使用され、ユーザーに注意が必要であることを伝えます。

次のように、色の組合せとそのクラス名を利用して既存のデザインで意図した通りに反転させることができます。

「ライトモード White(#FFFFFF) → ダークモード  Black(#000000) 」とした時
固有のクラス名をつけることで色の組合せパターンを増やせる

グローバルカラーを見直す

では、具体的な作成プロセスについてお伝えします。

グローバルカラーのパレットは、ライトモード、ダークモードで必要なコントラスト比を保てるように WCAG 2.1 を考慮します。

テキストが 18pt(日本語テキストでは22pt)以下では最低 4.5:1、それ以上のテキストもしくは画像類では最低 3:1 のコントラストを確保する

コントラスト (最低限): 達成基準 1.4.3 を理解する ー WCAG2.0

アクセントカラーの最適化

カラーの中心になる、ブランドカラーとCTAボタンに使用するアクセントカラーを決めて、それらを中心にパレットを展開します。

アクセントカラーは元々「#0062FF」を使用していて、コントラスト比を確認すると 5:1 ですが、かえってコントラストが強すぎるため「目が痛い」という意見もあったため彩度を落とし 4.5:1 に限りなく近づけた「#146AF5」に見直しました。なお、ブランドカラーは「#222222」のまま使用します。

参照しやすいベース色の設定

今回、一つのパレットでライト・ダーク共に参照できるようにしたため、それぞれの状態でコントラストを確保し、状態変化も考慮しておきたいです。

まず、「ベース色」(UI上、Primaryとして使用する色)は、状態変化で濃い色・淡い色どちらも使用する可能性があるため、パレット内の中間位置に配置しました。そこで、ライトモードでのベース色を600、ダークモードでのベース色を500とします。また隣接する色はSecondaryとして使用する可能性が高い色です。「600 はライトで 4.5:1 達成 かつ ダークで 3:1 を達成」、「500 はライトで 3:1 達成 かつ ダークで 4.5:1 達成」できるようにするとミニマムに一つのパレットで完結できました。

白文字がライトモード、黒文字がダークモードでのコントラストを表示

テキストはほとんどが 22pt 以下のため 4.5:1 をクリアしている 600 を使用し、アイコンやグラフなどの画像類は 3:1 を達成すればよいので 500 を使用する、というようにアクセシビリティ達成基準を判断する目安になり、瞬時に判断できるようになりました。

10段階のパレットのつくり方

10段階のパレットの展開は、HSBを微調整していくというかなり地味な方法でやっていきました。合わせて、Figmaの拡張機能や Material Design のパレット自動算出なども利用しつつベースカラーからのグラデーションの差分がバランス良くなっているかどうか、使い勝手がいいかどうか、色のトーンが揃っているかどうか、を見つつ少しずつ数値を変えていきます。

大体出来上がった後は、アプリの画面に当ててみて色のバランスがおかしくなっていないかなどをチェックします。

UIに当てて確認

グレーに透明色を採用

グレーは補足テキストやプレースホルダーなどUI上サブ的な役割で利用されるケースは多く、さまざまな背景色のパターンで配置される可能性があることを鑑みて、Amebaのブログ を参考にコントラスト比を確保しやすい透明色の選択を取りました。

透明色のクラス名は、GrayAlpha05(#222222/5%)、GrayAlpha40(#222222/40%)など、数字は「透明度」を表しています。

透明色、実際使用してみると便利なのですが Surface に用いる際は注意が必要です。Surface はいろんなレイヤーの表層になり、その下のレイヤーの色や見た目に影響を受ける可能性があるため、Surface には使用を避けた方が無難かもしれません。

セマンティックカラーを決める

グローバルカラーが大体決まったらセマンティックカラーを決めていきます。

既存の要素すべてに適応するために、粒度は細かくしすぎず汎用性の高さを優先しました。画面や色数が多いため、まずはゆるく定義 → 全画面に当てる → このルールに当てはまらない箇所をピックアップ → 修正 を繰り返して精度を高めていきました。

1.主要画面から色を抽出して簡単なルールを定義

まずは主要画面の色を抽出していきます。「最新の画面」と「古い画面」を数画面をピックアップし、その画面内で使用されている色と役割を書き出していきます。大体出てきたら、その時点で一度セマンティック名を定義し始めます。暫定ルールを画面に適応して漏れがないかを確認していきました。

つくったルールを当てていく

基本的にすべての要素は Surface の上に配置されるため、Surface を漏れなく洗い出すことでそれ以外の要素パターンの漏れが少なくなります。同じ白でも、ダークモードでは黒に反転するものもあれば、白のままになるケースが存在するため、それらを区別して命名していきます。

重複や漏れをチェック

2.残りの画面にルールを適用する

1 で作成したルールで、主要画面以外にも色当てを行っていきます。画面数が多いのでチームメンバーと手分けして行いました。

全画面色当ての進め方

※ 現在は Figma の Variablesの機能で、ルールを登録すると瞬時にライト・ダークの画面の見た目を切り替えることが可能。

適用できない箇所があればピックアップし、ルールに追加していきます。個別適用で今後使用していかない可能性のあるものは「Other / XX / XX」という命名にして後で消せるようにしておきました。

3.レビューを通じてブラッシュアップ

懸念点を抽出し切った後に、誰が見ても自然と理解できる状態にするために何度もデザインメンバーに共有しながら修正を行いました。その後、開発が始まってからも都合がつかない箇所が出れば都度修正して、アプリをカバーできるカラールールが出来上がりました。

App Token - UI Color

UIカラー適用表を用意して、使い方・使用例などをあらかじめ記載しておき他のメンバーが適用するときに悩まないようにしておきました。

UIカラー適用表

命名が一番難しい

役割や使用箇所などを加えた独自のクラス名を用意します。参照元となるカラーパレット(グローバルカラー)があり、役割別のクラス名(セマンティックカラー)をコンポーネントに適用する「2段階のカラー構造」となっています。

命名の基本構造は次のようにしました。

A) 役割 / B) 使用方法/ C) 優先度 or 状態

A) 役割

・Body = 画面内の最下層にあり全ての画面に存在するもの。デザインのアートボード色。
Surface = Bodyの上に乗るグループ要素の下地。
Object = アイコンやグラフなどのUIのグラフィック的要素。
Text = 文字情報。
Overlay = 画面全体または特定の要素を覆う一枚の透過要素。
Highlight = iOS版でSurfaceタップ時に、フィードバックとして変換される。
Gradient = グラデーション色。
NewsPicks = NewsPicksのブランドカラー。
ThirdParty = SNSサービスのブランドカラー。
Other = 使用箇所が限定的で役割名にするほど汎用的でないもの、または今後使用し続ける可能性が低いもの。

B) 使用方法

・Base = そのジャンルの中で基本的に使用する色。
Inverse = ライトモードでは白、ダークモードでは黒。
Outline = 白抜き。Surface が濃い色の時に乗る要素の色で、ダークモードでも白。
Accent = アクセントとなる色。ニューズピックスでは青または黒。
Information = お知らせで使用する色。
Caution = 警告を表す色。
Success = 成功、完了を表す色。
IrregBlack(OnIrregBlack) = 前提に記載した「特定のセクションで黒背景を用いている場合」の対処として、Surface に Irreg Black(Irregular Black)という命名を用意し、その上に乗る要素は On Irteg Black という命名でまとめ、イレギュラー的な使用方法であることがわかるようにしつつ後々廃止されたときにまとめて削除できるようにしたもの。

C) 優先度 or 状態

名前の3階層目は Default, Primary, Secondary, Selected, Disabled… などステータスや優先度で整理しています。その他、サードパーティのブランドカラーではブランド名、Overlay では濃淡を Weak, Strong で区別するなど、役割別に変えています。

完成!

通称: App UI Color - 全体像
拡大画像1
拡大画像2
Variables

運用のためにNotion作成

色当ての手順や間違えやすいポイントなどをドキュメントにしておきました。

セマンティックカラーは、あくまでダークモード対応のタイミングでは完成形ですが、デザインに変更があれば必要に応じて最新に更新しています。

さいごに

ダークモード化プロジェクトを振り返ると、大変な時期もありましたが結果的によいことばかりでした。

アプリ開発メンバーからは「これはXXX(色名)を当てておきました! デザイナーに確認しなくても色指定できるようになってめちゃくちゃいいです!」と喜びの声をもらえ、デザインの際も「この要素はこの色」などルールが決まっているので考えることが少なくなりかなり楽になっています。他にも、デザインの色適用の揺れがなくなり、コミュニケーションを減らして見た目の統一化ができるようになったことなど、メリットはたくさんあります。何より、カラーに役割名がついたことで、一貫した設計思想をつくるための制約になり、今後のアプリ開発にとって大事な転換点になったように思います。

(ちなみに、現在コメント欄の改善に取り組んでおり、コメント入力画面もダークモードに対応されるなので、アプリをご利用のみなさんは是非お楽しみに)

そして、設計の際に参考にしたドキュメントのリンクを貼っていますので、こちらもご参考ください!

設計の際に参考にしたドキュメント


サポートいただけたら一層頑張れそうです!