npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sy17/react-masonry-component

v1.0.4

Published

A masonry component for React.js with v19 support

Readme

React Masonry Component

npm version

A React.js Masonry component with full TypeScript support. Works with React 17, 18, and 19. SSR compatible with Next.js and other server-side rendering frameworks.

Table of Contents

  1. Installation
  2. Basic Usage
  3. Server-Side Rendering (SSR)
  4. Responsive Masonry
  5. TypeScript Support
  6. Props
  7. Custom Props
  8. Accessing Masonry Instance
  9. Images Loaded Options
  10. Events

Installation

npm install --save react-masonry-component

The component is bundled with Masonry, so no additional dependencies are needed!

Basic Usage

import React from 'react';
import Masonry from 'react-masonry-component';

const masonryOptions = {
  transitionDuration: 0
};

const imagesLoadedOptions = { background: '.my-bg-image-el' };

interface Element {
  src: string;
}

interface GalleryProps {
  elements: Element[];
}

function Gallery({ elements }: GalleryProps) {
  return (
    <Masonry
      className="my-gallery-class"    // default ''
      elementType="ul"                 // default 'div'
      options={masonryOptions}         // default {}
      disableImagesLoaded={false}      // default false
      updateOnEachImageLoad={false}    // default false and works only if disableImagesLoaded is false
      imagesLoadedOptions={imagesLoadedOptions} // default {}
    >
      {elements.map((element, index) => (
        <li key={index} className="image-element-class">
          <img src={element.src} alt="" />
        </li>
      ))}
    </Masonry>
  );
}

export default Gallery;

Server-Side Rendering (SSR)

This component is fully compatible with server-side rendering frameworks like Next.js. The component safely handles the window object and browser-only dependencies, so you won't encounter "window is not defined" errors during SSR.

Next.js Usage

Simply import and use the component - no special configuration needed:

// app/page.tsx or pages/gallery.tsx
"use client"; // For Next.js 13+ App Router

import Masonry from '@sy17/react-masonry-component';

export default function Gallery() {
  return (
    <Masonry className="my-gallery">
      <div className="item">Item 1</div>
      <div className="item">Item 2</div>
      <div className="item">Item 3</div>
    </Masonry>
  );
}

Responsive Masonry

Use the ResponsiveMasonry component to automatically adjust the layout based on viewport width breakpoints:

import React from 'react';
import Masonry, { ResponsiveMasonry } from '@sy17/react-masonry-component';

function Gallery() {
  return (
    <ResponsiveMasonry
      columnsCountBreakPoints={{ 300: 2, 500: 3, 700: 5, 900: 6 }}
      className="p-5"
    >
      {(columnsCount) => (
        <Masonry options={{ columnWidth: `${100 / columnsCount}%` }}>
          <div className="item">Item 1</div>
          <div className="item">Item 2</div>
          <div className="item">Item 3</div>
        </Masonry>
      )}
    </ResponsiveMasonry>
  );
}

export default Gallery;

ResponsiveMasonry Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | columnsCountBreakPoints | { [breakpoint: number]: number } | { 350: 1, 750: 2, 900: 3 } | Breakpoint configuration for responsive columns. Keys are minimum viewport widths in pixels, values are column counts. | | children | ReactNode \| ((columnsCount: number) => ReactNode) | - | Children to render. Can be a render prop function that receives the current column count. |

How Breakpoints Work

The component uses the column count for the largest matching breakpoint. For example, with { 300: 2, 500: 3, 700: 5 }:

  • Viewport width < 300px: 1 column (default)
  • Viewport width 300-499px: 2 columns
  • Viewport width 500-699px: 3 columns
  • Viewport width >= 700px: 5 columns

TypeScript Support

This package includes built-in TypeScript definitions. You can import the types directly:

import Masonry, { 
  MasonryProps, 
  MasonryOptions, 
  ImagesLoadedOptions,
  ResponsiveMasonry,
  ResponsiveMasonryProps,
  ColumnsCountBreakPoints
} from '@sy17/react-masonry-component';

const options: MasonryOptions = {
  columnWidth: 200,
  gutter: 10,
  transitionDuration: 0
};

const imagesLoadedOptions: ImagesLoadedOptions = {
  background: '.my-bg-image-el'
};

const breakpoints: ColumnsCountBreakPoints = {
  300: 2,
  500: 3,
  700: 5
};

Available Types

  • MasonryOptions - Configuration options for Masonry layout
  • MasonryProps - Props for the Masonry component
  • ImagesLoadedOptions - Options for imagesloaded library
  • ResponsiveMasonryProps - Props for the ResponsiveMasonry component
  • ColumnsCountBreakPoints - Type for responsive breakpoint configuration

MasonryOptions

interface MasonryOptions {
  columnWidth?: number | string | HTMLElement | null;
  itemSelector?: string;
  gutter?: number | string;
  percentPosition?: boolean;
  horizontalOrder?: boolean;
  stamp?: string;
  fitWidth?: boolean;
  originLeft?: boolean;
  originTop?: boolean;
  containerStyle?: Record<string, string>;
  transitionDuration?: number | string;
  resize?: boolean;
  initLayout?: boolean;
}

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | elementType | ElementType | 'div' | The element type to render as the container | | options | MasonryOptions | {} | Masonry layout options | | disableImagesLoaded | boolean | false | Disable imagesloaded library | | updateOnEachImageLoad | boolean | false | Update layout on each image load | | imagesLoadedOptions | ImagesLoadedOptions | {} | Options for imagesloaded library | | enableResizableChildren | boolean | false | Enable resize detection on children | | onLayoutComplete | (items?: unknown[]) => void | - | Callback when layout completes | | onRemoveComplete | (items?: unknown[]) => void | - | Callback when item is removed | | onImagesLoaded | (instance: ImagesLoaded) => void | - | Callback when images are loaded |

Custom Props

You can pass any HTML attributes to the component, including inline styles and event handlers:

import React from 'react';
import Masonry from 'react-masonry-component';

const style = {
  backgroundColor: 'tomato'
};

function Gallery() {
  const handleClick = () => {
    console.log('clicked');
  };

  return (
    <Masonry
      className="my-gallery-class"
      style={style}
      onClick={handleClick}
      data-testid="masonry-gallery"
    >
      {/* children */}
    </Masonry>
  );
}

export default Gallery;

Accessing Masonry Instance

You can access the Masonry instance using refs:

import React, { useRef, useEffect } from 'react';
import Masonry from 'react-masonry-component';

function Gallery() {
  const masonryRef = useRef<Masonry>(null);

  useEffect(() => {
    if (masonryRef.current?.masonry) {
      // Access the masonry instance
      const masonry = masonryRef.current.masonry;
      
      // Example: manually trigger layout
      masonry.layout();
    }
  }, []);

  return (
    <Masonry ref={masonryRef}>
      {/* children */}
    </Masonry>
  );
}

export default Gallery;

Images Loaded Options

React Masonry Component uses Desandro's imagesloaded library to detect when images have loaded. Pass options via the imagesLoadedOptions prop.

This is commonly used for detecting when CSS background images have loaded:

import React from 'react';
import Masonry from 'react-masonry-component';

function Gallery() {
  const imagesLoadedOptions = { background: '.my-bg-image-el' };
  
  return (
    <Masonry
      className="my-gallery-class"
      elementType="ul"
      imagesLoadedOptions={imagesLoadedOptions}
    >
      <li className="my-bg-image-el" style={{ backgroundImage: 'url(image.jpg)' }}></li>
    </Masonry>
  );
}

export default Gallery;

More info available on the imagesloaded website.

Events

The component provides three event callbacks:

  • onImagesLoaded - Triggered when all images are loaded (or after each image when updateOnEachImageLoad is true)
  • onLayoutComplete - Triggered after layout and positioning transitions complete
  • onRemoveComplete - Triggered after an item element is removed
import React, { useState } from 'react';
import Masonry from 'react-masonry-component';

function Gallery() {
  const [isVisible, setIsVisible] = useState(false);

  const handleImagesLoaded = () => {
    setIsVisible(true);
  };

  const handleLayoutComplete = (laidOutItems?: unknown[]) => {
    console.log('Layout complete', laidOutItems);
  };

  const handleRemoveComplete = (removedItems?: unknown[]) => {
    console.log('Remove complete', removedItems);
  };

  return (
    <Masonry
      onImagesLoaded={handleImagesLoaded}
      onLayoutComplete={handleLayoutComplete}
      onRemoveComplete={handleRemoveComplete}
      style={{ opacity: isVisible ? 1 : 0 }}
    >
      {/* children */}
    </Masonry>
  );
}

export default Gallery;

License

MIT