View Transitions API で画面遷移アニメーション

View Transitions API とは

デモ

  1. ひとつのHTMLファイル内の要素をアニメーションさせる
  2. 異なるHTMLファイルの遷移間をアニメーションさせる

のふたつが大きく分けて View Transitions API では実現できますが、今回は 2. の異なるHTMLファイル間のデモです。

ics-creative/230510_view_transitions_api を触りながら少し改変してみました。( GitHub

Chromeで確認。URLが変更されブラウザバックでも動作しました。

作成の流れ

  • HTML
    • トップページ( index.html )、詳細ページ( cat_*.html )を作成。
    • 互いのページに同じ画像を使用するようにしておく。
  • JavaScript
    • こちらもChrome、Edgeのみサポートの Navigation API を使ってページ遷移を感知
    • ページ間のアニメーションをさせたい要素に対して style.viewTransitionName を設定
      • 今回は cat-anime
    • 遷移動線のパターンによって <html> にクラスを付与
      • 今回の例
        • トップページから詳細ページ( from-index, to-detail
        • 詳細ページからトップページ( from-detail, to-detail
        • 詳細ページから詳細ページ( from-detail, to-detail
    • 遷移先のDOMを取得し更新
  • CSS
    • アニメーションさせる要素に対して view-transition-name: cat-anime; を指定
    • トップ、詳細で画像のサイズを指定
      • 画像の拡縮アニメーションは自動的に行われる
    • その他のDOMのアニメーションを設定
      • ::view-transition-old , ::view-transition-new 疑似要素に対して先ほどの遷移動線パターンで付与したクラスを使用
        • 今回の例
          • html.from-index.to-detail::view-transition-old(root) { ... }

(参考)Safariの場合

未サポートのブラウザでは遷移時のアニメーションは無くなりますが、遷移自体は可能です。

所感

  • 「簡単に実現できる」とは言ったものの、ブラウザAPIとしてサポートされてライブラリ等が必要ないだけで実装内容によっては簡単ではない
  • pjaxでは遷移時に更新する/しないDOMを指定したりしてたが、遷移動線のパターンを網羅しながらやるという所は考え方的には似てる気がした
  • 今回のデモの場合ページタイトルは遷移時に切り替わらないため、headの中身は自前で切り替えが必要そう
  • 「ひとつのHTMLファイル内の要素をアニメーションさせる」方法は、例えば画像ライトボックスが実装できるため全モダンブラウザでサポートしたら本格的に使うことになりそう

参考記事

【読書メモ】ウェブ・インクルーシブデザイン ─ Webのアクセシビリティとインクルージョンを実現するための実践ガイド

目次・概要

著者はレジーン・M・ギルバート氏。UXデザイナーであり、国際アクセシビリティプロフェッショナル協会が認定するアクセシビリティの専門家。
もともと障害を持つご家族と暮らした影響から、アクセシビリティに興味を持ちガイドラインを整えたり、トレーニングを実施されているとのこと。

この本では、主にデザイン要件の中に最初からアクセシビリティを組み込んでおけば、アクセシビリティとデザインは継ぎ目のないプロセスになるというアイデアが紹介されています。

インクルーシブデザインとは

インクルーシブは「多様な人を包摂する」こと。
インクルーシブデザインとは「民間・公共を問わずあらゆるサービスに多様なユーザーがアクセスし、理解し、操作できるようにする」こと。

日本の状況

さまざまな疾患・障害を持つ人が日本では964万人、割合にすると約7.6%の人が何かしら障害を抱えて生活し、さらにその中の95%の人が入院をせずに生活している。

障害者の表記

障害の原因を個々人の機能障害や他社との差異に置くのではなく、社会のあり方にあるとする考えに基づくため本書内では「障害者」と表記。

ポイント

気になった点のメモです。

第1章 アクセシビリティを考慮したデザイン

アクセシビリティとインクルーシブデザイン

アクセシビリティ」とは、誰もが抵抗なくアクセスできるようにすること。(性質)
「インクルーシブデザイン」とは、すべての人のためにプロダクトをつくること。(方法論)

障害の社会モデルと医学モデル

本書では「社会モデル」を前提。

  • 社会モデル
    • 社会のあり方に障害の原因があるとする考え方。
    • 障害者の人生の選択を制限する障壁(バリア)を取り除くことを検討する。
  • 医学モデル
    • 個人の機能障害や他社との差異に原因があるとする考え方。
    • 心身の機能障害や差異は医療その他の治療によって「治す」か、交換により回復すべきと考える。

5W1H

イデアが浮かんだら、形にする前に5W1Hを考える。

  • Who:あなたのプロダクトを使うのはですか?
  • What:彼らはなにをしていますか?
  • Where:彼らはどこでそれを使いますか?
  • When:彼らはいつそれを使いますか?
  • Why:彼らはなぜそうするのですか?
  • How:彼らはどうやってそれを使っていますか?

さまざまな人が恩恵を受ける

障害を障害抱える人のためにデザインをすれば、状況によって制限を感じる人もその恩恵を受ける。
たとえば、片腕の人のためにデザインされたデバイスは、手首を一時的に怪我している人や幼児を腕に抱えた新米の親にも効果的に使ってもらえる。
これを「ペルソナ・スペクトル」と呼ぶ。

第2章 アクセシビリティ、コンテンツ、HTML、JavaScriptCSS、そしてARIAの世界

Webアクセシビリティ

Webアクセシビリティとは「Webサイト、ツール、およびテクノロジーが、障害を持つ人たちが使えるように設計され、開発されていること」とW3Cでは定義されている。
つまり、障害を持つ人たちが次のことをできる状態にあること。

  • Webを認識して理解し、Web上を自由に動き回り、必要なインタラクションをする
  • Webに貢献する。

HTMLのベストプラクティス

  • コンテナ要素はレイアウトのみに使う
    • <div><span> のような要素はレイアウト専用。
  • 他のHTML要素を本来の意図通りに使う
    • <header>, <nav>, <main>, <article>, <aside>, <footer>
  • ヘッダー
    • h1は1ページにつき1個で、ページタイトルと一致させる
    • 階層を上げるときはスキップ不可、下げるときはスキップ可
      • 例:h1, h2, h3, h2, h3, h4, h2, h3, h4

ボタン、モーダル、フォーカスなどの動作はJavaScriptで制御できるが、アクセシビリティの観点からはJavaScriptの仕様はある程度に限定にするのが理想で、セマンティックHTMLとCSSに比重を置く。

第3章 わずらわしい=おそらくアクセシブルではない

よりアクセシブルなプロダクトをつくるためにできること

  • 行動を促す明確な呼びかけ
    • ボタンやリンクをしっかり区別して見せる
  • 明快なレイアウト
    • サイトのユーザーにとってももっとも論理的なレイアウトにする
  • タイポグラフィ
  • フィルター適用の昨日
    • サイト上でユーザーがフィルターをコントロールできるようにする
  • 明快なナビゲーション
    • 次にどこへ進めば良いかをはっきり示す
  • 適切で関連のあるコンテンツ
    • コンテンツがレイアウトと衝突していないことを確認する
  • コンテンツへのジャンプ
    • ユーザーが「コンテンツへジャンプ」できるようにする
  • 適切なコントラスト

第4章 コンプライアンスアクセシビリティ

WCAGの「POUR」

2018年にアップデートされたWCAGの骨子は「POUR」という呼び名で知られる四原則でできている。

  • 知覚可能(Perceivable)
  • 操作可能(Operable)
  • 理解可能(Understandable)
  • 堅牢性(Robust)

POURの概要と実例

第5章 未来のためのビジョンを描く:アクセシビリティのためのデザイン戦略

デザインフレームワークを用いる

インクルーシブデザインの実現に向けた取り組みは、誰のためにつくろうとしていて、誰を排除してしまう可能性があるかをはっきりさせるところからはじまる。
そのためプロジェクトのスタート時点で、デザイン戦略(例えば著者が作成したEVVCCフレームワーク)を用いることがプロダクトの生産や開発の肝となる。

  • 共感(Empathy)
    • 同僚や顧客が必要とすることを理解し、応じる能力
  • 価値(Value
    • 組織の価値観、目標、同僚や顧客に対する説明責任が共有され一致していること
  • ビジョン(Vision
    • 組織の規範のおおもとにあって中核をなす共通の信念
  • コンテキスト(Context)
    • プロジェクト、人、緊急性、リスク、ベネフィット、およびさまざまな状況要因に関連する課題
  • コミュニケーション(Communication)
    • 対話やプロダクトのニーズ、目標、意図、フィードバックなどの表明

Airbnbが採用する「Another Lens」

AirbnbではAnother Lensというツールを採用している。
https://miro.medium.com/v2/resize:fit:2000/format:webp/1*g_GF91BxDTL3mcpFi_W8qg.jpeg

これは偏った視点に対峙し、思慮深く、インクルーシブなものづくりをできるようになるために作られたツールで、次の基本原則がある。

  • バイアスのバランスを取る
    • あなた自身の生まれついてのもの、育ててきたもの、行動に関係するもの、さまざまなレンズがあり、誰もがレンズを持っている。自分が持っていないレンズについても考える
    • 確証バイアスを常に意識し、あなたが取り組むことがどんな不均衡をもららす可能性があるかを考える
  • 逆を考える
    • 「逆を考える」ことが確証バイアスの克服に直接的な影響がある
    • 同類性をもった人だけでなく、まったく違う視点を持つ人にも意見を聞く
  • グロースマインドセットを受け入れる
    • グロース(成長型)マインドセットの持ち主は、自分の特性や能力には成長や改善の余地があると信じ、学習し、柔軟性を高めるための機会として経験を捉える

第6章 インクルーシブデザインリサーチ

リサーチ計画書

早い段階でリサーチを行うこと、はじめからアクセシビリティを計画に入れることこそが組織のためになる。
下記はリサーチ計画書の内容例。

  • リサーチの目的
  • プロダクトの使用状況
  • ゴール(目標)
  • リサーチの優先事項
  • 手法
  • 懸念事項(失敗要因になりそうなこと)
  • タイムフレーム
  • 質問
  • 参加者(対象者)
  • スクリプト
  • 倫理

ケーススタディ

ジョージア州のデジタルサービスプラットフォーム(失業給付、退役軍人サービス、税務情報など)をアクセシブルにするために行った例。

  • カラーコントラストの向上
  • フォントの読みやすさを向上
  • セマンティックマークアップの改善
  • キーボード操作のみでナビゲーションできるように改善
  • スクリーンリーダー用に機能を拡張
    • ARIAラベルを使う。例えば、
      • 「つづきを読む」リンク
      • 「次へ」「戻る」リンク

第7章 支援技術

支援技術とは

支援技術は、5W1Hの中の「なにを(What)」にあたる。
つまり、障害を持つ人たちの補助や適応、そしてリハビリに使われるデバイスのこと。それらを使用するときのプロセスも支援技術に含まれる。
よく「適応技術」と同義語として扱われるが別物で、適応技術は障害を持つ人たちのために特別にデザインされた製品を指す。

ケーススタディ

Xbox アダプティブ コントローラーのアクセシブルなパッケージデザインの例。
https://news.xbox.com/en-us/wp-content/uploads/sites/2/Xbox-Adaptive-Controller-Packaging_940x528-1-hero.png

開梱しやすいデザインにするため、Microsoftのデザイナーが事例探しから着手。
支援者たちにフィードバックをもらいながら、少ない手順にまとめるよりも、手順が増えたとしてもシンプルなステップを踏むデザインになった。

第8章 インクルーシブデザインの実現に向けて

アクセシビリティがビジネスにもたらす利点

デジタルプロダクトのデザインと開発にアクセシビリティを組み込むことは一人で抱えきれる仕事ではない。
リーダーが支持していない状況では実現はかなり難しいが、アクセシビリティがビジネスにもたらす下記のような利点をしっかり捉えて、まずは種まきから行うとよい。

  • 差別と訴状を回避できる
  • 幅広いオーディエンスにリーチできる
  • プラスイメージの広報活動になる
  • SEOが向上する
  • ユーザビリティが向上する
  • ソースコードの質が上がる

アクセシビリティをデザインシステムに組み込む

コーディングがはじまる前の段階で組み込むのが得策。
デザインシステムがチームにもたらす恩恵は次の通り。

  • 自分たちのプロダクトに関連するアクセシビリティについて、チーム全員が理解していることを確認できる
  • ユーザーストーリー、ワイヤーフレーム、要件定義などにアクセシビリティが盛り込まれる
  • 全チームがアクセシビリティに責任を負うことと各チームの責任の範囲を明確にできる
  • ナビゲーションが明確にドキュメント化される
  • 色、フォーム、ナビゲーションのフォーカスなどの使い方が明確になる
  • 新たに加わるメンバーが参照できる資料が整う

これは確かに、構想やデザイン段階からアクセシビリティに対しての考えがまとまってないと難しくなることが多いと実務を通して感じているためその通りだなと思った。

第9章 ユーザビリティテスト

ユーザーテストとユーザビリティテスト

  • ユーザーテスト
    • プロダクトやサービスを使うことになる人(ユーザー)が持つニーズが何かをを確認すること
  • ユーザビリティテスト
    • プロダクトやサービスに備わる機能に注目し、それが使えるかを確認すること

なぜユーザビリティテストを行うのか

  1. 人が持つ能力の多様性に合わせた選択肢を提供することで、UXを底上げできる
  2. 提供しようとしていプロダクトやサービスが使える人を増やせる
  3. 市場シェアやブランドの認知を上げられる
  4. 内部のテストでは見つけられないユーザビリティの課題を特定できる
  5. 正しいことをできる!

ユーザビリティテストを行う前に観点を整理する。

  • なんのためにテストを行うのか?
  • プロダクトが実現しようとしていることはなにか?
  • どのくらいの時間を使えるか?
  • どのくらいの予算があるか?
  • テストに使えるリソースはどのくらいか?
  • 特別な機器やデバイスが必要になるか?
  • ユーザーに何をしてもらうか?

第10章 Webを超えて

過去に作られたイノベーション

  • 電話
    • 1870年代にアメリカにてアレクサンダー・グラハム・ベルによって発明。
    • ベルには進行性の難聴を患っていた母親がいたバックグランドがあった。
  • インターネット
  • テキストメッセージ
    • マッティ・マッコネンが聴覚障害者がコミュニケーションを取れるようにするためにSMSを発明。

ユニバーサルデザイン

エクストリームユーザー(極端な事情や理由を持ってプロダクトやサービスと向き合っている人)のニーズを満たすものづくりに取り組むことが、結局は大勢に響くものを生み出す事例もある。

  • 縁石カット
  • 傾斜路
  • 自動車のクルーズコントロールシステム
  • スクリーンリーダー

感想

  • デザイン戦略〜リサーチ〜WCAGの定義〜HTMLのコードレベルでこうやるとアクセシブルなどと、取り扱われている範囲が広かった。
    • それがインクルーシブデザインを実践する、ということなのだと解釈。
  • 特にアクセシビリティについての記事を読む際に、どういうスタンスで取り組むべきかはぼんやりと理解していたが、それが社会モデルと定義されていたことを初めて知った。
  • Airbnbの「Another Lens」、ググっても日本語の関連記事はあまりでてこなかったが何かをデザインするときに大事な視点だと感じた。
  • 今後の展望としてVR/ARが書籍内でもピックアップされていたが、 Apple Vision Proで変わるWebサイトのデザインとナビゲーション あたりもWeb制作で考慮する点としてスタンダードになってくるのだろうかと思った。

【読書メモ】縁の下のUIデザイン ─ 小さな工夫で大きな効果をもたらす実践TIPS&テクニック

目次・概要

  • 第1章:色,文字,動きによる見せ方の工夫
    • 赤の使い方──色が与える直感的な印象を活かす
    • 上手に配色するためのコツとテクニック
    • ユーザーに使い方を文字で説明するためのUI
    • 動きによる楽しさの演出──コンテンツの変化や操作へのフィードバック
  • 第2章:機能表現の工夫
    • 「いいね!」の効果的な使い方
    • 保存のデザインの使い分け
    • 未読と既読のデザイン
    • 情報の更新をどう表現するか
  • 第3章:UIコンポーネントの使い方による工夫
    • ボタンのデザインと使い分け
    • 数値の入力・選択に適したUI
    • カードUIの向き不向き
    • メッセンジャーサービスにおけるデザインの工夫
  • 第4章:ユーザーの行動への配慮
    • エラーと確認──スムーズな手続きを実現するには
    • 受動的な体験のデザイン──「なんとなく眺める」を快適にするには
    • 異なるユーザー層へのデザイン
    • 待ち時間中のユーザーへの配慮
    • 待ち時間を短く感じさせる方法
    • コンテンツがないときに考えること
  • 第5章:画面と画面遷移の設計
    • 画像はどう置く?──位置,大きさ,そろえ方
    • 長くなりがちなコンテンツをどう見やすくするか
    • 横配置メニューの項目数が多くなった場合の表現
    • 「もっと見る」をちゃんとデザインする
    • 入力フォームを1画面にする? 分割する?
    • 画面単位ではなく,画面遷移を意識した改善
  • 第6章:コミュニケーションとツール
    • エンジニアに意識してほしいこと
    • 初期リリースにおける理想像とのずれをどうするか
    • 「○○っぽいデザイン」のエッセンス
    • デザインシステムで,使い勝手・デザイン・コードに統一感を持たせる
    • UIデザインのためのGoogle アナリティクス
    • 説得力・納得感のあるデザインにする工夫
  • 第7章:考察,雑感
    • 今,iOS/Androidアプリのデザインガイドラインにどう向き合うか
    • 業務利用サービスのデザイン──多くの情報,専門用語をどう見やすく表示するか
    • 中国のスマートフォンアプリの共通項──所変わればデザイン変わる
    • 長押しを使ったデザインの可能性
    • 「当然そうなるだろう」という思い込みを考慮する

著書は 池田 拓司 さん。はてなクックパッドに勤務されていた方で「はじめてのUIデザイン」 の著書のひとりです。

「細かなデザインの工夫がどのような意図を持っているか」「なぜこのデザインが使いやすいのか」を具体的なWebサービスの事例を使用して各トピックに分けて解説されています。

掲載内容は過去に WEB+DB PRESS に掲載されたトピックから加筆されていたり、新規で書籍用に追加されたものがあります。
gihyo.jp にも一部記事が掲載されています。

ポイント

気になった点のメモです。

第1章:色,文字,動きによる見せ方の工夫

赤の使い方──色が与える直感的な印象を活かす

TwitterやLINEのユーザーアイコンの円形のように、特定サービス限らずユーザーが認知できる見た目や機能がある。
同じように赤色のテキストやボタンは、UIにおいて「危険」「注意」を表現することが多くあるが、どのようなユーザー体験を提供したいかを踏まえて色の選択をする必要がある。
(例:インジケータで、多い状態が赤になる/少ない状態が赤になる)
https://gihyo.jp/assets/images/design/serial/01/ui-design-unsung/0003/thumb/TH800_007.png

上手に配色するためのコツとテクニック

UIデザインの配色選定では、早い段階で完成イメージが湧く色で考えることが大切。
全体的な調和を取るために、テーマカラー以外のエラーやdisabledの色も最初のうちに決めておきたい。
また配色は構成とセットで考えるべきで、配色はどの色をどのくらいの面積で使われるか等はシミュレーションしながら作るとコンセンサスも取りやすい。( その手法を試すためのFigmaファイル:UI Color Impression Simulator

サービスの補足的なUI(背景/枠線など)には無彩色が使われがちだが、有彩色を少し入れることも検討してみると調和が取れることもある。
https://gihyo.jp/assets/images/design/serial/01/ui-design-unsung/0019/thumb/TH800_005.png

ユーザーに使い方を文字で説明するためのUI

直感的なデザインでテキストでUIを説明しないことに越したことはないが、テキストで説明な必要がある。その際、

  1. 特定の条件でだけ(たとえば初回に一度)見ることができる
  2. 常に説明を見ることができる
  3. ユーザーが見たいときにだけ表示させてみることができる

の3パターンが検討できる。

動きによる楽しさの演出──コンテンツの変化や操作へのフィードバック

サービスを作る過程では「わかりやすいか、使いやすいか」は考慮されるが、「楽しいか」という観点はなかなか意識されづらい。
@cosmeトップの口コミ数表示、Yahooショッピング商品ページの「現在◯人がカートに入れています」など、数値の上昇でサービスが賑わっている感を演出できる。
https://gihyo.jp/assets/images/design/serial/01/ui-design-unsung/0008/003.png

第2章:機能表現の工夫

「いいね!」の効果的な使い方

Facebook登場以降、スタンダードになっている「いいね!」のようなアクションをライトフィードバックと定義する。
このライトフィードバックの目的は、コンテンツに対して手軽にフィードバックを返せること。
例えば「いいね!」を言い換えて異なるワーディングで検討する場合、その変更が有効かどうかは慎重になったほうがいい場合もある。

またTwitterInstagramのように「保存」機能とライトフィードバックは区別して違いを明確化するなど、細かいところだが様々な配慮が必要なUIでもある。

保存のデザインの使い分け

UIにおける「保存」の概念は技術の変化に伴いユーザー体験に合わせた形で多様化した。
例えば管理画面の一覧ページの場合3つの手法が考えられ、ユーザーの行動を想像して考えるプロセスが大切。

https://gihyo.jp/assets/images/design/serial/01/ui-design-unsung/0013/thumb/TH800_002.png

  1. 自動保存
    • 保存忘れを防げる
    • 慎重に変更するデータには不向き
    • 保存されたことをユーザーに伝えることをおすすめ
  2. 行ごとに保存ボタン
    • 必要に応じてこまめに保存できる
    • 画面が煩雑になるケースも
    • どこを保存したか分からなくなってしまうケースも
  3. すべて保存ボタン
    • シンプルで操作がラク
    • ページをまたがず、1つのページで保存が完結できるように設計が必要
    • 先の状態が想像できないようなケースはプレビューの用意があると良い

未読と既読のデザイン

iPhoneホーム画面のアプリにつくバッジや、コンテンツの未読表現について。
https://gihyo.jp/assets/images/design/serial/01/ui-design-unsung/0028/001.png

前提としては厳選したコンテンツへのアクセスにこそ意味があるため、無駄な未読表現は控える。
下記を考慮し表現されていると使い勝手が良くなる。

  • 未読数を出すもの、出さないものを分ける
  • 数字が意味している情報を明確にする
  • 未読を既読にするタイミングを考える

情報の更新をどう表現するか

排他制御が行われた際にどのようにユーザーに伝えるか。

  • お知らせ画面で更新情報を伝える
  • モーダルを使って伝える
  • 詳細画面に更新情報のスペースを設ける
  • 一覧と詳細にアイコンで組み込む
  • 履歴管理機能を備える
  • メールや通知を送る

「この機能をどのように使ってもらいたいか」「ユーザーの解決したい課題は何か」を具体的な案を元に考えると判断もスムーズになる。

第3章:UIコンポーネントの使い方による工夫

ボタンのデザインと使い分け

ボタンはユーザーのアクションを査収する重要な要素。どのような場面でどういった形状のボタンを使うか、また画面内で複数のボタンがある場合どのように対応するかなど考えることが重要。

状態によるバリエーションでは下記のルールを参考にしてみると良い。

  • マウスオーバーまたはボタン押下時
    • 通常よりもボタン背景と文字のコントラストを上げる
  • 利用不可の状態
    • 通常よりも画面背景とボタン背景、ボタン背景と文字の両方のコントラストを下げる

「状態の違い」「形状の違い」以外にも、画面内での重要度によって強弱をつけるため、プライマリボタン/セカンダリボタンを用意することが多い。
ほかの要素と比較してボタンの主張が強くなりすぎないように、また複数のボタンが出現したときにどのアクションが重要なのかを明確にするためにこれらを使い分ける。
複数のボタンが登場するケースでは、プライマリボタンは基本的に「画面の中に1つしか使わない」と考えてデザインすることをおすすめ。

数値の入力・選択に適したUI

数値を入力・選択してもらう場合、どのようなUIコンポーネントが考えられるか。
ユーザーの自由度や操作性を考え、キーボードで入力ができるものが一番良い。

  • テキストフィールド(キーボード入力)
    • 普段使い慣れた入力方法をそのまま利用できる
    • ユーザー自身が自由に入力ができてしまうため制限がかけづらい
  • プルダウンメニュー
    • あらかじめ用意された数値を選んでもらう場合
    • 選択肢がたくさんある場合は選択が面倒
  • スライダー(シークバー)
    • 定められた最小値と最大値の間の数値を選択させたい場合
    • 直感的な操作で変更ができる
  • ステッパー
    • 数値を確実に上下できる
    • 数値の変更幅を一気に変えるにはボタンを押し続けなければいけない

カードUIの向き不向き

カードUIは、不均一な情報の集まりをまとめることに適したUIと言われている。
ただし目的を明確に持たないと、その良さを引き出すことができない。

効果的な場面の一例は以下。

  • 不均一な情報をきれいに整理する
  • 個々のコンテンツの主張を強くする

逆に注意点として、情報の比較がしにくくなるケースは避ける。
https://gihyo.jp/assets/images/design/serial/01/ui-design-unsung/0015/007.png

この例ではカードUIよりテーブル形式のほうが情報の比較がしやすい。

第4章:ユーザーの行動への配慮

エラーと確認──スムーズな手続きを実現するには

エラーをどのように伝えるかもスムーズに手続きを完了させるための大切な要素で、ユーザーが離脱する大きな要因になってしまう。

必要な項目がすべて埋まらない限り機能しないdisabledボタンは避けるべきで、いつでもボタンは押せる状態にしエラーメッセージを表示できることが理想。
https://gihyo.jp/assets/images/design/serial/01/ui-design-unsung/0002/002.png

また状況に応じた確認手段を用いることも必要で、例えば日用品と車の購入では、意思決定をするまでのプロセスが異なる。実社会の体験も踏まえてUIを検討することで、ユーザーの気持ちを読み取りやすくなる。

受動的な体験のデザイン──「なんとなく眺める」を快適にするには

YouTubeInstagramなど、暇な時間にとりあえず眺めるコンテンツが増えた。
そのようなコンテンツには「ハンズフリー(操作しなくてよい)な体験作り」が向いている。

例えば、Instagramのストーリー機能はユーザーアイコンをタップしてショート動画が再生、次の動画も自動またはタップで再生できる。

異なるユーザー層へのデザイン

  • ユーザー層が重なっていない(重なりにくい)サービス / ユーザー層が重なっているサービス
  • はじめて使うユーザー / ずっと使っているリピートユーザー

など、サービスを使うユーザー層はさまざま。

例えばAirbnbは「部屋を貸したいユーザー」と「民泊希望のユーザー」でユーザー層が重ならないことが想定されるが、もう片方のユーザーがどのように見えているかを簡単にプレビューできるなど、サービスやユーザーの特性に応じて考慮することが重要。

待ち時間中のユーザーへの配慮

待ち時間であることをユーザーに視覚的に伝えるUI表現は「終わり時間を明確に示していないタイプ」「終わり時間を明確に示したタイプ」に分かれる。
またUIコンポーネントとしては、「スピナー」もしくは「プログレスバー」で表すことが多い。

  • 待ち時間を感じさせない設計ができないか
  • 時間がかかることが事前にわかっている場合それをどう伝えるか
  • 待ち時間に別の行動がとれるようにできないか

を考慮することが必要で、例えば「みてね」アプリではアップロードしたい写真を選択した直後から別の操作が可能となっている。
https://gihyo.jp/assets/images/design/serial/01/ui-design-unsung/0004/004.png

コンテンツがないときに考えること

サービスの使用開始直後など、コンテンツが空の状態「エンプティステート」での表現や対応手段について。

画面全体が空の状態の場合、ユーザーの行動によって状態を解消できるケースと、解消できないケースがある。

できるケース:ユーザーが積極的に行動できるように次へのアクションを促す。
できないケース:ユーザーの心情をなだめるコミュニケーションが必要。

「できないケース」の例はクックパッドマートの未対応地域への対応開始メッセージ。

第5章:画面と画面遷移の設計

画像はどう置く?──位置,大きさ,そろえ方

一覧形式のレイアウトで左側/右側に置く、またその詳細ページでは大きく表示/カルーセル付きで複数展開など、動線やユーザーのニーズに合わせて考慮する。

また画像をメインに使い感性に訴えかけたい場合は、一休のトップページのように全面に写真を大きく用いることが効果的。
「何県何温泉のあのホテルを今すぐに最安で予約したい」という目的よりも、「貴重な休みがとれたのでどこか良い場所はないだろうか」という目的に沿ってデザインされている。 https://gihyo.jp/assets/images/design/serial/01/ui-design-unsung/0001/005.png

長くなりがちなコンテンツをどう見やすくするか

できるだけ画面が長くならないようにするためどうすればよいか。

  • すでにある要素を削る。または分け合う
  • 効果の最大化を意識する
  • 面積比率をルール化する
    • 筆者は「その画面に本来あるべき要素が7割、関連する情報など関係の薄い要素は3割」といったように具体的にルールを用いたことも

長くなった場合どのように考えて対応するか。

  • 画面内のキーとなる要素を知る
  • 追加要素を分散させる
  • 一部の要素を隠す

横配置メニューの項目数が多くなった場合の表現

横に配置するメニューを使うときの注意点として、「縦方向に比べ、一度に表示できるメニュー件数が少ない」「複数の階層構造を一度に表示しにくい」というデメリットがある。

その上で横配置メニューを使用するパターンとしては下記が挙げられる。

  • スクローラブルにするパターン
  • 最後のメニューにまとめるパターン
  • 複数段にするパターン
  • 長押しで表示するパターン

「もっと見る」をちゃんとデザインする

「もっと見る」には大きく分けて2つの使い方がある。

  • 特定の切り口の情報だけではなく、いろいろな切り口で情報を少しずつ見せる必要がある場面
  • すべての情報を一度に表示させると件数が多すぎるため途中で切って表示し、続きを見たい人が「もっと見る」を押すような場面

「画面遷移する」か「その場で開く」かも2通りあるが、実装コストやユーザーの現在地の理解しやすさの観点で、画面遷移する(ページング処理)ほうがおすすめ。
https://gihyo.jp/assets/images/design/serial/01/ui-design-unsung/0006/thumb/TH800_005.png

入力フォームを1画面にする? 分割する?

入力フォームを、長くなっても分割せずに1画面にするのか、それとも画面を分割して複数画面にするのか、悩む場合が多い。
https://gihyo.jp/assets/images/design/serial/01/ui-design-unsung/0016/001.png

分割するかしないかの基準は下記を目安とするとよい。

  • コンバージョン重視ならできるだけ分割しない
  • モバイルならスクロールよりタップ移動のほうが行いやすいので分割する
    • Uber Eatsの評価画面など
  • じっくり編集したり、あとから更新が多い場合は分割する
    • 特にB2Bサービスなど会社情報やビジネス情報の入力/編集画面

画面単位ではなく,画面遷移を意識した改善

UIデザインの改善をする際に画面単位や機能単位での小さな改修を優先していくと、全体の流れが崩れがち。
その際はユーザーストーリーマッピングをしましょう、という話。

  • 体験をストーリー単位で考える
  • すべての画面変化を書き出す

をしたら、「違和感がある」「改善したい」という箇所について書き出し解決案を探る。(「課題」(issue)と「解決案」を分けることが大事) https://gihyo.jp/assets/images/design/serial/01/ui-design-unsung/0022/003.png

第6章:コミュニケーションとツール

エンジニアに意識してほしいこと

デザイナー/エンジニアそれぞれお互いの歩み寄りが必要。そのうえでエンジニアに意識してほしいこと。

  • 実装の認識合わせ
    • 実装方法を知りたい
    • デザインに制限がかかるライブラリを利用するかを知りたい
    • 負荷による制限を教えてほしい
      • デザイナーはサクサク動くこと前提で考えてしまう
      • 検索結果の絞り込みなど、読み込み状態が必要かなど
  • デザイナーのこだわりとの付き合い
    • 再現の精度を上げてほしい
      • 余白 / フォント / 文字サイズ / 行間
    • 立地な表現や細やかな表現を行いたい
      • デザイナーはDribbbleなど見て突っ走っちゃうときがあるので、事前にスケジュール感と表現の幅についてできるだけ認識を合わせておく

初期リリースにおける理想像とのずれをどうするか

サービスはミニマム状態と理想状態がある場合が多く、それぞれの状態で何を考慮すべきか。
大きな観点としては「充足した情報がどれくらい作られるか」

  • 理想状態は1,000商品を取り扱うECサイトを作りたいが、ミニマム状態では10商品しかない
  • 理想状態は毎日5記事更新、全部で1,500記事できるようなメディアサイトを作りたいが、ミニマム状態は週に1記事更新でリリース時は50記事しかストックがない
  • 理想状態は10,000人が集まるクチコミサイトを作りたいが、ミニマム状態ではメンバーに情報を集めてもらう

など、いずれかの状態専用でデザインする/共用でデザインするには大きな違いがある。

例えば、ミニマムリリース時にアイテム件数が少ないサービスでは、フリーワード検索ではなく用意しているタグ検索を用いる。
https://gihyo.jp/assets/images/design/serial/01/ui-design-unsung/0021/002.png

「○○っぽいデザイン」のエッセンス

デザインの依頼時に「○○っぽいデザインでお願いします」の「○○っぽさ」とは何なのか。
3つの観点がある。

  • UIデザインを指すパターン
    • 例)画面全体のベースカラーが「ベージュ」で、アクセントカラーに「緑」を用いている
  • 体験そのものを指すパターン
    • 例)ボタンを押したときのフィードバックや画面のロードタイムがとても早い
  • 利用者の傾向を指すパターン

例えば「Pinterestっぽい一覧画面のデザインにしたい」という「○○っぽさ」を「UIデザインを指すパターン」と仮定する。
その中でエッセンスはどこかを探ると最適なデザインに近づくことがある。 https://gihyo.jp/assets/images/design/serial/01/ui-design-unsung/0026/001.png

  • 情報が2カラムに配置されている
  • 写真がレンガ状に互い違いに並んでいる
  • 写真とラベルだけで情報の要素が少ない
  • 余白が最小限で、少ないスクロールで数多くの情報を見ることができる

デザインシステムで,使い勝手・デザイン・コードに統一感を持たせる

デザインシステムがどのようなものか。構築メリットとして下記が挙げられる。

  • 一貫した使い勝手をユーザーに提供する
  • 統一した視覚表現で魅力的な世界観を表現する
  • 提供しているサービスの思想や価値観の認識を開発者間で合わせられる
  • スタイルやコンポーネント単位でソースコードを共通化し効率化する

含まれる要素として

が挙げられるが、例えばデザインガイドラインがエンジニアと共有されているか、それが実装レベルまで反映されているかは、デザイナーだけエンジニアだけではなく両者での構築が必要となる。

説得力・納得感のあるデザインにする工夫

大前提として自分が作ったデザインに自信を持って提案するのは、実際にユーザーに使ってもらい、うまくいっている様子を確かめない限り難しい。
その上でそれ以外の方法で筆者が意識していること。

感想

  • スマートフォンアプリ限定の話題もありましたが、Webサービス/サイトに通ずるところも多く勉強になった。
    • 補足的なUI(背景/枠線など)に無彩色が使われがちや、ボタンの状態作成、実際の案件だと確かに半ば思考停止でやり過ごしてしまいがちなので気づきになった。
  • 「どのUIが最適か」に対する答えとしてはケースバイケースということが多い。(決まりきったことはほぼない)
    • サービス全体とその中のその画面内で、どの属性のユーザーが何を達成したいかによって、どのようなUIが適切かが判断できる。
    • 引き出しを多く持ちその特性を理解すること、常日頃から自身が使うサービスのUIについて考えることが重要と感じた。
  • 第6章の「エンジニアに意識してほしいこと」や「初期リリースにおける理想像とのずれをどうするか」の内容、こういう類の本でなかなか語られない開発視点の内容なので新鮮でした。
  • 最後にChatGPTなど技術進化は増しているが、「開発者の小さな工夫や細かなこだわりが大切なことは変わることがないと感じています」という所がいいなと思いました。

GASでMLB試合予定を日本時間でGoogleカレンダーに登録する

  • MLB の Stats API を使用
  • GAS で予定取得し変換、Googleカレンダーに登録
    • 特定チーム(今回はエンゼルス)の予定を取得
    • 時刻は日本時間に
    • タイトルのチーム名は3文字の省略形(LAA など)に

// GoogleカレンダーIDをセット
const CALENDAR_ID = '[GOOGLE_CALENDAR_ID]';

// MLB Data APIからエンゼルスの試合情報を取得
function fetchAngelsSchedule() {
  const apiUrl = 'https://statsapi.mlb.com/api/v1/schedule?teamId=108&season=2023&sportId=1';
  const response = UrlFetchApp.fetch(apiUrl);
  const data = JSON.parse(response.getContentText());
  const games = data.dates.flatMap(date => date.games);

  return games.map(game => {
    const gameDate = new Date(game.gameDate);
    const end = new Date(gameDate.getTime() + 3 * 60 * 60 * 1000); // 試合終了時間を仮定して3時間後に設定
    const isHome = game.teams.home.team.id === 108;
    const opponent = isHome ? game.teams.away.team : game.teams.home.team;
    const opponentShortName = getShortName(opponent);
    return {
      start: gameDate,
      end: end,
      opponent: opponentShortName,
      isHome: isHome,
    };
  });
}

function getShortName(team) {
  const shortNames = {
    'Baltimore Orioles': 'BAL',
    'Boston Red Sox': 'BOS',
    'New York Yankees': 'NYY',
    'Tampa Bay Rays': 'TBR',
    'Toronto Blue Jays': 'TOR',
    'Chicago White Sox': 'CWS',
    'Cleveland Guardians': 'CLE',
    'Detroit Tigers': 'DET',
    'Kansas City Royals': 'KC',
    'Minnesota Twins': 'MIN',
    'Los Angeles Angels': 'LAA',
    'Oakland Athletics': 'OAK',
    'Seattle Mariners': 'SEA',
    'Texas Rangers': 'TEX',
    'Houston Astros': 'HOU',
    'Atlanta Braves': 'ATL',
    'Miami Marlins': 'MIA',
    'New York Mets': 'NYM',
    'Philadelphia Phillies': 'PHI',
    'Washington Nationals': 'WSH',
    'Chicago Cubs': 'CHC',
    'Cincinnati Reds': 'CIN',
    'Milwaukee Brewers': 'MIL',
    'Pittsburgh Pirates': 'PIT',
    'St. Louis Cardinals': 'STL',
    'Arizona Diamondbacks': 'ARI',
    'Colorado Rockies': 'COL',
    'Los Angeles Dodgers': 'LAD',
    'San Diego Padres': 'SDP',
    'San Francisco Giants': 'SFG',
  };

  return shortNames[team.name] || team.name;
}

// 日時を日本時間に変換
function convertToJST(date) {
  const jstDate = new Date(date.toLocaleString('en-US', { timeZone: 'Asia/Tokyo' }));
  return jstDate;
}

// Googleカレンダーに試合予定を登録
function addAngelsScheduleToCalendar() {
  const calendar = CalendarApp.getCalendarById(CALENDAR_ID);
  const games = fetchAngelsSchedule();

  const seasonStart = new Date(2023, 2, 31); // 2023年3月31日
  const seasonEnd = new Date(2023, 9, 31); // 2023年10月31日

  games.forEach(game => {
    const startJST = convertToJST(game.start);
    const endJST = convertToJST(game.end);

    if (startJST >= seasonStart && startJST <= seasonEnd) {
      const title = game.isHome ? `LAA vs ${game.opponent}` : `${game.opponent} vs LAA`;

      // 予定がすでにあるかチェック
      const rangeStart = new Date(startJST.getTime() - 24 * 60 * 60 * 1000);
      const rangeEnd = new Date(startJST.getTime() + 24 * 60 * 60 * 1000);
      const events = calendar.getEvents(rangeStart, rangeEnd, { search: title });

      const isEventExist = events.some(event => {
        const eventStart = event.getStartTime();
        return eventStart.getYear() === startJST.getYear() &&
               eventStart.getMonth() === startJST.getMonth() &&
               eventStart.getDate() === startJST.getDate();
      });

      if (!isEventExist) {
        // 予定がなければ新たに追加
        calendar.createEvent(title, startJST, endJST);
      }
    }
  });
}

React / OpenAI API でコードを説明してもらう

What does this code do? を見て、日本語で同じようなもの作れそうなのでやってみる。

コード入力/送信ボタン押下でOpenAI APIにリクエストを送りコードの説明を得る。フロントのみなのでセッション保持などはなし。

GitHub: https://github.com/yuheijotaki/chatgpt-what-does-this-code-do

OpenAI APIへのリクエスト、これまでAxiosを使ってましたが openai のライブラリがあったので使ってみる。

import { Configuration, OpenAIApi } from 'openai';

const configuration = new Configuration({
  apiKey: process.env.REACT_APP_OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);

messages には下記を仕込んでおく。

messages: [
  { role: "system", content: "あなたはコードを説明するエキスパートです。" },
  { role: "user", content: `このプログラムのコードを${maxTokens}文字以内で説明してください:\n${code}` },
],

所感

gpt-3.5-turbo でやりましたが、GPT-3.5のモデル みると text-davinci-003 が本来は妥当なのかも?
max_tokens 周りもよく分かってないので、もう少し検証や調査が必要。

参考

React / DALL-E API で画像生成

ReactとOpenAI API(DALL-E API)を使って画像生成アプリを作ってみる。

キーワードを入力/画像生成ボタン押下でAPIにリクエストを送り画像を取得する。フロントのみなのでセッション保持などはなし。

GitHub: https://github.com/yuheijotaki/chatgpt-dall-e-sample

Create image のエンドポイントへPOSTする。

  const generateImage = async () => {
    try {
      const response = await axios.post(
        "https://api.openai.com/v1/images/generations",
        {
          prompt: inputText,
          n: 1,
          size: "256x256",
          response_format: "url",
        },
        ...
      );
      setImageUrl(response.data.data[0].url);
    } catch (error) {
      ...
    }
  };

size でサイズ変更、 response_formatb64_json などのフォーマットと変更も可能。

所感

例えば「3匹の猫」と入力したら白い花の画像が生成されたり、結構厳密にキーワード指定しないと精度的にはそこまで高くなさそう。(現状では)
Create image edit や Create image variation など、インプットが画像ベースになるのも試してみたい。

React / OpenAI API でチャットボット作成

ReactとOpenAI APIを使ってチャットボットを作ってみる。

ChatGPTのWebブラウザ版と同じく、メッセージ入力/送信ボタン押下でOpenAI APIにリクエストを送り回答を得る。フロントのみなのでセッション保持などはなし。

GitHub: https://github.com/yuheijotaki/chatgpt-bot-sample

OpenAI APIへのPOSTは、

const response = await axios.post(
  'https://api.openai.com/v1/chat/completions',
  {
    model: 'gpt-3.5-turbo',
    messages: [
      ...conversation,
      {
        role: 'user',
        content: message,
      },
    ],
  },
  ...
);

messages 内で会話履歴を配列にいれておくことで、文脈を踏まえて回答するようになる。

所感

レスポンスの早さが gpt-3.5-turbo っていうくらいなので、早いと期待していましたがそこまでではなかったです。
GPT-4も招待来たら使ってみたいと思います。