Build lightning-fast Vue apps that only render what is on-screen
Vue-Infinity brings a radical efficiency boost to your UI by applying the same principle that powers 3D engines: if it’s not in visible, it doesn’t get rendered. This lets your app handle hundreds or thousands of elements without bloating memory, janking or killing batteries.
Whether you’re building infinite feeds, carousels, media galleries, or dashboards—Vue-Infinity keeps your app fast, smooth, and efficient.
The gallery-ce
is a web component built on top of the Carousel component that provides an easy way to display a gallery of images with features like lazy loading, responsive layout, and dynamic sizing. It's designed to efficiently handle large collections of images while maintaining smooth performance.
<gallery-ce id="gallery" height="400px" num-cols-to-show="3"></gallery-ce> <script type="module"> import { registerElements } from 'vue-infinity'; registerElements(); const gallery = document.getElementById('gallery'); gallery.updateImages([ 'image1.jpg', 'image2.jpg', 'image3.jpg' ]); </script>
import { useEffect, useRef } from 'react'; import { registerElements } from 'vue-infinity'; registerElements(); function Gallery() { const galleryRef = useRef(null); useEffect(() => { if (galleryRef.current) { galleryRef.current.updateImages([ 'image1.jpg', 'image2.jpg', 'image3.jpg' ]); } }, []); return <gallery-ce ref={galleryRef} height="400px" num-cols-to-show="3" />; }
<script> import { onMount } from 'svelte'; import { registerElements } from 'vue-infinity'; registerElements(); let gallery; onMount(() => { gallery.updateImages([ 'image1.jpg', 'image2.jpg', 'image3.jpg' ]); }); </script> <gallery-ce bind:this={gallery} height="400px" num-cols-to-show="3" />
<template> <gallery-ce ref="galleryRef" height="400px" :num-cols-to-show="3" /> </template> <script setup> import { ref, onMounted } from 'vue'; import { registerElements } from 'vue-infinity'; registerElements(); const galleryRef = ref(null); onMounted(() => { galleryRef.value.updateImages([ 'image1.jpg', 'image2.jpg', 'image3.jpg' ]); }); </script>Prop Type Default Description
items
String (JSON) '[]'
Array of image URLs or objects with url
, title
, and alt
properties height
String '400px'
Height of the gallery container width
String '100%'
Width of the gallery container num-cols-to-show
Number 1
Number of columns to show (can be fractional for partial items) num-rows-to-show
Number 1
Number of rows to show gap
String '1rem'
Gap between items vertical-scroll
Boolean false
Whether to scroll vertically instead of horizontally Method Parameters Description updateImages
newItems
(Array or JSON string) Update the gallery with new images scrollToItem
itemIndex
(Number) Scroll to a specific item by index
Note: The registerElements()
function must be called once before using any vue-infinity web components.
The Carousel component works like the Gallery but for any type of content. It provides a flexible way to display any kind of content in a carousel layout with lazy loading and responsive design.
<template> <Carousel :items="items" height="400px" :numColsToShow="3" gap="1rem" > <template #item="{ item, index }"> <div class="carousel-item"> <h3>{{ item.title }}</h3> <p>{{ item.description }}</p> </div> </template> </Carousel> </template> <script setup> import { Carousel } from 'vue-infinity'; const items = [ { title: 'Item 1', description: 'Description 1' }, { title: 'Item 2', description: 'Description 2' }, { title: 'Item 3', description: 'Description 3' } ]; </script>
The InfiniteCarousel works like the Carousel but with the ability to fetch more data as the user scrolls. It integrates with the useInfiniteList
composable to handle data fetching and caching.
import { useInfiniteList } from 'vue-infinity'; const infiniteList = useInfiniteList({ fetchItems: async (page, signal) => { const response = await fetch(`/api/items?page=${page}`, { signal }); return response.json(); }, itemsPerPage: 50, maxPagesToCache: 5 });
<template> <InfiniteCarousel :infinite-list="infiniteList" :height="'50vh'" :width="'100%'" :numColsToShow="3" :numRowsToShow="2" > <template #item="{ item, index }"> <img :src="item.url" :alt="item.title" class="carousel-img"/> </template> </InfiniteCarousel> </template> <script setup> import { useInfiniteList } from 'vue-infinity'; const infiniteList = useInfiniteList({ fetchItems: (page) => fetchPage(page), itemsPerPage: 20, maxPagesToCache: 5 }); </script>
The Ghost component is useful when you want to apply visibility based rendering to anything. It optimizes performance by conditionally rendering its slot content. When off-screen, the content is replaced by a dimensionally-identical placeholder.
<template> <Ghost @on-load="handleLoad" @before-unload="handleBeforeUnload" @on-unload="handleUnload"> <div style="height: 300px; background-color: lightblue;"> This content will be replaced when not visible. </div> </Ghost> </template> <script setup> const handleLoad = () => { console.log('Content is now visible and rendered.'); }; const handleBeforeUnload = () => { console.log('Content is about to be hidden.'); }; const handleUnload = () => { console.log('Content is hidden and replaced by a placeholder.'); }; </script>
<template> <div v-ghost="{ rootMargin: '100px', onLoad: handleLoad, beforeUnload: handleBeforeUnload, onUnload: handleUnload }"> <!-- Heavy content goes here --> </div> </template> <script setup> const handleLoad = () => { console.log('Content is now visible and rendered.'); }; const handleBeforeUnload = () => { console.log('Content is about to be hidden.'); }; const handleUnload = () => { console.log('Content is hidden and replaced by a placeholder.'); }; </script>
The AutoObserver combines a MutationObserver and IntersectionObserver to allow you to track a container's child elements. It automatically handles new elements and cleaning up removed ones.
const containerRef = ref<HTMLElement>(); const { disconnect } = useAutoObserver( containerRef, (entries) => { entries.forEach(entry => { console.log('Element visibility changed:', entry.isIntersecting); }); }, { rootMargin: '200px', threshold: 0.1, filter: el => el.classList.contains('observe-me') } );
Explore the live demo here: https://tewolde.co/vueInfinity/
To run the playground application locally:
New Components and FeaturesGallery Web Component:
v-ghost
directive to optimize performance by automatically unloading off-screen content.InfiniteCarousel
now supports an onGetItemAspectRatio
callback, enabling it to render items with variable heights.v-ghost
directive and the dynamic sizing feature.Apache 2.0 License - https://opensource.org/licenses/Apache-2.0
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4