Giter Site home page Giter Site logo

paulcollett / react-masonry-css Goto Github PK

View Code? Open in Web Editor NEW
904.0 3.0 60.0 638 KB

React Masonry layout component powered by CSS, dependancy free

Home Page: https://paulcollett.github.io/react-masonry-css/demo/

License: MIT License

JavaScript 100.00%
hacktoberfest masonry masonry-component

react-masonry-css's Introduction

A Masonry component leveraging CSS and native React rendering, for fast, responsive masonry layouts

image

๐Ÿ˜Ž Why?

Existing solutions like React wrapped DeSandro Masonry, while popular, don't actually leverage React's highly optimized Virtual DOM renderer and in DeSandro Masonry's case, actually renders elements twice before showing the layout. All of this is ok but we found it to lead to a slow, "laggy" user experience that would occasionally miss-render our layout.

Our need for a simple Masonry layout that was fast, used React's Virtual DOM without needing jQuery or other dependencies led us to explore what we could do with the latest techniques using just CSS within a React Component.

Between flexbox, css columns, css grid we settled on plain ol' div's and a dab of flexbox that allows for "fluid" responsive layouts by default but most importantly is true to Reacts rendering lifecycle.

react-masonry-css Is a React Component with a simple interface to order items into the desired columns at specified breakpoints. With minimal CSS this leads to a quick, reliable solution that also has great browser support along with rendering performance.

๐Ÿ˜„ What does this do

  • Responsive! ..always
  • IE 10+
  • No Dependencies - Which means no need for jQuery!
  • Works with existing CSS animations on your elements, like fading in on first load
  • CSS powered (Faster to render)
  • Allows for Gaps (Gutters) between elements

๐Ÿณ๏ธ What doesn't this do

  • Works with elements with different widths
  • Sorting based on height - This kills performance, so if you don't need it we're here for you

๐Ÿ˜ฒ Simple Usage

Add react-masonry-css to your project:

npm install react-masonry-css

In your React Component...

import Masonry from 'react-masonry-css'

//...

<Masonry
  breakpointCols={3}
  className="my-masonry-grid"
  columnClassName="my-masonry-grid_column">
  {/* array of JSX items */}
</Masonry>

And, CSS:

.my-masonry-grid {
  display: -webkit-box; /* Not needed if autoprefixing */
  display: -ms-flexbox; /* Not needed if autoprefixing */
  display: flex;
  margin-left: -30px; /* gutter size offset */
  width: auto;
}
.my-masonry-grid_column {
  padding-left: 30px; /* gutter size */
  background-clip: padding-box;
}

/* Style your items */
.my-masonry-grid_column > div { /* change div to reference your elements you put in <Masonry> */
  background: grey;
  margin-bottom: 30px;
}

Responsive Breakpoints

Different columns can be specified by passing an object containing key's of the window widths and their value as the number of columns. To have a fallback value, use the default key.

const breakpointColumnsObj = {
  default: 4,
  1100: 3,
  700: 2,
  500: 1
};

//...

<Masonry
  breakpointCols={breakpointColumnsObj}
  className="my-masonry-grid"
  columnClassName="my-masonry-grid_column"
>
  <div>My Element</div>
  <div>My Element</div>
  <div>My Element</div>
  <div>My Element</div>
</Masonry>

Configuration Props

  • breakpointCols={{default: 4, 800: 2}} optional (defaults to 2 columns)
  • className for the container
  • columnClassName class name added to each generated column

Example Demo

https://paulcollett.github.io/react-masonry-css/demo/

Common usage

outputting an array of items:

var items = [
  {id: 1, name: 'My First Item'},
  {id: 2, name: 'Another item'},
  {id: 3, name: 'Third Item'},
  {id: 4, name: 'Here is the Fourth'},
  {id: 5, name: 'High Five'}
];

// Convert array to JSX items
items = items.map(function(item) {
  return <div key={item.id}>{item.name}</div>
});

<Masonry
  breakpointCols={myBreakpointsAndCols}
  className="my-masonry-grid"
  columnClassName="my-masonry-grid_column"
>
  {items}
</Masonry>

Optional, Responsive gutters

We can add the following to the above CSS to further adjust the layout between screen sizes.

/* Optional, different gutter size on mobile */
@media (max-width: 800px) {
  .my-masonry-grid {
    margin-left: -15px; /* gutter size offset */
  }
  .my-masonry-grid_column {
    padding-left: 15px; /* gutter size offset */
  }
  .my-masonry-grid_column > div {
    margin-bottom: 15px; /* space between items */
  }
}

Use with Preact

You can use react-masonry-css with Preact when using preact/compat

DummyJS

Improve your frontend builds with dynamic placeholder images and dummy text from DummyJs.com. https://www.npmjs.com/package/dummyjs

Suggestions & Issues

https://github.com/paulcollett/react-masonry-css/issues/

Contact me direct:

react-masonry-css's People

Contributors

andrebclark avatar asimqt avatar brxck avatar dandv avatar dependabot[bot] avatar nsdrowned avatar paulcollett avatar tdharmon avatar yantakus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

react-masonry-css's Issues

Add a css file

So since this project is in npm, and we have really good support in webpack for css files, I'd like to see a css file in the distribution that I can just import, as opposed to having it in the documentation. ;)

Centering items?

I want to be able to center the columns or at least change their justify-content value easily.
Is there a way to do this?

SSR support

Does this library provide SSR support for frameworks like Gatsby?

Reason I'm asking:
I tried it out using Gatsby. On initial load the default breakpointCols are used, independently from the current viewport width of the browser.
After a second or so the columns are jumping into place, according to the breakpointCols applicable, based on the viewport width of the browser, which looks weird.

I assume it's due to missing SSR support?

Wrong column width when items count < max columns

Hello!
First of all, thank you for the awesome library. It's really helpful.
I found a strange behaviour when items count is less than max columns.
For example, if I have 4 columns by default and only 2 items, it renders only 2 columns.
The problem is - the width of that columns sets as 25% which is 25% from grid with only two columns, not 25% from grid of 4 columns!
In a case when I know max width of grid it's ok, but when I don't know it, I get my items too tiny by their width.
Is it possible to render all 4 columns in case I have only 2 items, or set 50% column width for 2 columns in this case?
Thank you!

Add Type Definitions

I'm using Typescript and wanted to use this repo and have it typed correctly. For future typescript users who want to use this package, it would be really helpful to add a .d.ts file. I created my own declarations file that looks like this:

declare module 'react-masonry-css' {
  import * as React from 'react';

  export interface MasonryProps {
    breakpointCols?: Object;
    columnClassName?: string;
  }

  export default class Masonry extends React.Component<MasonryProps & React.HTMLProps<HTMLElement>, any> {
    render(): JSX.Element;
  }
}

This could be a start to that file (it was mostly generated for me by react-to-typescript, with some minor massaging). My understanding is that Typescript can't look at PropTypes but needs typings explicitly in a .d.ts file.

[Feature] Load on scroll

I am currently using react-masonry-css with Gatsby. I have a lot of images, they take time to load, and the problem is that images at the bottom load when they shouldn't.

I want to replicate the effect used here https://savee.it/, the images load only when in view.
How can I implement that with react-masonry-css?

Is this type of Masonry possible asking for a feature

I have a particular type of requirement where tiles are added dynamically, each tiles will be having different height and width
I wanted it to look it like this
masonry

If this is possible I wanted to try this library

css, incorrect column count with few items

due to using flex: 1 to set column width, when there are less items than specified columns, the rendered column count will be off.

eg. 3 specifed columns with only 2 items will result in only 2 columns

Uneven distribution of masonry items with conditional rendering

I have the content inside of the masonry rendered like this:

  {
    items.map((item, i) => {
      return (
        this.state.filter === 'ALL' ||
        item.filter === this.state.filter
      ) ? (
          <Item
            { ...item }
            key={ i }
          />
        ) : null
    })
  }

When a filter is applied (state change), there is no redistribution of the items between different columns... it's uneven. Would solving this problem require JS?

adding ref to wrapper element

I wanted to use react-infinite-scroll-hook with react-masonry-css, in order to do so I needed to pass the ref ( by useRef hook) to the actual list wrapper div.

because adding it to the Masonry component did not work:

const infiniteRef = useInfiniteScroll({
    loading: isLoading,
    // This value is set to "true" for this demo only. You will need to
    // get this value from the API when you request your items.
    hasNextPage,
    onLoadMore: onPaginatedSearch,
    scrollContainer: "window"
  });

<Masonry
        ref={infiniteRef}
        breakpointCols={breakpointColumnsObj}
        className="masonry"
        columnClassName="masonry-column"
      >...</Masonry>

so I have forked you repo and change the code to support this:

render() {
    const {
      breakpointCols,
      columnClassName,
      column,
      elRef,
      ...wrapperProps
    } = this.props;

    return (
      <div ref={elRef} {...wrapperProps}>
        {this.renderColumns()}
      </div>
    );
  }

so tha I could do this:

const infiniteRef = useInfiniteScroll({
    loading: isLoading,
    // This value is set to "true" for this demo only. You will need to
    // get this value from the API when you request your items.
    hasNextPage,
    onLoadMore: onPaginatedSearch,
    scrollContainer: "window"
  });

<Masonry
        elRef={infiniteRef}
        breakpointCols={breakpointColumnsObj}
        className="masonry"
        columnClassName="masonry-column"
      >...</Masonry>

I this could be potentially useful for other use cases, so it would be nice if you could include it in your code.

[Masonry] The property "columnClassName" requires a string - Error shows in Chrome console

I'm using react-masonry-css module. Recently I'm getting the below error in my Chrome Console. Any common reason for this error?

[Masonry] The property "columnClassName" requires a string myJSFile:formatted:3200

When I went to the JS file line number which shows error, I got the below code.

key: "logDeprecated", value: function(t) { console.error("[Masonry]", t) }

Please advice.

Enforcing minimum or fixed widths for children?

Hi @paulcollett! Thank you for creating this library! I was trying to use it to render post embeds all of which are a fixed width (and while can expand with margin, they can't go below a certain width).

On using this library as recommended, I notice:

screen shot 2018-10-21 at 9 40 08 am

Here is my code:

const breakpointColumnsObj = {
	"default": 2,
	1600: 4,
	1200: 3,
	800: 2,
	400: 1,
}

return (
	<Masonry
		breakpointCols = { breakpointColumnsObj }
		className = "post-preview-grid"
		columnClassName = "post-preview-column"
	>
		{ this.renderPosts() }
	</Masonry>
)

I'm not sure if this is possible and I'm misunderstanding breakpoints in this case or is there some other tweak that I need?

Thank you!

Failed to compile (You may need an appropriate loader to handle this file type.)

Hi, I wanted to give this a try, but unfortunately I get the following error:

./node_modules/react-masonry-css/src/react-masonry-css.js
Module parse failed: /home/user/github/project/node_modules/react-masonry-css/src/react-masonry-css.js Unexpected token (92:13)
You may need an appropriate loader to handle this file type.
| 
|     return childrenInColumns.map((items, i) => {
|       return <div
|         key={i}
|         className={columnClassName}

I am on React 16, using create-react-app .

my cards always rerender

After wrapping my cards with react-masonry-css the shouldComponentUpdate in my card component is ignored and my cards keeps rendering !
can someone help me how to solve this issue ?

 render() {
        // console.log("render CardsContainer")
        const {
            view,
            cells,
            memberAvatar,
            imageThumbnail,
            COLORS_CONFIG,
            zoomValue,
        } = this.props;


        return (
            <React.Fragment>
                <Masonry
                    breakpointCols={6}
                    className="my-masonry-grid"
                    columnClassName="my-masonry-grid_column">

                    {cells[0][0].map((item, itemIndex) => (
                        <CardComponent
                            zoomValue={zoomValue}
                            key={item.getEntity().getId()}
                            itemIndex={itemIndex}
                            item={item}
                            view={view}
                            imageThumbnailFilter={imageThumbnail}
                            memberAvatarFilter={memberAvatar}
                            colorConfig={
                                COLORS_CONFIG.OptionsBackgroundColorsByPallete[0]
                            }
                            colorConfigRGB={
                                COLORS_CONFIG.OptionsBackgroundColorsByPallete[1]
                            }
                        />
                    ))}

                </Masonry>

            </React.Fragment >

        );
    }

Different widths

Is there a posibility to have different widths in the same "column"?

elements with column span

Hi, I want to create a Dashboard that displays many elements with variable dimensions in a masonry grid. This Component works fine for me, even with the dynamic heights, but I need to stretch some of the elements over 2 columns. Implementing this with css leads to an overlap with the elements around it.
Is there any possibility to set some elements wider, without destructing the whole layout or, if not, is this a planned feature for the future?

Thanks in advance

IE 11 - unequal width of the columns initially

Hello - I am observing that on IE 11 when the masonry layout renders, it initially renders with unequal column widths, then if I perform any interactions in the page like clicks, the columns are I guess re-renders and they are displayed with correct width (equal width column). In Chrome, this works without any issues.
Has anyone observed this issue?
I have a release planned on Monday, hence looking for some urgent help, at least if there are any workarounds. thank you in advance.

IE 10 props/_this undefined

Great work with this component!

I am using this with Preact & Preact Compat. When running in IE 10 I get an error message saying:

Unable to get property 'breakpointCols' of undefined or null reference.

screen shot 2019-02-21 at 4 45 28 pm

It appears the props are not defined in '_this' via the _possibleConstructorReturn function. Any ideas?

See attached: The props object has a value _this does not have props.
screen shot 2019-02-21 at 4 51 54 pm

Note: This does not occur using IE Edge

cards overlap when total # of cards = # of default columns - 1

I'm running into a bug where cards overlap under a specific condition: when the total # of cards is equal to whatever I'm using as a default # of columns minus one. So, with the breakpoints set as follows, I'm getting overlapping cards (see image) when there are only 2, but as soon as I add a 3rd card, it's fine, and continues to be fine as more cards are added. Is this a Masonry issue or something else?

const breakpointColsGoals = {
default: 3,
1370: 2,
740: 1,
};

image

Row based ordered images

Images are rendered in the following order in 3 columns layout.
*** note: numbers indicate index in the array.***

img1     img4     img7
img2     img5     img8
img3     img6     img9

But I want row-based order described below.

img1     img2     img3
img4     img5     img6
img7     img8     img9

How to achieve that?

Left-to-right content flow

It would be great to have an option to set content to flow from left to right instead of top to bottom.

A possible solution would be to reorder the passed array of React elements like described here before rendering.

image

no script!

proof of concept is ready to tidied up and to be added to the repo.

If you hit here, let me know which minimum version you can work with - ES6 or ES5?

not an issue, just a tip for alternating grid shading

Hi, thanks a lot for the library!
This isn't an issue, I just wanted to throw in my example of alternating grid shading. Maybe you could add it to the readme?

.my-masonry-grid_column:nth-of-type(even) > div:nth-of-type(odd) {
  background: #e6e6e6;
  border-radius: 5px;
}

.my-masonry-grid_column:nth-of-type(odd) > div:first-of-type {
  padding-top: 5px;
}

.my-masonry-grid_column:nth-of-type(odd) > div:nth-of-type(even) {
  background: #e6e6e6;
  border-radius: 5px;
}

This will give you a pattern like this:

screen shot 2018-05-07 at 6 29 39 pm

Thanks!

first column spacing behavior different

Screen Shot 2020-10-17 at 1 38 15 PM

As seen in the picture, the first column's elements aren't aligned at the top and there is a spacing error between both elements in column 1. Wondering if this was a recurring issue with others. The current setup is the one elaborated in the documentations.

Enabling filtering

Hey Paul.

First off all great job on this component. It's allowing me to achieve a layout grid I couldn't do with masonry.

I need to be able to filter elements within the grid. Right now when I do, it removes them from the column they are in without reshuffling the whole grid (redistributing the elements accordingly). How would one achieve this? Is there a way to do a transition as well?

Thanks.

colSpan?

I would like to have a two column masonry container with some items in it spanning both columns.
Is that possible?

Any way to center childrens?

I tried using justify-content: space-around and center, doesn't work. Is there any prop that can center my divs?

Condionally rendered children cause wrong column placement

In React falsy children are not rendered so it's possible to conditionally render children using logical operators or a ternary in the JSX like so:

<MyMasonryComponent>
  <FirstChild />
  {shouldShow && <SecondChild />}
  <AnotherChild />
</MyMasonryComponent>

however when using react-masonry-css it seems that the falsy child is treated as a valid element when calculating the columns so that in such a situation the 2 truthy children are put in 1 column and another empty column is added to the DOM instead of each child being in a separate column.

I was able to stop that from happening in my case by filtering the children passing into my masonry component but something like should probably be done inside this package:

<Masonry
  breakpointCols={2}
  className="masonry-grid"
  columnClassName="masonry-grid_column"
>
  {_.filter(props.children)}
</Masonry>

Peer dependency on React 15

React 16 users will be getting this warning in the console.

[email protected]" has incorrect peer dependency "react@^15.0.0".

Is there any reason that react-masonry-css needs React 15, or could this be updated now that React is at v16.3.2?

Improve accessibility

Thanks for sharing your code. I tried it - installing was easy and it works as advertised.

I do want to mention though that the resulting HTML structure has a significant impact on accessibility. Wrapping the grid items into column <div>s means that the tab order of the page is changed. Given a 4x3 grid, people who rely on keyboard navigation now have to step through the items in a 1-5-9-2-6-10-3-7-11-4-8-12 order. This is extremely confusing, especially for blind users.

Wrapping the columns in <div>s also means that it is not possible to apply the masonry component to a HTML list (<ul> or <ol>). These tags are often used to build semantic and accessible markup.

IMHO as web developers we have an obligation to build websites for everybody. If there are ways to improve the accessibility of this component, that would be awesome. If there aren't, please mention the impact on accessibility in the readme.

updating the breakpointCols object doesn't update the app until i manually resize it

Having a sidebar in my app I would like the columns to update with the sidebar being open or not. To do this i updated the breakpointCols object with new values but it doesn't change the app until i manually change the window size. Not sure if I'm being clear or not, but hope the images bellow help.

captura de ecra 2018-08-31 as 15 43 14

As you can see here the columns are displaying correctly

captura de ecra 2018-08-31 as 15 46 39

However when I open the sidebar the breakpoint values get updated but not the app. In this case there should be only 2 columns

captura de ecra 2018-08-31 as 15 49 04

The desired behaviour only occurs when i resize the windows itself


I would really appreciate if someone could help me fix this

EDIT:

here's the code: (For whatever reason I can't format it here)
I swapped the code for an image as I could not format it right

captura de ecra 2018-08-31 as 22 10 44

feat, allow for sorting transitions

While you can currently do loading animations with CSS, sorting transitions requires a small layer of JS which can been added without effecting the rendering performance of this library.

This will be an optional feature enabled by a prop (along with duration):

<Masonry {...options} sortTransition={300}>{items}</Masonry> 

Let me know if your interested in seeing this

Add "originLeft" option

Masonry has an option for controlling the horizontal flow of the layout. By default, item elements start positioning at the left, with originLeft: true. If you want them to start positioning at the right you simply set it to false. How does one achieve the same thing with this library?

Loving this library. Thank you!

Not compatible with IE9

Hello,
Thanks for your work and your component :) it is really interesting..
But the documentation says that it is IE9+ compatible, whereas it is said to use display: flex which is not supported for IE9.
Did I misunderstand something??
Thanks a lot!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.