L’infinite scroll (défilement infini) transforme l’expérience utilisateur en chargeant du contenu de façon fluide, sans pagination intrusive. Grâce à Inertia.js v2+, cette fonctionnalité est désormais native, performante et facile à implémenter dans une stack Laravel + Vue 3.
Contrairement aux solutions manuelles (gestion d’API, état, scroll, erreurs), Inertia.js fournit une intégration full-stack cohérente : le backend prépare les données, le frontend les consomme intelligemment — avec fusion automatique, synchronisation d’URL, et gestion fine du chargement.
Sommaire
- Pourquoi utiliser l’infinite scroll ?
- Prérequis techniques
- Configuration côté serveur (Laravel)
- Mise en place côté client (Vue 3)
- Fonctionnalités avancées
- Bonnes pratiques
- Conclusion
Pourquoi utiliser l’infinite scroll ?
L’infinite scroll améliore :
- L’engagement utilisateur : pas de clics répétitifs sur « page suivante ».
- La fluidité : le contenu arrive naturellement au scroll.
- La modernité : attendu sur les réseaux sociaux, blogs, marketplaces, chats.
⚠️ À utiliser avec discernement : il n’est pas adapté à tous les cas (ex. résultats de recherche paginés où la navigation précise est utile).
Prérequis techniques
Assurez-vous d’utiliser les versions minimales suivantes :
- Frontend :
@inertiajs/vue3 ≥ v2.2.0
- Backend :
inertiajs/inertia-laravel ≥ v2.0.10
Mettez à jour si nécessaire :
npm install @inertiajs/vue3@latestcomposer require inertiajs/inertia-laravel:^2.0
Configuration côté serveur (Laravel)
Utilisez Inertia::scroll()
pour préparer vos données paginées. Cette méthode :
- Normalise les métadonnées de pagination (
next
,prev
,current_page
, etc.) - Active la fusion automatique côté frontend (ajout, pas remplacement)
use Inertia\Inertia; Route::get('/blog', function () { $posts = Post::published() ->with('category') ->latest() ->paginate(6); return Inertia::render('Blog/Index', [ 'posts' => Inertia::scroll($posts), ]);});
✅ Compatible avec :
paginate()
simplePaginate()
cursorPaginate()
- Eloquent API Resources
💡 Astuce : Si vous filtrez les données (ex. par catégorie), réinitialisez le scroll avec
reset: ['posts']
dans vos requêtes Inertia :
router.visit('/blog', { data: { category: 'dev' }, reset: ['posts'] });
Mise en place côté client (Vue 3)
Le composant <InfiniteScroll>
gère tout : détection du scroll, chargement, fusion.
🔹 Structure de base
<template> <InfiniteScroll data="posts"> <article v-for="post in posts.data" :key="post.id"> {{ post.title }} </article> </InfiniteScroll></template> <script setup>import { InfiniteScroll } from '@inertiajs/vue3'</script>
Le prop
data="posts"
correspond à la clé utilisée dansInertia::render([... 'posts' => ...])
.
Fonctionnalités avancées
1. Chargement anticipé (buffer)
Charge le contenu avant d’atteindre la fin :
<InfiniteScroll data="posts" :buffer="800" />
Plus la valeur est élevée, plus le chargement est précoce — mais risque de charger du contenu inutile.
2. Synchronisation d’URL
Par défaut, l’URL est mise à jour avec ?page=2
, ?page=3
, etc., selon la page la plus visible.
Désactivez-le pour du contenu secondaire :
<InfiniteScroll data="comments" preserve-url />
3. Mode manuel après N pages
Idéal pour limiter les appels automatiques :
<InfiniteScroll data="posts" :manual-after="3"> <template #next="{ loading, fetch, hasMore, manualMode }"> <button v-if="manualMode && hasMore" @click="fetch" :disabled="loading"> <Loader2 v-if="loading" class="animate-spin" /> {{ loading ? 'Chargement...' : 'Charger plus' }} </button> </template></InfiniteScroll>
Les slots
#previous
et#next
reçoivent :
loading
,loadingNext
,loadingPrevious
fetch()
→ déclenche le chargementhasMore
,hasNext
,hasPrevious
manualMode
/autoMode
4. Slot de chargement par défaut
<template #loading> <div class="text-center py-4 text-muted">Chargement des articles…</div></template>
Affiché pendant le chargement automatique si aucun slot before
/after
n’est fourni.
5. Chargement dans les deux sens
Par défaut, le composant charge vers le haut et vers le bas.
Restreignez la direction :
<!-- Seulement vers le bas --><InfiniteScroll data="posts" only-next /> <!-- Seulement vers le haut --><InfiniteScroll data="messages" only-previous />
6. Mode inversé (chat, timeline)
Pour les interfaces où les nouveaux éléments sont en bas :
<InfiniteScroll data="messages" reverse :auto-scroll="false"> <!-- Messages du plus ancien au plus récent --></InfiniteScroll>
⚠️ Triez vos données correctement côté serveur. Le composant gère le scroll, pas l’ordre.
7. Conteneurs de scroll personnalisés
Fonctionne dans n’importe quel conteneur scrollable :
<div style="height: 500px; overflow-y: auto;"> <InfiniteScroll data="posts">...</InfiniteScroll></div>
8. Plusieurs scrolls sur une même page
Évitez les conflits d’URL avec pageName
:
// Backend'users' => Inertia::scroll(User::paginate(pageName: 'users')),'orders' => Inertia::scroll(Order::paginate(pageName: 'orders')),
→ URL : ?users=2&orders=3
9. Accès programmatique
<script setup>import { ref } from 'vue'const scrollRef = ref() const loadMore = () => scrollRef.value?.fetchNext()</script> <template> <button @click="loadMore">Charger plus</button> <InfiniteScroll ref="scrollRef" data="posts" manual /></template>
Méthodes exposées : fetchNext()
, fetchPrevious()
, hasNext()
, hasPrevious()
.
10. Ciblage d’éléments (tables, listes complexes)
Pour les <table>
, <ul>
, etc. :
<InfiniteScroll data="users" items-element="#table-body"> <table> <tbody id="table-body"> <tr v-for="user in users.data" :key="user.id">...</tr> </tbody> </table></InfiniteScroll>
Ou avec des ref
:
<InfiniteScroll :items-element="() => tableBody" :start-element="() => tableHeader" :end-element="() => tableFooter">
Bonnes pratiques
Recommandation | Raison |
---|---|
6–10 éléments/page | Équilibre UX/performance |
Optimisez les requêtes (with() , select() ) |
Réduisez la taille des payloads |
Prévoyez un fallback (bouton "Charger plus") | Accessibilité (JS désactivé, préférences utilisateur) |
Évitez les composants lourds dans les listes | Performance du scroll |
Réinitialisez avec reset lors de changement de filtre |
Évite le mélange de résultats |
Testez sur mobile | Le scroll peut être plus sensible |
Conclusion
Avec Inertia::scroll()
et <InfiniteScroll>
, vous bénéficiez d’une solution full-stack cohérente, performante et riche en fonctionnalités, sans avoir à gérer manuellement les appels API, la fusion d’état ou la gestion du scroll.
C’est l’outil idéal pour :
- Blogs et flux d’articles
- Réseaux sociaux
- Marketplaces
- Interfaces de chat
- Timelines d’activité
Grâce à Inertia.js, l’infinite scroll devient simple, fiable et maintenable — même dans des applications complexes.
Ressources officielles
✨ Prêt à moderniser votre interface ? Implémentez l’infinite scroll dès aujourd’hui et offrez une expérience utilisateur fluide et engageante.