Virtuoso Masonry
A virtualized masonry layout component for React that arranges items in a grid with varying heights.
Features
Section titled “Features”- Virtualized rendering - only renders visible items for optimal performance with large datasets
- Variable item heights - items can have different heights, automatically measured and arranged
- Dynamic column count - change column count based on screen/container width
- Window scroll support - can use the window as the scroll container
- Just-in-time distribution - items are distributed to columns as you scroll
Installation
Section titled “Installation”bashQuick Start
Section titled “Quick Start”import { VirtuosoMasonry } from '@virtuoso.dev/masonry'
import { useMemo } from 'react'
const ItemContent: React.FC<{ data: number }> = ({ data }) => {
const height = data % 10 === 0 ? 200 : data % 5 === 0 ? 180 : data % 7 ? 150 : 120
return (
<div style={{ padding: '5px' }}>
<div style={{ height, border: '1px solid black' }}>Item {data}</div>
</div>
)
}
export default function App() {
const data = useMemo(() => {
return Array.from({ length: 1000 }, (_, index) => index)
}, [])
return (
<div>
<VirtuosoMasonry columnCount={3} data={data} style={{ height: 500 }} initialItemCount={50} ItemContent={ItemContent} />
</div>
)
}Window Scroll Example
Section titled “Window Scroll Example”import { VirtuosoMasonry } from '@virtuoso.dev/masonry'
import { useEffect, useMemo, useState } from 'react'
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth)
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth)
window.addEventListener('resize', handleResize)
return () => window.removeEventListener('resize', handleResize)
}, [])
return width
}
const ItemContent: React.FC<{ data: number }> = ({ data }) => {
const height = data % 10 === 0 ? 200 : data % 5 === 0 ? 180 : data % 7 ? 150 : 120
return (
<div style={{ padding: '5px' }}>
<div style={{ height, border: '1px solid black' }}>Item {data}</div>
</div>
)
}
export default function App() {
const data = useMemo(() => {
return Array.from({ length: 1000 }, (_, index) => index)
}, [])
const width = useWindowWidth()
const columnCount = useMemo(() => {
if (width < 500) {
return 2
}
if (width < 800) {
return 3
}
return 4
}, [width])
return (
<div>
<VirtuosoMasonry columnCount={columnCount} data={data} useWindowScroll={true} initialItemCount={50} ItemContent={ItemContent} />
</div>
)
}