universal-virtual-scroll
v1.0.2
Published
A lightweight and framework-agnostic virtual scrolling library.
Maintainers
Readme
universal-virtual-scroll
A lightweight and framework-agnostic virtual scrolling library for efficiently rendering large lists and grids with smooth performance.
Installation
npm install universal-virtual-scrollImport
import {
UniversalVirtualScroll
} from 'universal-virtual-scroll';Angular Example
app.component.html
<div #viewport class="viewport">
<div
#content
[style.paddingTop.px]="paddingTop"
[style.paddingBottom.px]="paddingBottom">
@for (item of visibleItems; track item.name) {
<div class="card">
{{ item.name }}
</div>
}
</div>
</div>app.component.ts
import {
AfterViewInit,
Component,
ElementRef,
ViewChild
} from '@angular/core';
import {
UniversalVirtualScroll
} from 'universal-virtual-scroll';
@Component({
selector: 'app-root',
standalone: true,
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent
implements AfterViewInit {
@ViewChild('viewport')
viewport!: ElementRef;
@ViewChild('content')
content!: ElementRef;
visibleItems: any[] = [];
paddingTop = 0;
paddingBottom = 0;
items = Array.from(
{ length: 100000 },
(_, i) => ({
name: `Item ${i + 1}`
})
);
ngAfterViewInit(): void {
new UniversalVirtualScroll({
viewport:
this.viewport.nativeElement,
content:
this.content.nativeElement,
items: this.items,
itemHeight: 100,
itemWidth: 200,
onUpdate: (
items,
top,
bottom
) => {
this.visibleItems = items;
this.paddingTop = top;
this.paddingBottom = bottom;
}
});
}
}app.component.css
.viewport {
height: 100vh;
overflow-y: auto;
}
.card {
height: 100px;
}React Example
App.jsx
import {
useEffect,
useRef,
useState
} from 'react';
import {
UniversalVirtualScroll
} from 'universal-virtual-scroll';
function App() {
const viewportRef = useRef(null);
const contentRef = useRef(null);
const [visibleItems, setVisibleItems] =
useState([]);
const [paddingTop, setPaddingTop] =
useState(0);
const [paddingBottom, setPaddingBottom] =
useState(0);
const items = Array.from(
{ length: 100000 },
(_, i) => ({
name: `Item ${i + 1}`
})
);
useEffect(() => {
const virtualScroll =
new UniversalVirtualScroll({
viewport:
viewportRef.current,
content:
contentRef.current,
items,
itemHeight: 100,
itemWidth: 200,
onUpdate: (
items,
top,
bottom
) => {
setVisibleItems(items);
setPaddingTop(top);
setPaddingBottom(bottom);
}
});
return () => {
virtualScroll.destroy();
};
}, []);
return (
<div
ref={viewportRef}
className="viewport">
<div
ref={contentRef}
style={{
paddingTop,
paddingBottom
}}>
{
visibleItems.map(item => (
<div
key={item.name}
className="card">
{item.name}
</div>
))
}
</div>
</div>
);
}
export default App;App.css
.viewport {
height: 100vh;
overflow-y: auto;
}
.card {
height: 100px;
}Next.js Example
app/page.jsx
'use client';
import {
useEffect,
useRef,
useState
} from 'react';
import {
UniversalVirtualScroll
} from 'universal-virtual-scroll';
export default function Home() {
const viewportRef = useRef(null);
const contentRef = useRef(null);
const [visibleItems, setVisibleItems] =
useState([]);
const [paddingTop, setPaddingTop] =
useState(0);
const [paddingBottom, setPaddingBottom] =
useState(0);
const items = Array.from(
{ length: 100000 },
(_, i) => ({
name: `Item ${i + 1}`
})
);
useEffect(() => {
const virtualScroll =
new UniversalVirtualScroll({
viewport:
viewportRef.current,
content:
contentRef.current,
items,
itemHeight: 100,
itemWidth: 200,
onUpdate: (
items,
top,
bottom
) => {
setVisibleItems(items);
setPaddingTop(top);
setPaddingBottom(bottom);
}
});
return () => {
virtualScroll.destroy();
};
}, []);
return (
<div
ref={viewportRef}
className="viewport">
<div
ref={contentRef}
style={{
paddingTop,
paddingBottom
}}>
{
visibleItems.map(item => (
<div
key={item.name}
className="card">
{item.name}
</div>
))
}
</div>
</div>
);
}app/globals.css
.viewport {
height: 100vh;
overflow-y: auto;
}
.card {
height: 100px;
}Configuration
| Option | Type | Description | |---|---|---| | viewport | HTMLElement | Scroll container | | content | HTMLElement | Content wrapper | | items | Array | Full dataset | | itemHeight | Number | Item height | | itemWidth | Number | Item width | | onUpdate | Function | Update callback |
Methods
updateItems
virtualScroll.updateItems(newItems);destroy
virtualScroll.destroy();Important
viewportmust have fixed heightviewportmust useoverflow-y: autoitemHeightmust match actual item heightitemWidthmust match actual item width
License
MIT
