利用者と「対話」するUIを考える|後編 過不足ないレスポンスの考え方

目次

前回まで

前回の記事では、利用者とUIによる対話の必要性について解説しました。ホテルコンシェルジュとの対人でのやり取りを例に挙げながら、発話だけではない、双方の細かな反応や動作が対話をよりスムーズなものにしていることがわかりました。

加えて、対人とのやり取りとは違って、コンピューターとの対話には、いくつかの考慮ポイントがあることも解説しています。

後編となる今回は、より具体的なUIの見た目を例に挙げながら、利用者とUIの対話について掘り下げていきます。その際、どれくらいの粒度で利用者に反応すべきかを考えるために、CSSの擬似クラスによって表わされる状態に着目しています。

本編に入る前に、前回解説した、利用者とUIの対話におけるいくつかの考慮ポイントを再掲します。

  • 1アクションにつき1レスポンス返す
  • バトンの所在を明確にする
  • レスポンスは画面上の変化でもよい
  • 大げさに反応する必要はない
  • レスポンスはアクション起点の周辺で行う
  • 一方的な判断をしない

それぞれの詳しい解説は、前回の記事を参照していただければと思いますが、あえて、これらの考慮ポイントを簡潔にまとめるなら、「レスポンスをサボってはいけない」ということです。なぜなら、現時点でのコンピューターが備えるUIは、生身の人間が行うような多彩なリアクションをすることができないからです。

利用者との対話手段に限りのあるUIは、そもそもで生身の人間との対話を得意としていません。ですが、現実問題として利用者とコンピューターが意思疎通をするためには、接点となる何かしらのUIは必須となりますので、利用者とのつなぎ役となるUIには、過不足のないレスポンスが求められます。

レスポンスの粒度

それでは「レスポンスをサボらない」ためには、UIはどのような粒度でレスポンスを返す必要があるでしょうか。粒度の例として、ごくごく一般的なUI部品のボタン要素とテキスト入力欄を取り上げて、レスポンスの一覧を作ってみました。

ボタン要素のレスポンス一覧(Button -Fill)

ボタン要素のさまざまな状態を示した図。紫色の点線で囲まれた領域に複数のボタンが縦に並んで表示されており、それぞれの状態に応じたアイコンや色、カーソルの状態が示されている。詳細は本文の表参照。

ボタン要素に入るテキストは{{button.text}}で表されています。

状態ボタンの色アイコンの状態枠線マウスポインターの形状
Default通常なしなし
:focus通常デフォルトのフォーカスリングなし
:active通常なしpointer
:hover濃紺通常なしpointer
:focus:hover濃紺通常デフォルトのフォーカスリングpointer
:disabled灰色通常なしnot-allowed
Busy灰色2つの半円の矢印で回転しているアイコンなしnot-allowed
Done灰色円にチェックマークが入ったアイコンなしnot-allowed
Error赤色(ボタンの下に赤い文字で{{error.message}}!マークが入った八角形アイコンなしnot-allowed

テキスト入力欄

図:テキスト入力要素のさまざまな状態を示した図。紫色の点線で囲まれた領域に複数のテキスト入力ボックスが縦に並んで表示されており、それぞれの状態に応じたアイコンや色、編集の可否が示されている。詳細は本文の表参照。

テキスト入力欄に入るテキストは{{value}}で表されています。

状態テキストの状態枠線フォーカスリングアイコンマウスポインターの形状
Default黒文字薄い灰色の線なしなしなし
:focus黒文字薄い灰色の線デフォルトのフォーカスリングなしなし
:hover黒文字細い青の線なしなしtext
:focus:hover黒文字細い青の線デフォルトのフォーカスリングなしtext
:disabled薄い灰色文字なしなしなしnot-allowed
:valid黒文字細い緑の線なし緑の円に白抜きのチェックマークなし
:invalid黒文字細いオレンジの線なしオレンジの八角形の白抜きの!マークなし
::placeholder薄い灰色文字 {{placeholder}}薄い灰色の線なしなしなし
:read-only薄い灰色文字なしなしなしnot-allowed

基本的には、CSSに定義された擬似クラスに対応させて見た目を設定しています。一覧を見て、「え!?そんなに細かく作る必要ってあるの?」と思う人もいるかもしれません。しかし、前にも述べたように、限られた対話手段のなかで、利用者とのコミュニケーションを実現させるためには、アクションに対する丁寧なレスポンスが必要になってきます。

これはデザイン段階の話になりますが、UI作成者が画面に向かってモクモクと作業していると、知らぬ間に、利用者の行動を事前に確定した内容でUIを作り始めてしまうことがあります。このような固定された筋書きのある状態でUIを作ってしまうと、そこには生身の利用者が存在しなくなってしまい、代わりに、UI提供側にとって都合よく行動してくれる仮想的な利用者が居座ってしまいます。

答えがわかっている状態でUIを操作すると、UIが返却する細かなレスポンスが無駄に感じられてきてしまい、結果的に短縮されたやり取りを求めてしまいがちです。そうなってしまうと、もはやそれは利用者との対話ではなく、無機質な機械同士による機械信号の応酬になってしまいます。

本来、生身の人間の行動は未来が確定していません。次の行動が確定していない状態でお互いの認識を合わせながら対話をスムーズに進めるためには、前回の記事で例に挙げたコンシェルジュと宿泊者のやり取りのように、逐一返される細かなレスポンスを頼りにする必要があります。特に、対話手段の限られているコンピュターがそれを実現しようとするのであれば、なおさらのことです。

擬似クラスで考えるレスポンス

WebサイトやWebアプリケーションはブラウザ上で動作しますが、要素の見た目やレイアウトを実装するCSSには、要素の状態を利用者へ伝達するために、疑似クラスというセレクターを備えています。たとえば、疑似クラスには:hover:disabledなどのように、よく知られるセレクターの他にも多くの状態が定義されていますので、これを利用者との対話粒度として利用します。

先ほどの図にある疑似クラスを、いくつか取り上げて解説します。

button:active

図:button:activeなボタン要素の状態を示す図。「Button - Fill/:active」と表示され、ボタンがactive状態であることを示している。中央に青色のボタンが表示されており、ボタンには白色のテキストで「{{button.text}}」と表示され、左側には白色のアイコンがある。ホバーしたマウスポインターは手の形になっている。

:activeという疑似クラスの存在自体はよく知られていますが、デザイン指定から漏れていることが少なくありません。:active疑似クラスは、マウスのボタンを押し込んでいる最中に適用されます。

たとえばクリック操作であった場合、マウスのボタンを押し込んでいる時間は非常に短いものです。大体の場合は、マウスのボタンの押し込み状態が解除されたタイミングで、次のレスポンスが実施されるため、:activeの状態は瞬時に次の動作に切り替わってしまいます。そのため、:activeの状態がなかったとしてもボタン操作は成立すると考え、重要視されないことがしばしばです。

しかし、利用者との対話を目指すならば、:activeな状態にもレスポンスを設定するのが望ましいでしょう。それは、「あなたのクリック、ちゃんと押せてますよ」というレスポンスを利用者へ応答するためです。

物理的なボタンを想像してみてください。そこには、押してもスカスカと感触の乏しいボタンと、押されるとカチリと振動のフィードバックがあるボタンがあります。2つとも押せばちゃんと利用者のアクションを受け付けてくれますが、どちらがよりボタンとして押した実感があるかは自明ですね。

:focus:hover

図:input-type-text:focus:hoverなテキスト入力要素の状態を示す図。「input-type-text/:focus:hover」と表示され、この状態がフォーカスとホバーの同時適用状態であることを示している。中央に表示された入力フィールドは、青色の細めの枠線と濃紺の太めの枠線で囲まれており、内部には灰色の背景に黒色のテキストで「{{value}}」と表示されている。Iビームカーソルがフィールド内に表示されている。

フォーカスは要素が選択状態にあることを示すもので、ホバーはカーソルが該当要素に侵入したことを知らせるレスポンスです。これらは個別に操作することができて、2つの状態を同時に発生させることが可能です。

よくある失敗例として、フォーカスリングがホバー時のデザインを打ち消していることがあります。ホバー時のデザインが、テキスト入力欄の枠線の色変化のみで作られている場合、同じ入力欄にフォーカスが当たっていると、フォーカスリングは要素の前面に被さって表示されます。それによってテキスト入力欄の枠線が隠されてしまい、利用者はホバー時のレスポンスを受け取ることができないといった現象です。

利用者のアクションは多様で、さまざまな手段やタイミングでUIにアクセスを試みます。ですので、UI側も多様な操作をなるべく取りこぼさないように、複合的な状態への配慮もしていけると良いでしょう。

:valid、:invalid

図:input-type-email要素のvalid状態とinvalid状態を示す図。2つのテキストフィールドが並んでいる。左側のフィールドはテキストで「input-type-email/:valid」と表示されている。緑色の枠で囲まれた入力フィールドが表示され、内部には灰色の背景に黒色のテキストで「hoge@example.com」と表示されている。メールアドレスの右側には緑色のチェックマークアイコンがある。右側のフィールドはテキストで「input-type-email/:invalid」と表示されている。オレンジ色の枠で囲まれた入力フィールドが表示され、内部には灰色の背景に黒色のテキストで「hoge0example.com」と表示されている。メールアドレスの右側にはオレンジ色のエクスクラメーションマークアイコンがある。

:valid:invalidという擬似クラスも対話に利用することができます。いずれも、利用者が入力した内容を検証するもので、:validは入力された値が、受け取り側が要求する形式に合致していることを伝えます。反対に、:invalidは入力された値が要求した形式に合致していないことを伝達します。

:invalidの状態は、発生した何かしらの問題を利用者へ伝えようとすることから、いわゆるエラー表示と同一視してしまうかもしれませんが、:invalidとエラーのレスポンスは違うものだと認識してUIを検討するのが望ましいでしょう。

それは、事前の注意喚起事後の結果伝達の違いによるものです。

:invalidという擬似クラスは、利用者が入力した内容の不備をコンピュター側が発見して指摘するもので、「このままでは失敗してしまいますよ」ということを事前に伝達しています。

一方で、エラーは利用者から受け取ったアクションが、プログラムや通信の経路で発生した問題により実行中の処理が失敗した事実を、利用者へ事後に伝達しています。

これらをコンピューター側の視点で見ると、両方とも失敗と捉えることが可能なため、一括りにできそうに見えますが、利用者の視点から見た場合には、事前と事後のタイミングの違いがあります。

再びコンシェルジュの例で、住所氏名を用紙に書き込んでもらうシーンを考えてみると、事前の注意喚起は、お客が書き入れる前に「あっ、こちらはカタカナでお願いいたします」になるでしょうし、事後の結果伝達は、お客が一通り書き入れて、受付が完了した後に「誠に申し訳ありません…今回は定員に達してしまっていたようで…」という対応になるでしょう。このように、応答の変化に繋がってきます。

擬似クラス以外のレスポンス

ここまで解説した擬似クラスは、利用者のアクションに直接紐づいたレスポンスでした。一方で、WebサイトやWebアプリケーションには、間接的なレスポンスも存在します。

それは、UIが窓口となり利用者のアクションをいったん受け付け、その後、APIを介してサーバーとの通信を行い、最終的な結果を利用者へ応答する場合に発生します。

APIを介したレスポンスは、通信環境やサーバーの処理速度や稼働状況によって左右されるため、最終的なレスポンスまでに時間がかかってしまう場合があります。そうすると、利用者側に待機時間が発生してしまうため、現在状況を明示する対応が必要になってきます。

現在状況を明示するレスポンス

図:ユーザーのアクションとウェブリクエストのフローを示す図。左側には手を挙げた人のアイコンがあり、中央にはラップトップのアイコン、右側には地球のアイコンが配置されている。人のアイコンからラップトップに向かって「アクション」という矢印が描かれ、ラップトップから人のアイコンに向かって「レスポンス」という矢印が描かれている。同様に、ラップトップから地球に向かって「リクエスト」という矢印が描かれ、地球からラップトップに向かって「レスポンス」という矢印が描かれている。ラップトップの上にはピンク色のテキストで「ちょっとまってね」と書かれている。

API通信に関連したUIの状態としては、BusyDoneErrorが考えられます。このような、APIとの通信に関する状態は、擬似クラスには用意されていませんが、間接的なやり取りとして利用者へレスポンスを返す必要があります。これは、前回の記事で解説したバトンの所在を明確にするに該当する内容です。利用者のアクションに対してUIが即答できない場合、「ちょっとまってね」「今やっているよ」というような感じで、とりあえずの応答をしつつも、まだバトンはコンピューター側にあることを利用者へ伝達します。

Busy、Done、Error

図:ボタン要素の「Busy」「Done」「Error」の状態を示す図。左から順に3つのボタンが並んでいる。左側のボタンはBusy状態を表す。ボタンは灰色で、「{{button.text}}」と白色のテキストが表示されており、テキストの左側には回転する矢印のアイコンがある。中央のボタンはDone状態を表す。ボタンは灰色で、「{{button.text}}」と白色のテキストが表示されており、テキストの左側には白色のチェックマークアイコンがある。右側のボタンはError状態を表す。ボタンはピンク色で、「{{button.text}}」と白色のテキストが表示されており、テキストの左側には白色のエクスクラメーションマークアイコンがある。ボタンの下には「{{error.message}}」とピンク色のテキストが表示されている。

図にはBusyとDone、それとErrorのボタンが並んでいます。ボタンの見た目としては特別難しいところはありません。

Busyは、バトンがまだコンピューター側にあることを伝達するためにスピナーがグルグルと回って、APIからの応答を待機します。今回はたまたまボタン要素の例ですが、もう少し大きな単位で実施される部品の通信だったとしても同様で、待機状態を表現します。

Doneは、処理が正常に終了したことを利用者へ伝達します。一応、スピナーがクルクル回ったあとに、Doneの状態を省略してボタン要素をデフォルトの状態に戻すことで、暗黙的に処理の完了としてしまうことも可能だとは思います。ですが、この対応だと、客に何かを頼まれて黙って実行するだけの「無言のコンシェルジュ」がやはり誕生してしまうので、丁寧な対応をするのであれば、Doneのレスポンスが返せるのが望ましいでしょう。

最後にErrorです。処理に失敗した場合は、その事実を利用者へ伝達します。エラーを伝達する場合は、その事実だけでなく、利用者が次に実行すべき行動も合わせて伝達できると良いでしょう。

そして、API通信が関わる操作の一連の流れを連結させた例が、次のボタンの図になります。バトンの所在を明確にしつつ、細かくレスポンスを返し、大げさな変化はないが、利用者が注目している箇所の周辺で、レスポンスを実施しています。

API通信が関わる操作におけるボタンの変化

図:ボタンの状態変化を示す図。2列に分かれ、それぞれ左右に3つずつ縦にボタンが並んでいる。左列の一番上には「写真を保存する」という青色のボタンが表示され、ボタンには白色のアイコンとテキストが表示されており、ホバー状態でマウスポインターが手の形になっている。このボタンから下に向かって「クリック」と添えられた矢印があり、灰色の「保存しています…」というボタンに変わり、処理中(Busy)になることを示している。Busy状態のボタンからは、「完了」と添えられた矢印があり、処理が完了した後に表示される「保存されました!」という灰色のボタンの完了(Done)状態のボタンへ伸びている。右列には、左列と同様に「写真を保存する」という青色のボタンがホバー状態で表示されており、クリック後に灰色の「保存しています…」という状態を経て、矢印が下に向かって描かれ、処理が失敗するとピンク色の「エラー」というボタンに変わることが示されている。エラー状態(Error)では、ボタンの下に「保存に失敗しました。再保存してください。」というピンク色のエラーメッセージが表示されている。

まとめ

前後編とやや駆け足でしたが、利用者と対話するUIについて解説しました。コンシェルジュと宿泊者のやり取りをヒントにして、UIの対話方法を紹介しましたが、筆者は常々、WebサイトやWebアプリケーションは、サイト利用者に対してコンシェルジュ的な対応ができることが理想的であろうと思っています。もちろんそれは、UIにコンシェルジュの見た目を投入して、「ご質問は何でしょう?」というフローから開始しましょうということではありません。

UIには、UIなりのコンシェルジュ的な振る舞いがあって、最終的には「利用者の数あるタスクを、多様な方法でもってスムーズに解決に導くこと」をゴールにしています。「なんだかわからないけれど、なんとなくの感じでやってみたら、できちゃった」という感じでしょうか。理想論だよなぁ、という気持ちもあるのですが、利用者とUIとの対話は、利用者をゴールへ導くために必要不可欠な要素だと筆者は考えています。

著者プロフィール

  • URLをコピーしました!
目次