paulcollett / react-masonry-css

React Masonry layout component powered by CSS, dependancy free
https://paulcollett.github.io/react-masonry-css/demo/
MIT License
953 stars 66 forks source link

Does anybody use with next/image? it doesn't work. #84

Open nwatab opened 2 years ago

nwatab commented 2 years ago

All images are shown in full screen and overlaid.

import Image from 'next/image';
import Masonry from 'react-masonry-css'

<Masonry>
{
  imgs.map(img => (
    <Image
      key={img.id}
      src={img.src}
      layout='fill'
    />
  ))
}
</Masonry>
ivenuss commented 2 years ago

Next.js fill layout requires relative position parent. But this won't kinda resolve the issue.

SanjivG10 commented 2 years ago

I don't think it works with NextJS image as NextJS Image is kind of fixed and optimized by NextJS itself. I always prefer to use plain old tag when I use react-masonry.

nwatab commented 2 years ago

Hi. This works.

index.tsx

import React from 'react'
import Masonry, { MasonryProps } from 'react-masonry-css'
import styles from "./index.module.css"

const breakpointColumnsObj = {
  default: 4,
  1024: 3,
  768: 2,
  // 640: 1
};

type MasonryGridProps = {
  breakpointCols?: MasonryProps['breakpointCols']
}

export const MasonryGrid: React.FC<MasonryGridProps> = ({children, breakpointCols=breakpointColumnsObj}) => (
  <Masonry
    breakpointCols={breakpointCols}
    className={styles.container}
    columnClassName={styles.column}
  >
    {children}
  </Masonry>
)

index.module.css

.container {
  display: -webkit-box; /* Not needed if autoprefixing */
  display: -ms-flexbox; /* Not needed if autoprefixing */
  display: flex;
  margin-left: -1px; /* gutter size offset */
  width: auto;
}
.column {
  padding-left: 1px; /* gutter size */
  background-clip: padding-box;
}

.column > span { /* change div to reference your elements you put in <Masonry> */
  background: grey;
  margin-bottom: 1px;
}

I'm using it with next/Image

import Image from 'next/image'
...
  <MasonryGrid>
    {images.map((img, index) => (
        <Image
          src={img.url}
          width={640}
          height={640 * img.height / img.width}
          loader={replaceWithYourLoader}
        />
    ))}
  </MasonryGrid>
mbritton commented 1 year ago
"use client";

import styles from "@/styles/slices/ImageGallery/ImageGallery.module.scss";
import Image from "next/image";
import Masonry from "react-masonry-css";
import ImageOverlay from "@/components/ImageOverlay";

/**
 * @typedef {import("@prismicio/client").Content.ImageGallerySlice} ImageGallerySlice
 * @typedef {import("@prismicio/react").SliceComponentProps<ImageGallerySlice>} ImageGalleryProps
 * @param {ImageGalleryProps}
 */
const ImageGallery = ({ slice }) => {
  const imageChildren = slice.items.map((item) => {
    return (
      <div
        key={`${item + item.stair_photo.url}`}
        className={styles.imageGalleryItem}
      >
        <Image fill alt={item.stair_photo.alt} src={item.stair_photo.url} />
      </div>
    );
  });

  return (
    <div>
      <ImageOverlay imageProps={slice} />
      <div className={styles.container}>
        <div className={styles.sectionTitle}>
          {slice.primary.section_title[0].text}
        </div>
        <Masonry
          breakpointCols={3}
          className={styles.myMasonryGrid}
          columnClassName={styles.myMasonryGridColumn}
        >
          {imageChildren}
        </Masonry>
      </div>
    </div>
  );
};

export default ImageGallery;