【WEB版 WEAR】position: sticky で似ているアイテム検索の使いやすい UI/UX を実現する


この記事はZOZOテクノロジーズ #2 Advent Calendar 2019 19日目の記事になります。
昨日は、@saitoryuji さんによる「新卒2年目のエンジニアが単体テストをやってみる」でした。

また、今年は全部で5つのAdvent Calendarが公開されています。

はじめに

最近、スマートフォンのWEB版 WEARで、コーデ画像をもとにAIがアイテムを検出し、さらにそのアイテムに似ているアイテムを検出して一覧で表示する機能をリリースしました

この機能をWEBで実装するにあたり、使いやすいUI/UXを目指した奮闘記を紹介します!

こんなのをやりたい

まず、大まかな要件は以下の通りです。

  1. コーデ画像の左下のをタッチすると検索スクリーンが下から上がってくる
  2. コーデ画像からアイテムが検出された箇所を「◯」で表示する
  3. スクリーン下部に、選択されたアイテムの「似ているアイテム」の一覧を表示する
  4. スクロールすると「似ているアイテム」の一覧が上がってくる
  5. 「似ているアイテム」の一覧はヘッダーが固定され、一覧内でスクロールできる

 →  →  → 

最初にこの要件を聞いたとき、経験上難しそうだなーと感じたのは、
windowのスクロールとは別に、一覧内もスクロールできるようにしないとけないところでした。
実装自体は可能なのですが、スクロールできる要素の中にスクロールできる要素を配置すると、スクロールしたい方じゃない方がスクロールされるなど、とても使いにくいイメージがありました。。。

今回は上記の要件のうち、1、4、5の部分について説明します。
※以下に出てくるソースコードは、説明用のサンプルです。

ボツになった案

それでも、まずは思いついたままに、以下のような構成で実装してみた。
(最初に言っておきますが、これはボツです笑)

実装

HTML
<div id="searchScreen" style="position: relative; transform: translateY(0px);">
    <div id="image" style="position: absolute;">...</div>
    <div id="list">
        <div id="listHead"></div>
        <div id="listBody" style="height: 812px; overflow-y: scroll;">
            <ul>
                <li></li>
                :
            </ul>
        </div>
    </div>
</div>

See the Pen Sample1 by mitanih (@mitanih) on CodePen.

#searchScreen
コーデ画像のボタンのクリックイベントで、下から上がってくる検索スクリーン
下から上げる処理として、CSSアニメーションでtransformtranslateY(100%)からtranslateY(0px)に切り替えて表現する
※marginの切り替えでも表現できるが、残像ができたり動きがカクつくなどの問題があった

#image
検索スクリーン内上部のイメージエリア
windowがスクロールされても固定したいので、position: absoluteを指定して、常に画面の同じ位置にいるようJavaScriptで制御する
※親要素にtranslateを指定しているのでposition: fixedは使えない

#list
検索スクリーン内下部の一覧

#listHead
一覧のヘッダー

#listBody
一覧のボディ
一覧内をスクロールさせるためheightを設定し、overflow-y: scrollを指定

問題点

触ってみて、やっぱり使いにくかった。。。
iOSのSafariで動作確認した範囲ですが、windowをスクロールさせて一覧を上に持っていきたいのに、一覧内がスクロールされてしまったり、慣性スクロールの影響なのか、windowがスクロールして完全に止まらないと、一覧内がスクロールできないなどの現象も起きた。
スクロールしやすいように工夫して、一覧が一番上まで来ていなければ一覧内はスクロールできないようJavaScriptで制御も入れてみたが、スムーズな動きとはいかなかった。
あと、#imageの位置を固定するためスクロールの度にJavaScriptで位置を計算して設定したが、フラフラ動いてなんか変。
何より無理し過ぎな気がしました。。。

採用した方法

いや、もっといい方法はあるはずだ。他のサービスでこんなぎこちないの見たことないぞ。。。
と、いろいろ調べていて、position: stickyに辿り着きました!
Excelの行固定みたいな機能が簡単に実現できるあのスタイルです。

position: stickyの説明
https://developer.mozilla.org/ja/docs/Web/CSS/position

メジャーなiOS、Androidのブラウザ対応も問題なさそう!
https://caniuse.com/#search=sticky

実装

HTML
<div id="searchScreen" style="position: relative; transform: translateY(0px);">
    <div id="image" style="position: sticky;">...</div>
    <div id="list">
        <div id="listHead" style="position: sticky;"></div>
        <div id="listBody">
            <ul>
                <li></li>
                :
            </ul>
        </div>
    </div>
</div>

See the Pen Sample2 by mitanih (@mitanih) on CodePen.

細かい調整は省略しますが、要は#imageと#listHeadにposition: stickyを設定するだけで解決しました!
windowのスクロールで#listが上に来るまでは、#imageがstickyしてくれる。#listが上までくると#listHeadがstickyし、windowのスクロールでそのまま#listBodyが下まで見られる。
まさに理想的なスタイル!
無理していない実装なので動きもスムーズです!

まとめ

JavaScriptやCSSのプロパティを覚えると、自力でゴリゴリ書けちゃうんですが、実機で確認すると動きがぎこちなくてなんか無理してる感じがすることってあると思います。
そんなときは視点を変えてもっとシンプルな方法を探すと、よりよい解決策が見つかるということに気付かされます。
プログラミングって、そんなことのくり返しのような気がする。。。

明日は、@ikkou さんによる「WebAR の現状確認 2019 Winter」です。
お楽しみに~!