masonry-grid-component
v3.0.5
Published
A Pinterest-style grid layout component built on top of @zapperwing/pinterest-view
Readme
MasonryGrid Component
Pinterest-style grid layout component that automatically arranges child elements in an optimized grid pattern. Built on top of @zapperwing/pinterest-view, this component provides virtualization support for grids with a large number of cards.
Installation
npm install masonry-grid-componentVersion Compatibility
This component is built on top of @zapperwing/pinterest-view v2.0.0+ and includes support for:
- Layout Freezing: Lock the current layout in place to prevent reflow
- Enhanced Ref API: Full ref-forwarding with both callback and object refs
- Improved Performance: Better virtualization and layout optimization
Basic Usage
import { MasonryGrid } from 'masonry-grid-component';
function Gallery() {
return (
<MasonryGrid columnWidth={300} gutter={15}>
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</MasonryGrid>
);
}With Percentage-based Columns
<MasonryGrid columnWidth="33.33%" gutter={15}>
{/* items */}
</MasonryGrid>With Image Monitoring
<MasonryGrid
columnWidth={300}
gutter={15}
monitorImagesLoaded={true}
>
<img src="image1.jpg" />
<img src="image2.jpg" />
</MasonryGrid>With Manual Layout Updates
import { MasonryGrid, MasonryGridRef } from 'masonry-grid-component';
import { useRef } from 'react';
function DynamicGallery() {
const gridRef = useRef<MasonryGridRef>(null);
const handleContentChange = () => {
gridRef.current?.updateLayout();
};
return (
<MasonryGrid ref={gridRef} columnWidth={300} gutter={15}>
{/* Dynamic content */}
</MasonryGrid>
);
}With Layout Freezing (v2.0.0+)
import { MasonryGrid, MasonryGridRef } from 'masonry-grid-component';
import { useRef } from 'react';
function GalleryWithFreeze() {
const gridRef = useRef<MasonryGridRef>(null);
const handleFreeze = () => {
gridRef.current?.freeze(); // Locks current layout
};
const handleUnfreeze = () => {
gridRef.current?.unfreeze(); // Allows normal reflow
};
return (
<div>
<button onClick={handleFreeze}>Freeze Layout</button>
<button onClick={handleUnfreeze}>Unfreeze Layout</button>
<MasonryGrid ref={gridRef} columnWidth={300} gutter={15}>
{/* Grid items */}
</MasonryGrid>
</div>
);
}With Custom Scroll Container
import { MasonryGrid } from 'masonry-grid-component';
import { useRef } from 'react';
function ScrollableGallery() {
const scrollContainerRef = useRef<HTMLDivElement>(null);
return (
<div
ref={scrollContainerRef}
style={{ height: '600px', overflow: 'auto' }}
>
<MasonryGrid
columnWidth={300}
gutter={15}
virtualized={true}
scrollContainer={scrollContainerRef.current}
>
{/* Grid items */}
</MasonryGrid>
</div>
);
}Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| columnWidth | number \| string | 150 | Width of each column. Can be pixels or percentage |
| gutter | number | 5 | Spacing between items in pixels |
| monitorImagesLoaded | boolean | false | Whether to monitor and reflow when images load |
| onLayout | (layout: { height: number }) => void | - | Callback function when layout changes |
| className | string | - | Additional CSS class for the grid container |
| style | React.CSSProperties | - | Additional inline styles |
| id | string | - | Unique identifier for the component |
| children | ReactNode | - | Grid items to be rendered |
| virtualized | boolean | false | Enable virtualization for better performance with large lists |
| virtualizationBuffer | number | 800 | Buffer size for virtualization in pixels |
| debug | boolean | false | Enable debug logging |
| rtl | boolean | false | Enable right-to-left layout |
| scrollContainer | HTMLElement | - | Custom scroll container for virtualization (defaults to window) |
Ref Methods
When using a ref with the MasonryGrid component, you can access these methods:
| Method | Description |
|--------|-------------|
| updateLayout() | Manually triggers a layout recalculation |
| clearCache() | Clears the height cache and triggers a layout update |
| freeze() | Freezes the current layout in place (locks positions) |
| unfreeze() | Clears the frozen state so new items will re-flow normally |
Component Structure
Core Components
- MasonryGrid: The main component wrapped with
forwardReffor ref forwarding - StackGrid: The underlying grid implementation from
@zapperwing/pinterest-view
Key Features Implementation
Virtualization
The component uses virtualized rendering through the StackGrid component, making it efficient even with thousands of items:
<StackGrid
virtualized={true}
columnWidth={columnWidth}
gutterWidth={gutter}
gutterHeight={gutter}
>
{children}
</StackGrid>Layout Updates
Exposes an imperative handle for manual layout updates and layout freezing:
useImperativeHandle(ref, () => ({
updateLayout: () => {
if (gridRef.current?.updateLayout) {
gridRef.current.updateLayout();
} else if (gridRef.current?.layout) {
gridRef.current.layout();
}
},
clearCache: () => {
// Trigger a layout update as a fallback
if (gridRef.current?.updateLayout) {
gridRef.current.updateLayout();
} else if (gridRef.current?.layout) {
gridRef.current.layout();
}
},
freeze: () => {
if (gridRef.current?.freeze) {
gridRef.current.freeze();
}
},
unfreeze: () => {
if (gridRef.current?.unfreeze) {
gridRef.current.unfreeze();
}
},
}));Best Practices
Performance
- Use virtualization when dealing with large numbers of items
- Enable
monitorImagesLoadedonly when necessary - Provide fixed dimensions for child items when possible
Responsive Design
- Use percentage-based column widths for fluid layouts
- Consider different column widths for different breakpoints
Image Loading
- Enable
monitorImagesLoadedwhen your grid contains images - The component will automatically reflow when images finish loading
- Enable
Examples
Check the demo in the demo/ directory for more examples, including:
- Virtualized rendering with many cards
- Variable height items
- Percentage-based layouts
- Dynamic expandable cards
Testing
Run the component's tests:
npm test