ユーザーを「あえて待たせる」UI設計
遅いのは良くないけど、速すぎるのも不安になる。
システムの制作では、ことにつけてパフォーマンスが重視されます。Webサイトならレスポンスタイムやロードタイムはユーザーの離脱率に直結しますし、その他のアプリやシステムでも様々思考を凝らしてなるべく効率的に・高速に処理をするのがベストだというのは共通認識かと思います。それは間違いありません。軽量・高速なものほど、ユーザーの快適性が上がり、ストレスなく作業ができます。
しかし、UIデザインでは、ユーザー体験(UX)の観点からあえて待たせることが重要な場面もあると私は考えています。今回は、最近制作したWebアプリで私が実際にユーザーを待たせる実装にした例を見つつ、よりよいUXについて考えてみたいと思います。
実例① ローディング画面の表示時間
Webサイトを開いた際に全画面にローディングが表示されて、読み込まれるまで操作を受け付けないようなUIがあります。これはどうなのでしょうか?
コンテンツ系のWebサイト
もちろん、ブログやメディアサイトなど不特定多数がアクセスするコンテンツ重視のサイトでは、ページの読み込み時間は命取りです。こういったサイトではローディング画面の表示は極力避けるべきでしょう。
こういったサイトではそもそも表示時間の短縮に注力してローディング画面の必要性が無いようにするのを目標にするべきでしょうし、万が一読み込みに時間がかかる場合でも、ローディング画面にページ本体を隠すより、ローディング画面無しでコンテンツが徐々に表示されていく経過をユーザーに見せるほうが、何が起こっているかを把握できてユーザーのストレスを軽減できるのではないでしょうか(画像の読み込みが多少遅れたところで文章は読めますしね)。
ツールなどのWebアプリ
一方、SPAのWebアプリなど、アセットが膨大でどうしても読み込みに時間を要するシステムの場合は、ローディング画面の導入を検討することは多々あるでしょう。この際、私が重要だと考えているのは、ローディングが完了した直後に画面を切り替えるのではなく、短い一定の時間は必ずローディング画面を表示し続けることです。一見ユーザーを余計待たせるような無駄な行為に思えますが、なぜこれが重要なのでしょうか?
例えば、高速回線を利用していて、アセットの読み込みが一瞬で完了した場合を考えてみましょう。ローディング画面が一瞬だけ表示されてすぐに消えてしまうと、ユーザーはその画面に何が表示されていたのかを確認できず、余計なフラストレーション(というには小さすぎるかもしれないですが…)を溜めてしまう可能性があります。少なくとも、「あれ、今なんか書いてあった?」と気になってしまうのではないでしょうか。
そこで、読み込みの完了状況にかかわらず、一定時間ローディング画面を表示し続けることで、ユーザーに「処理が進行中である」という安心感を与え、不要なストレスを感じさせずにアプリケーションを利用してもらうことができます。もちろん、不必要に長くすると本当に何の意味もなくなるので、あくまでローディング画面を認識できるくらいで留めておく必要はあるでしょう。
実例
私が制作に携わった大阪公立大学の学内向けアプリ「情報基盤センター Tools」のローディング画面をご覧ください。
(※画面は開発中のものです。実際の表示とは異なる可能性があります)
このWebアプリはSPA(Single Page Application)、つまりJavaScriptがすべてのUIの表示を担います。すべての必要なJavaScriptファイルが読み込まれ、その実行が完了するまでには少し時間がかかるため、読み込むHTMLファイル側にあらかじめ「Loading...」の画面を入れ、その裏で初期描画を行います。初期描画が完了したら、描画開始から最低でも約1秒間は待ってからLoading画面の要素を削除しています(処理が終わってから1秒待つのではなく、処理が始まってからの時間も織り込んで最低1秒待機するという形)。
これにより、ユーザーにはローディング画面が出ていることを理解できるだけの時間が与えられるので、ストレスなく操作を開始できます。
実際のコード
情報基盤センター Tools で実際に使用している、エントリーポイントのコードです。
async function boot() {
const bootStartedAt = Date.now();
// ... 各種の起動処理 ...
//#region スプラッシュを削除
const bootCompletedAt = Date.now();
function removeSplash(el: HTMLElement) {
el.classList.add('opacity-0');
setTimeout(() => {
el.remove();
}, 500);
}
const splash = document.getElementById('splash');
if (splash) {
// あまりにも早くスプラッシュ画面を消しちゃうと画面がチカチカするので、最低でも1秒は表示する
setTimeout(() => {
removeSplash(splash);
}, Math.max(0, 1000 - (bootCompletedAt - bootStartedAt)));
}
//#endregion
}
boot();
余談ですが、基盤センター Tools のフロントエンドは以下のようなスタックで作られています:
- バンドラ
- Vite
- JSフレームワーク
- Vue.js
- Vue Router
- Vue i18n
- Floating UI(モーダル位置計算)
- Vue.js
- CSSフレームワーク
- UnoCSS
- Bootstrap (フォームコンポーネントのみ)
- 同梱する操作マニュアルサイト
- VitePress
状態管理・日付選択などのコンポーネント・モーダルの管理などについては既存のライブラリを使用せずに内製しており、バンドルサイズの軽減や不要な処理の軽減でアプリの軽量化に貢献しています。今後はこれらの共通のコンポーネント・ユーティリティを非公開のNPMパッケージにまとめて、他のアプリの製作時に呼び出せるようにすることでWebアプリ製作の効率化ができるようにしたいと考えています。
実例② API実行後の待機時間
バックエンド処理の高速化により、データの編集や削除などの処理が一瞬で完了することがあります。しかし、あまりに処理が高速すぎると、ユーザーがボタンを押した瞬間に処理が完了してしまい、本当に処理が実行されたのかどうか不安に感じてしまうかもしれません。
このような場合、私はAPI呼び出し後に一定時間スピナー(ぐるぐる)などを表示し、「処理が確実に行われている」という感覚をユーザーに与えるようにしています。
ただし、頻繁に状態が切り替わる要素(例えば、トグルスイッチを切り替えるたびにAPIが走る場合など)や、バックグラウンドで更新処理が行われることが期待されるようなUIに対してローディングを表示すると、かえって煩わしさを感じさせてしまうため、適切な場面での利用が重要です。また、そもそもAPIの実行に数秒かかるような場合はそれ自体を改善するべきかも(もしくはプログレスバーなどを用いて具体的な進行状況を知らせるUIにする方が良いかも)しれません。
「情報基盤センター Tools」では、データの編集・削除時にローディング表示を挟み、その後完了マークを一定時間表示するように設計しました。実際のAPI処理は約150ms程度で完了していますが、ローディング表示を設けることで、「処理が正しく実行された感」を演出できると考えています。
この実装はMisskeyのUIを参考にさせていただきました
(※画面は開発中のものです。実際の表示とは異なる可能性があります)
まとめ
これらの例からわかるように、UIデザインにおいては必ずしも「速さ」だけが正義というわけではなさそうです。ユーザーの心理状態や操作の流れを考慮し、意図的に「待機時間」を設けることで、ユーザーに生まれる無駄な引っかかりを排除し、より良いUXを提供できる場合があります。
待ちの時間は、ユーザーに操作への確信を持たせるための有効な手段だといえます。ただ、これを導入するかどうか・どこに導入するかは、その場その場の状況に応じて慎重に判断する必要があります。既存のUIや操作フローを理解したうえで、戦略的にユーザーを待たせることで、よりよいユーザー体験を実現できるのではないでしょうか。
Discussion