Dokonalé scrollování přesně tam, kam uživatel potřebuje
Při vývoji nového košíku Slevomatu jsme čelili řadě výzev. Jedna z nich souvisela s tím, že celý košík byl prezentován na jedné stránce a nové kroky prodlužovaly stránku směrem dolů. Pro uživatele to má ten přínos, že na pozdějších krocích nemusí dohledávat, co v košíku vlastně má, ale stačí se podívat na vrchol stránky.
Celý košík je koncipovaný jako SPA1. I když jsme měli wireframy s návrhem podoby jednotlivých kroků košíku, statický návrh, který sám o sobě vypadá dobře, neposkytuje kompletní obraz o fungování aplikace. Musel jsem přijít na to, jak udělat přechod mezi jednotlivými kroky košíku tak, aby se uživatel hned zorientoval a měl představu, kde se nachází.
V momentě, kdy uživatel vyjádří svůj úmysl (pokračuje v košíku do dalšího kroku, nebo se vrací zpět) by mu aplikace neměla klást žádné překážky a další „úkoly“ před tím, než bude moct pokračovat v tom, co chce udělat. V případě našeho košíku se tedy nabízí automatické scrollování, aby uživatel poté, co klikne na „Pokračovat“, mohl rovnou vybírat platbu a nemusel už sahat na kolečko myši.
První naivní implementace posouvala stránku vždy tak, že horní okraj aktuálního kroku košíku byl srovnaný s horním okrajem viewportu:
Stránka se hýbala pokaždé a někdy urazila i zbytečně dlouhou vzdálenost, což bylo nepříjemné pro oči. Řekl jsem si, že cílem vlastně není, aby se aktuální krok objevil vždy na vrcholu viewportu, ale pouze aby byl celý viditelný a to kdekoli na obrazovce.
První optimalizace spočívala v tom, že pokud už je aktuální krok celý ve viewportu, nemusím scrollovat vůbec. K tomu potřebuji výšku viewportu a relativní pozici prvku vůči němu. Žádné scrollování je nejlepší scrollování!
Pokud tato podmínka neprošla, přistoupil jsem opět k naivnímu scrollu k hornímu okraji. To ale vedlo ke stejně zbytečným a příliš velkým pohybům jako před touto optimalizací. Napadlo mě, že bych mohl nějak pracovat s dolním okrajem prvku a zarovnávat ho ke spodnímu okraji viewportu:
Ale v jakém případě? Nemůžu tak scrollovat pokaždé, protože by to since jakž-takž fungovalo pro přechod do následujících kroků, ale při návratu do předchozích by opět docházelo k většímu pohybu stránky, než je ve skutečnosti potřeba. A to je ten pravý klíč - porovnám vzdálenost, jakou musí stránka cestovat pro zarovnání horního okraje prvku s horním okrajem viewportu a dolního okraje prvku s dolním okrajem viewportu a zascrolluju tam, kam je to blíž!
Ze scrollování na dolní okraje musím ještě vyřadit prvky, které jsou vyšší než celý viewport, protože uživatel by neměl přijít o začátek kroku, kde může být jeho název, vysvětlivky nebo třeba i část formuláře, který musí vyplnit.
Toto řešení se mi už celkem líbilo. Poslední detail, který jsem upravil, byla délka trvání animace. Pro větší vzdálenosti proběhl scroll příliš rychle a výsledný efekt opět nebyl příjemný. Nastavil jsem animaci tedy tak, že pokud během scrollu urazí stránka více jak 60 % viewportu, prodloužím výchozí délku o 30 %:
Mám za to, že nad pozicí při scrollování je potřeba uvažovat vždy a nezůstat u naivního řešení v první ukázce. Věřím, že popsaný postup najde uplatnění nejen u jednostránkových košíků.
Osobně se jako doma cítím spíše při programování backendu, ale baví mě občas skočit i na frontend a vyřešit nějaký zajímavý problém - počítání se souřadnicemi na displeji je úplně jiná liga, než psaní SQL dotazů a plnění šablon2. Minulý týden jsem např. strávil nějakou dobu3 laděním pohybu vinylové desky, aby se plynule zastavovala a rozjížděla v závislosti na kurzoru uživatele.
-
Single-page application – po prvotním načtení už veškerá uživatelova interakce a komunikace se serverem probíhá pomocí AJAXu a nedochází ke znovunačítání stránky, což vede k rychlejší práci s aplikací a zvýšenému uživatelskému komfortu. ↩
-
Samozřejmě, že práce na backendu není jen o tomhle, ale s klientskými aplikacemi si připadám tak nějak blíž lidem 😉 ↩
-
Víc, než jsem ochotný přiznat. ↩