Présentation de base de la création d'une expérience semblable aux stories Instagram sur le Web.
Dans cet article, je souhaite partager mes réflexions sur la création d'un composant Stories pour le Web qui soit responsif, compatible avec la navigation au clavier et compatible avec tous les navigateurs.
Si vous préférez une démonstration pratique de la création de ce composant Stories, consultez l'atelier de programmation sur le composant Stories.
Si vous préférez les vidéos, voici une version YouTube de ce post :
Présentation
Deux exemples populaires d'expérience utilisateur de Stories sont les Stories Snapchat et les Stories Instagram (sans parler des flottes). En termes d'expérience utilisateur, les stories sont généralement un modèle réservé aux mobiles et centré sur les gestes de tapotement pour naviguer entre plusieurs abonnements. Par exemple, sur Instagram, les utilisateurs ouvrent la story d'un ami et parcourent les images qu'elle contient. Ils le font généralement pour plusieurs amis à la fois. En appuyant sur le côté droit de l'appareil, l'utilisateur passe à la story suivante de cet ami. En balayant l'écran vers la droite, l'utilisateur passe à un autre ami. Un composant Story est assez semblable à un carrousel, mais il permet de naviguer dans un tableau multidimensionnel plutôt que dans un tableau unidimensionnel. C'est comme s'il y avait un carrousel dans chaque carrousel. 🤯
2e carrousel "empilé" de stories
👍 Liste dans une liste, c'est-à-dire un tableau multidimensionnel
Choisir les bons outils pour la tâche
Dans l'ensemble, j'ai trouvé ce composant assez simple à créer, grâce à quelques fonctionnalités essentielles de la plate-forme Web. Découvrons-les ensemble.
Grille CSS
Notre mise en page s'est avérée être un jeu d'enfant pour CSS Grid, car il est équipé de moyens puissants pour gérer le contenu.
Mise en page de Friends
Notre wrapper de composant .stories principal est une vue à défilement horizontal orientée mobile :
.stories {
inline-size: 100vw;
block-size: 100vh;
display: grid;
grid: 1fr / auto-flow 100%;
gap: 1ch;
overflow-x: auto;
scroll-snap-type: x mandatory;
overscroll-behavior: contain;
touch-action: pan-x;
}
/* desktop constraint */
@media (hover: hover) and (min-width: 480px) {
max-inline-size: 480px;
max-block-size: 848px;
}
Décomposons cette mise en page grid :
- Nous remplissons explicitement la fenêtre d'affichage sur mobile avec
100vhet100vw, et limitons la taille sur ordinateur. /sépare nos modèles de lignes et de colonnesauto-flowse traduit pargrid-auto-flow: column- Le modèle de flux automatique est
100%, qui correspond ici à la largeur de la fenêtre de défilement.
Sur un téléphone mobile, imaginez que la taille de la ligne correspond à la hauteur de la fenêtre d'affichage et que chaque colonne correspond à la largeur de la fenêtre d'affichage. Pour reprendre l'exemple des stories Snapchat et Instagram, chaque colonne correspondra à la story d'un ami. Nous voulons que les stories des amis continuent en dehors de la fenêtre d'affichage pour que nous puissions faire défiler la page. La grille créera autant de colonnes que nécessaire pour disposer votre code HTML pour chaque story d'ami, créant ainsi un conteneur de défilement dynamique et responsif. Grid nous a permis de centraliser l'ensemble de l'effet.
Empilables
Pour chaque ami, nous avons besoin de ses stories dans un état prêt pour la pagination. En prévision de l'animation et d'autres motifs amusants, j'ai choisi une pile. Quand je parle de pile, je veux dire que vous regardez un sandwich d'en haut, et non de côté.
Avec la grille CSS, nous pouvons définir une grille à cellule unique (c'est-à-dire un carré), où les lignes et les colonnes partagent un alias ([story]), puis chaque enfant est attribué à cet espace à cellule unique avec alias :
.user {
display: grid;
grid: [story] 1fr / [story] 1fr;
scroll-snap-align: start;
scroll-snap-stop: always;
}
.story {
grid-area: story;
background-size: cover;
…
}
Cela permet à notre code HTML de contrôler l'ordre d'empilement et de conserver tous les éléments dans le flux. Notez que nous n'avons pas eu besoin de modifier le positionnement absolute ou z-index, ni de corriger la boîte avec height: 100% ou width: 100%. La grille parente définissait déjà la taille de la fenêtre d'affichage de l'image de la story. Il n'était donc pas nécessaire d'indiquer à ces composants de la story de la remplir.
Points d'ancrage du défilement CSS
La spécification CSS Scroll Snap Points permet de verrouiller facilement des éléments dans la fenêtre d'affichage lors du défilement. Avant l'existence de ces propriétés CSS, vous deviez utiliser JavaScript, et c'était… délicat, pour ne pas dire plus. Consultez l'article Introducing CSS Scroll Snap Points (Présentation des points d'ancrage de défilement CSS) de Sarah Drasner pour découvrir comment les utiliser.
scroll-snap-points.
Sans cela, les utilisateurs peuvent faire défiler l'écran librement, comme d'habitude. Avec cette option, le navigateur s'arrête brièvement sur chaque élément.
.stories { display: grid; grid: 1fr / auto-flow 100%; gap: 1ch; overflow-x: auto; scroll-snap-type: x mandatory; overscroll-behavior: contain; touch-action: pan-x; }
.user { display: grid; grid: [story] 1fr / [story] 1fr; scroll-snap-align: start; scroll-snap-stop: always; }
J'ai choisi les points d'ancrage de défilement pour plusieurs raisons :
- Accessibilité sans frais. La spécification des points d'ancrage de défilement indique que l'appui sur les touches Flèche vers la gauche et Flèche vers la droite doit permettre de parcourir les points d'ancrage par défaut.
- Une spécification en pleine croissance. La spécification Scroll Snap Points bénéficie constamment de nouvelles fonctionnalités et améliorations, ce qui signifie que mon composant Stories ne fera probablement que s'améliorer à partir de maintenant.
- Facilité d'implémentation : Les points d'ancrage du défilement sont pratiquement conçus pour le cas d'utilisation de la pagination horizontale tactile.
- Inertie de style plate-forme libre. Chaque plate-forme défile et s'arrête selon son propre style, contrairement à l'inertie normalisée, qui peut avoir un style de défilement et d'arrêt inhabituel.
Compatibilité multinavigateur
Nous avons testé Opera, Firefox, Safari et Chrome, ainsi qu'Android et iOS. Voici un bref aperçu des fonctionnalités Web pour lesquelles nous avons constaté des différences de capacités et de compatibilité.
Cependant, certaines règles CSS n'ont pas été appliquées, de sorte que certaines plates-formes ne bénéficient pas actuellement des optimisations de l'expérience utilisateur. J'ai apprécié de ne pas avoir à gérer ces fonctionnalités et je suis convaincu qu'elles finiront par être disponibles sur d'autres navigateurs et plates-formes.
scroll-snap-stop
Les carrousels sont l'un des principaux cas d'utilisation de l'expérience utilisateur qui ont motivé la création de la spécification des points d'ancrage de défilement CSS. Contrairement aux stories, un carrousel n'a pas toujours besoin de s'arrêter sur chaque image après qu'un utilisateur a interagi avec lui. Il peut être acceptable ou encouragé de faire défiler rapidement le carrousel. En revanche, il est préférable de parcourir les stories une par une, et c'est exactement ce que propose scroll-snap-stop.
.user {
scroll-snap-align: start;
scroll-snap-stop: always;
}
Au moment de la rédaction de cet article, scroll-snap-stop n'est compatible qu'avec les navigateurs basés sur Chromium. Consultez la section Compatibilité du navigateur pour en savoir plus. Toutefois, cela ne bloque pas le processus. Cela signifie simplement que sur les navigateurs non compatibles, les utilisateurs peuvent accidentellement ignorer un ami. Les utilisateurs devront donc être plus prudents, ou nous devrons écrire du code JavaScript pour nous assurer qu'un ami ignoré n'est pas marqué comme vu.
Pour en savoir plus, consultez les spécifications.
overscroll-behavior
Vous est-il déjà arrivé de faire défiler une fenêtre modale et de voir soudainement le contenu derrière la fenêtre modale défiler ?
overscroll-behavior permet au développeur de piéger ce défilement et de ne jamais le laisser s'échapper. Il est idéal pour toutes sortes d'occasions. Mon composant Stories l'utilise pour empêcher les gestes de balayage et de défilement supplémentaires de quitter le composant.
.stories {
overflow-x: auto;
overscroll-behavior: contain;
}
Safari et Opera étaient les deux navigateurs qui ne prenaient pas en charge cette fonctionnalité, et ce n'est pas un problème. Ces utilisateurs bénéficieront d'une expérience de défilement hors limites à laquelle ils sont habitués et ne remarqueront peut-être jamais cette amélioration. Personnellement, je l'apprécie beaucoup et j'aime l'inclure dans presque toutes les fonctionnalités de défilement excessif que j'implémente. Il s'agit d'un ajout inoffensif qui ne peut qu'améliorer l'expérience utilisateur.
scrollIntoView({behavior: 'smooth'})
Lorsqu'un utilisateur appuie ou clique et qu'il a atteint la fin de l'ensemble de stories d'un ami, il est temps de passer à l'ami suivant dans l'ensemble de points d'ancrage de défilement. Avec JavaScript, nous avons pu référencer l'ami suivant et demander à ce qu'il soit affiché. La prise en charge des principes de base est excellente : tous les navigateurs ont fait défiler l'élément pour l'afficher. Mais tous les navigateurs ne l'ont pas fait 'smooth'. Cela signifie simplement qu'il est affiché par défilement au lieu d'être ancré.
element.scrollIntoView({
behavior: 'smooth'
})
Safari était le seul navigateur à ne pas accepter behavior: 'smooth' ici. Consultez la section Compatibilité du navigateur pour en savoir plus.
Pratique
Maintenant que vous savez comment j'ai fait, comment feriez-vous ? Diversifions nos approches et découvrons toutes les façons de créer sur le Web. Créez une démo, tweetez-moi votre version et je l'ajouterai à la section Remix de la communauté ci-dessous.
Remix par la communauté
- @geoffrich_ avec Svelte : code
- @GauteMeekOlsen avec Vue : démo et code
- @AnaestheticsApp avec Lit : code