Infinite scroll is a slick UX pattern that loads content as users scroll—think Instagram or Twitter feeds. In this guide, we’ll implement infinite scroll using Vue 3’s Composition API with the new <script setup>
syntax, ref
, watch
, and onMounted
. No need for external libraries—just Vue and Axios.

🚀 What You’ll Learn
- How to use
<script setup>
in Vue 3 - Fetch paginated data using Axios
- Detect when the user scrolls near the bottom
- Load more content automatically
📦 Prerequisites
- Basic knowledge of Vue 3
- Vue project set up with Vite or Vue CLI
- Axios installed (
npm install axios
)
💡 Setup the Component
<template>
<div ref="scrollContainer" class="scroll-container" @scroll="handleScroll">
<div v-for="student in students" :key="student.id" class="student-card">
{{ student.name }}
</div>
<div v-if="loading" class="loader">Loading...</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import axios from 'axios'
const students = ref([])
const page = ref(1)
const loading = ref(false)
const scrollContainer = ref(null)
const perPage = 10
const fetchStudents = async () => {
loading.value = true
try {
const response = await axios.get(`/api/students?page=${page.value}&limit=${perPage}`)
students.value.push(...response.data.students)
if (response.data.students.length === perPage) {
page.value++
}
} catch (error) {
console.error('Error fetching students:', error)
} finally {
loading.value = false
}
}
const handleScroll = () => {
const container = scrollContainer.value
if (!container) return
const scrollBottom = container.scrollTop + container.clientHeight
const threshold = container.scrollHeight - 100
if (scrollBottom >= threshold && !loading.value) {
fetchStudents()
}
}
onMounted(() => {
fetchStudents()
})
</script>
<style scoped>
.scroll-container {
height: 500px;
overflow-y: auto;
padding: 16px;
border: 1px solid #ccc;
}
.student-card {
padding: 12px;
margin-bottom: 10px;
background-color: #f7f7f7;
border-radius: 6px;
}
.loader {
text-align: center;
padding: 20px;
color: #888;
}
</style>
🧠 Key Takeaways
- We use
ref
to keep track of reactive variables like the page, loading state, and container reference. onMounted
loads the first batch of students.- We manually detect scroll position and trigger
fetchStudents()
when nearing the bottom. - This keeps your app lean and performant—no extra packages!
⚙️ Bonus: Backend Pagination Sample (Laravel)
If your API is Laravel-based, make sure your controller returns paginated results like this:
public function index(Request $request)
{
$limit = $request->get('limit', 10);
$students = Student::paginate($limit);
return response()->json([
'students' => $students->items(),
'total' => $students->total(),
]);
}
🔚 Conclusion
With just Vue 3 core features, you can create a smooth infinite scroll experience. This not only enhances UX but also keeps your frontend performance optimized.
Want this infinite scroll in your next web app? Contact me at developerdalpat@gmail.com or Portfolio and let’s build something amazing together 🚀