Présentation de base sur la façon de créer une expérience semblable à Instagram Stories sur le Web.
Dans cet article, je souhaite partager ma réflexion sur la création d'un composant Stories pour le Web, qui soit responsif, compatible avec la navigation au clavier et fonctionnel sur 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 cet article :
Présentation
Les stories Snapchat et Instagram (sans oublier les fleets) sont deux exemples populaires d'UX de stories. En termes d'UX, les stories sont généralement un modèle de navigation axé sur le toucher et réservé aux mobiles pour parcourir plusieurs abonnements. Par exemple, sur Instagram, les utilisateurs ouvrent la story d'un ami et parcourent les photos qu'elle contient. Ils ajoutent généralement plusieurs amis à la fois. En appuyant sur le côté droit de l'appareil, l'utilisateur passe à la prochaine story 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 parcourir un tableau multidimensionnel au lieu d'un tableau unidimensionnel. C'est comme s'il y avait un carrousel à l'intérieur de chaque carrousel. 🤯

Deuxième carrousel "empilé" d'histoires
👍 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 !
Grille CSS
Notre mise en page s'est avérée être un jeu d'enfant pour CSS Grid, qui est équipé de puissants outils pour organiser le contenu.
Mise en page "Amis"
Notre wrapper de composant .stories
principal est une vue à défilement horizontal axée sur le 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;
}
Analysons cette mise en page grid
:
- Nous remplissons explicitement la fenêtre d'affichage sur mobile avec
100vh
et100vw
, et nous limitons la taille sur ordinateur. /
sépare nos modèles de lignes et de colonnes.auto-flow
est traduit pargrid-auto-flow: column
- Le modèle de flux automatique est
100%
, qui correspond dans ce cas à 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. En reprenant l'exemple des Stories Snapchat et Instagram, chaque colonne correspondra à la story d'un ami. Nous voulons que les histoires d'amis continuent en dehors de la fenêtre d'affichage afin d'avoir un endroit où faire défiler. Grid créera le nombre de colonnes nécessaires pour mettre en page votre code HTML pour chaque story d'ami, créant ainsi un conteneur de défilement dynamique et réactif. La grille nous a permis de centraliser l'ensemble de l'effet.
Empilement
Pour chaque ami, nous avons besoin de ses histoires 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 dis "empiler", je veux dire comme si vous regardiez un sandwich de haut, et non de côté.
Avec la grille CSS, nous pouvons définir une grille à une seule cellule (c'est-à-dire un carré), où les lignes et les colonnes partagent un alias ([story]
), puis chaque enfant est affecté à cet espace à une seule cellule 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 maintenir tous les éléments dans le flux. Notez que nous n'avons pas eu besoin d'intervenir au niveau du positionnement absolute
ni de z-index
, et que nous n'avons pas eu besoin de corriger les boîtes avec height: 100%
ni width: 100%
. La grille parente a déjà défini la taille de la fenêtre d'affichage de l'image de la story. Il n'est donc pas nécessaire de demander à ces composants de la remplir.
Points d'accrochage de défilement CSS
La spécification CSS Scroll Snap Points permet de verrouiller facilement les é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 le moins. Consultez l'article Introducing CSS Scroll Snap Points (Présentation des points d'accrochage de défilement CSS) de Sarah Drasner pour obtenir une explication détaillée de leur utilisation.
scroll-snap-points
.
Sans cela, les utilisateurs peuvent faire défiler librement l'écran comme d'habitude. Le navigateur se pose délicatement 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'accrochage de défilement pour plusieurs raisons :
- Accessibilité sans frais : La spécification des points d'accroche de défilement indique que, par défaut, les touches Flèche vers la gauche et Flèche vers la droite doivent permettre de parcourir les points d'accroche.
- Une spécification en constante évolution : la spécification des points d'accrochage de défilement reçoit sans cesse de nouvelles fonctionnalités et améliorations. Cela signifie que mon composant Stories ne peut que s'améliorer à partir de maintenant.
- Facilité d'implémentation : Les points d'accrochage de défilement sont pratiquement conçus pour le cas d'utilisation de la pagination horizontale axée sur le tactile.
- Inertie de style plate-forme libre : Chaque plate-forme défile et s'arrête dans son propre style, contrairement à l'inertie normalisée qui peut avoir un style de défilement et d'arrêt étrange.
Compatibilité entre navigateurs
Nous avons effectué des tests sur Opera, Firefox, Safari et Chrome, ainsi que sur Android et iOS. Voici un bref aperçu des fonctionnalités Web pour lesquelles nous avons constaté des différences en termes de capacités et de compatibilité.
Cependant, certains CSS ne s'appliquent pas, ce qui signifie que certaines plates-formes ne bénéficient pas actuellement d'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 ont été l'un des principaux cas d'utilisation de l'UX qui ont conduit à la création de la spécification CSS Scroll Snap Points. Contrairement aux Stories, un carrousel n'a pas toujours besoin de s'arrêter sur chaque image après l'interaction d'un utilisateur. Il peut être acceptable, voire recommandé, de parcourir rapidement le carrousel. Les histoires, en revanche, sont plus adaptées à une navigation individuelle, 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 page Compatibilité des navigateurs pour obtenir les dernières informations. Toutefois, il ne s'agit pas d'un blocage. Cela signifie simplement que sur les navigateurs non compatibles, les utilisateurs peuvent accidentellement passer à côté d'un ami. Les utilisateurs devront donc simplement faire plus attention, 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 la spécification.
overscroll-behavior
Vous êtes-vous déjà retrouvé à faire défiler une boîte de dialogue et à commencer à faire défiler le contenu derrière la boîte de dialogue ?
overscroll-behavior
permet au développeur de piéger ce défilement et de ne jamais le laisser partir. Il convient à toutes sortes d'occasions. Le composant "Mes histoires" l'utilise pour empêcher les balayages et les gestes 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 supportaient pas cette fonctionnalité, et c'est tout à fait normal. 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 suis un grand fan et j'aime l'inclure dans presque toutes les fonctionnalités de dépassement de la limite de défilement que j'implémente. Il s'agit d'un ajout inoffensif qui ne peut qu'améliorer l'UX.
scrollIntoView({behavior: 'smooth'})
Lorsqu'un utilisateur appuie ou clique sur l'ensemble d'histoires d'un ami et qu'il a atteint la fin, il est temps de passer à l'ami suivant dans l'ensemble de points d'accroche de défilement. Avec JavaScript, nous avons pu référencer le prochain ami et demander à ce qu'il soit affiché. La prise en charge des bases est excellente : chaque navigateur l'a fait défiler pour l'afficher. Cependant, tous les navigateurs ne l'ont pas fait 'smooth'
. Cela signifie simplement qu'il est affiché à l'écran au lieu d'être ancré.
element.scrollIntoView({
behavior: 'smooth'
})
Safari était le seul navigateur à ne pas prendre en charge behavior: 'smooth'
. Consultez la page Compatibilité des navigateurs pour obtenir les dernières informations.
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 un remix sur Glitch, tweetez-moi votre version et je l'ajouterai à la section Remix de la communauté ci-dessous.
Remix de la communauté
- @geoffrich_ avec Svelte : démo et code
- @GauteMeekOlsen avec Vue : démonstration et code
- @AnaestheticsApp avec Lit : démo et code