WEBアプリケーションのデザイン時に最低限考える必要があるポイント
WEBアプリケーションの機能やインターフェースを設計するとき、WEBプラットフォームに関する知識やアプリケーションの仕組みをはじめ非常にたくさんのことを考える必要があります。
2~3年前に「UIデザインを作るときおさえておきたいポイント」的な記事を書いたのですが(恥ずかしくて下書きに戻しました)、今現在見返すと内容が非常に薄く、押さえるべきポイントはもっとあるよな〜と思ったため今回は「WEBアプリケーションのデザイン時に最低限考える必要があるポイント」と題して、改めてエンジニアへのレビューやリリース時に押さえておきたいポイントについてまとめてみました。ここで肝心なのはあくまでも「最低限」であることであり、実際の機能や仕様・インターフェースに応じてその都度論点となる部分は異なるため、決して万能なものではありません。そこに注意しつつ、汎用的に言及できそうな部分について見ていきましょう。
ボタンについて
hover, focus, active といった擬似クラスのスタイルとその transition
ユーザーとインタラクションが発生する「ボタン」はその interactivity を確保する必要があります。また、動きやなめらかさにこだわりたい場合は各擬似クラスで定めたスタイルへ変わるときの transition もお忘れなく。
width, height の値
「ボタン」のラベルとして入力されるテキストは場合によって様々です。「送信」のように短い場合もあればものすごく長い場合もあります。このとき「ボタン」そのものに width, height をそのまま指定するのか、それともラベルのテキストの長さに応じて可変になるよう padding を持たせるだけにするのか、はたまた親要素の大きさに依存させるよう % などの割合で指定するのか、など選択肢があります。特に「ボタン」を汎用的なコンポーネントとして切り出す場合はその意思決定や適切な運用に気を遣う必要があります。
enabled と disabled
フォームのバリデーションやユーザー権限による制御がある場合は「ボタン」が押下できたりできなかったりする場合があります。enabled は言わば通常状態の「ボタン」ですが、押下できない disabled のときはどういうインターフェースになり、また disabled はどういうときに状態として有効になるのか設計時に明示しましょう。
「ボタン」コンポーネントの使い分け
そこそこの規模なアプリケーションとなると、単一の「ボタン」では機能に対して適切なインターフェースを設計できない場合があり、往々にして primary, secondary, danger, ghost など様々な「ボタン」が生まれます。このとき、特定の機能およびインターフェースにおいて使用している「ボタン」がもっとも適しているかどうか確認しましょう。「ボタン」の使い分けはアプリケーションや開発チームによって異なるため、関係者で十分に認識をすり合わせる必要があります。また、適切なインターフェース設計のために汎用的なコンポーネントとして切り出された「ボタン」から逸脱した言わば「野良ボタン」を使用することもありますが、こちらも maintainability に関わるため議論が必要です。
「ボタン」押下時の実行処理
「ボタン」を押下したときにアプリケーション上で何が起こるのかについては、もっとも関心を寄せる必要があります。
・URL変更を伴うページ遷移なのか(同じドメイン内なのかあるいは外部サイトで新規タブかどうかも含む)
・クエリパラメータ付与等による描画・表示内容の変更なのか(その場合pushStateかreplaceStateかブラウザの履歴への影響など)
・データの送信やAPI呼び出しとそれに伴う処理(処理をしている間の loading はどうするのか、不正なデータが扱われる可能性や扱われたときの挙動)
など
例えば、リスト表示されている item をフィルタリングするような「ボタン」があるときに、そのフィルタリングをフロントエンドだけで行うのかAPIを呼び出して行うのかによってその実装の中身はだいぶ違います。「ボタン」を押下すると何が起こるかによってマークアップや動的な処理の部分にも大きく影響が出るため、実装するときには十分にエンジニアとの認識すり合わせが必要です。
テキストについて
単行表示か複数行表示か
そこに表示されるテキストもといデータが単行でしか表示されないのか、あるいは複数行にわたって表示されるのかは留意する必要があります。表示されるテキストが実データでは非常に長く、意図せずレイアウトが崩れてしまうという悲劇は多々起こります。また、それに伴い line-height の指定し忘れにも注意しましょう。
テキストの省略と empty
表示する画面やデータによってはその全てを表示せず省略することがあります。単行表示と定めた部分において表示できるテキスト長を超えた時にCSSで ellipsis を指定するのか、あるいは JavaScript で文字数に応じて省略処理をするなどいろいろ方法はあります。どのようなときにどのようにテキストを省略するか決めましょう。また、テキストデータがないときに「テキストがありません」という旨の代替テキストを表示するのか、そもそも要素としてレンダリングしないのか、といった論点もあります。
データ型
テキストというよりももはやデータについてですが、そこで表示される情報(テキスト)が例えば数値しかありえない、日付しかありえない、というような場合はデータ型に関して意識して実装者に共有してもいいと思います。
フォームについて
hover, focusといった擬似クラスのスタイルとその transition
「ボタン」同様、ユーザーとインタラクションが発生するため interactivity を確保する必要があります。もちろん、transition もお忘れなく。
「必須・任意」とそのエラー
何かしらのデータを入力・送信を要求するフォームには様々な理由で必須項目であるか任意項目であるかを定めます。このフォームにおける「必須・任意」の表示に関して、私個人としては唯一の解はないのかなと思っているためベストプラクティスは運用の中で自分たちで見つけるのが最適です。また、必須項目が入力されていないときやバリデーション違反の入力データなどに対してエラー表示をする必要があります。ビジネスロジック上あらかじめ発生しうる・特定しうるエラーはパターンとして考慮しましょう。
キーボードコントロールをはじめとしたアクセシビリティ
ブラウザデフォルトのものだとあまり心配ないですが、独自に実装したセレクトボックスなどでは Tab キー押下で各 item を選択できるようにする、といったキーボードコントロールにも配慮しましょう。"ちゃんと"実装するとなるとそこそこ気を遣ったり工数を必要とするため、あえて独自なスタイルのものを利用しないという手もあります。
submit に伴う処理
フォームにて入力された内容を submit したときに何が起こるかに注意しましょう。データの送信+ページ遷移なのか、表示内容がただ変更されるだけなのかなど、API周りと照らしあわせてのエラー処理も含めて仕様やインターフェースを決める必要があります。
レイアウトについて
viewport への思慮
昨今は様々なデバイスからWEBアプリケーションが利用されます。PC以外にもスマートフォンやタブレットといったデバイスからの利用は想定するのか決めて、考えうる viewport の幅や高さなどを決めましょう。メディアクエリをどの値で切るのか、どんな幅でも柔軟に表示が変わるリキッドレイアウトに振り切るのか、はたまた「PCのみ」のように想定する幅以外はサポートしないのかなどリソースと相談しつつ選択肢は多様にあります。
container あるいは wrapper に対してのスタイル
margin, padding, width といったスタイル要素はページ全体のレイアウトルールに大きく影響を与えます。整備されたレイアウトルールはユーザーへの認知的負荷を軽減したり、インターフェースを設計する上で迷いを与えません。ルールそのものが足枷とならない程度に決めて運用すると良いでしょう。
データ周りについて
empty 時の表示
何かしらの item を一覧表示する画面や空文字を許容するデータが含まれる画面などでは empty 時の表示が必要となります。上述していたテキスト同様、empty である旨を表示するのか要素としてレンダリングしないのかただ空文字を返すのかなどは、ユーザーが対峙するインターフェースとそのインタラクションにおいて大きな意味を持ちます。
データを読み込みレンダリングするまでの描画
ページにて静的な要素以外を表示する場合、データを読み込みそれがレンダリングされてブラウザに表示されるまでにそこそこ時間がかかります。一般的には扱っているデータが"大きい"ほどかかります。そうした読み込みの時間がかかっているときに真っ白なページをユーザーに返すのはあまり親切ではないため考える余地があります。
表示の区切り
画像やテキストが含まれたデータを1000件表示するとしましょう。このときその1000件を全て読み込み表示することは表示速度や各種リソースを食うためパフォーマンスがよくありません。スクロールして view に表示されるものから順に読み込み・レンダリングがされる方法や、適当な件数でページネーションするなどの方法があります。
プロセス途中での離脱やキャンセルをしたときの未保存データ処理
フォームをはじめとした、ユーザーに何かデータを入力させたりデータに対する操作を要求するプロセスにおいて、うっかり途中でページを閉じたりキャンセルをしたときに DB としては未保存のデータをどう処理したいかについて考えましょう。特に入力させる項目が多いフォームや長い文章の入力が想定されるフォームにおいては、入力途中だった内容を localStorage に保存してあげたりアラートを出してあげたりと打てる有効な手はいくつかあります。
権限によるデータへのアクセス制御
複雑なアプリケーションの場合、ユーザー権限によってはアクセスできないデータや操作が発生します。もしこれが存在する場合は、どの権限がどのようなデータにはアクセスできるのか否か、CRUD においてどの操作はできるのか否かについてしっかり整理しましょう。
データとしての「required」の変更や新たな項目の追加によるデータマイグレーション
機能追加や仕様変更で今まで任意な項目だったデータが required になったり新たな項目が追加される必要が出てきたとき、既に DB に存在するデータについて矛盾が出ないか確認しましょう。変更内容によってはデータマイグレーションが不可能な場合もあるため、有識者との協議が必要です。
さいごに
正直かなり基本的と言ってしまえばそれまでなのですが、ここに挙げたようなことを最初から全てばっちり考えてアプリケーションの設計ができる人というのはそこまで絶対数が多くないと感じています。静的なページではなくアプリケーションを設計する以上、本当に様々な観点を気にかけなかればいけませんがちょっとでもその手助けになればなと思います。
サポートは今後のインプット/アウトプットのために使ってまた皆さんに還元します!