Masonry
React Bootstrap 5 Masonry component
Responsive masonry built with React Bootstrap 5. Masonry is a grid layout based on columns & it optimizes the use of space inside the web page by reducing any unnecessary gaps.
To learn more read Docs.
Basic layout
import React, { useCallback, useEffect } from 'react';
export default function App() {
const basicMasonry = useCallback(() => {
const numCols = 3;
const colHeights = Array(numCols).fill(0);
const container = document.querySelector('#masonry-with-columns') as HTMLElement;
Array.from(container.children).forEach((child, i) => {
const order = i % numCols;
(child as HTMLElement).style.order = `${order}`;
colHeights[order] += parseFloat((child as HTMLElement).clientHeight);
});
container.style.height = Math.max(...colHeights) + 'px';
}, []);
useEffect(() => {
basicMasonry();
}, [basicMasonry]);
return (
<div className='masonry-with-columns' id='masonry-with-columns'>
<div style={{ order: '0' }}>1</div>
<div style={{ order: '1' }}>2</div>
<div style={{ order: '2' }}>3</div>
<div style={{ order: '0' }}>4</div>
<div style={{ order: '1' }}>5</div>
<div style={{ order: '2' }}>6</div>
<div style={{ order: '0' }}>7</div>
<div style={{ order: '1' }}>8</div>
<div style={{ order: '2' }}>9</div>
<div style={{ order: '0' }}>10</div>
<div style={{ order: '1' }}>11</div>
<div style={{ order: '2' }}>12</div>
<div style={{ order: '0' }}>13</div>
<div style={{ order: '1' }}>14</div>
<div style={{ order: '2' }}>15</div>
</div>
);
}
body {
margin: 0;
padding: 1rem;
}
.masonry-with-columns {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
max-height: 1000px;
}
.masonry-with-columns div {
-webkit-box-flex: 1;
-webkit-flex: 1 0 auto;
-ms-flex: 1 0 auto;
flex: 1 0 auto;
background: #00997b;
color: white;
margin: 0 1rem 1rem 0;
text-align: center;
font-weight: 900;
font-size: 2rem;
}
.masonry-with-columns div:nth-child(1) {
height: 163px;
line-height: 163px;
}
.masonry-with-columns div:nth-child(2) {
height: 495px;
line-height: 495px;
}
.masonry-with-columns div:nth-child(3) {
height: 120px;
line-height: 120px;
}
.masonry-with-columns div:nth-child(4) {
height: 309px;
line-height: 309px;
}
.masonry-with-columns div:nth-child(5) {
height: 317px;
line-height: 317px;
}
.masonry-with-columns div:nth-child(6) {
height: 277px;
line-height: 277px;
}
.masonry-with-columns div:nth-child(7) {
height: 339px;
line-height: 339px;
}
.masonry-with-columns div:nth-child(8) {
height: 491px;
line-height: 491px;
}
.masonry-with-columns div:nth-child(9) {
height: 281px;
line-height: 281px;
}
.masonry-with-columns div:nth-child(10) {
height: 499px;
line-height: 499px;
}
.masonry-with-columns div:nth-child(11) {
height: 490px;
line-height: 490px;
}
.masonry-with-columns div:nth-child(12) {
height: 289px;
line-height: 289px;
}
.masonry-with-columns div:nth-child(13) {
height: 356px;
line-height: 356px;
}
.masonry-with-columns div:nth-child(14) {
height: 406px;
line-height: 406px;
}
.masonry-with-columns div:nth-child(15) {
height: 196px;
line-height: 196px;
}
.masonry-with-columns div:nth-child(16) {
height: 237px;
line-height: 237px;
}
.masonry-with-columns div:nth-child(17) {
height: 367px;
line-height: 367px;
}
.masonry-with-columns div:nth-child(18) {
height: 472px;
line-height: 472px;
}
.masonry-with-columns div:nth-child(19) {
height: 413px;
line-height: 413px;
}
.masonry-with-columns div:nth-child(20) {
height: 337px;
line-height: 337px;
}
.masonry-with-columns div:nth-child(21) {
height: 406px;
line-height: 406px;
}
.masonry-with-columns div:nth-child(22) {
height: 368px;
line-height: 368px;
}
.masonry-with-columns div:nth-child(23) {
height: 130px;
line-height: 130px;
}
.masonry-with-columns div:nth-child(24) {
height: 209px;
line-height: 209px;
}
.masonry-with-columns div:nth-child(25) {
height: 203px;
line-height: 203px;
}
.masonry-with-columns div:nth-child(26) {
height: 368px;
line-height: 368px;
}
.masonry-with-columns div:nth-child(27) {
height: 163px;
line-height: 163px;
}
.masonry-with-columns div:nth-child(28) {
height: 418px;
line-height: 418px;
}
.masonry-with-columns div:nth-child(29) {
height: 123px;
line-height: 123px;
}
.masonry-with-columns div:nth-child(30) {
height: 256px;
line-height: 256px;
}
.masonry-with-columns div:nth-child(31) {
height: 196px;
line-height: 196px;
}
.masonry-with-columns div:nth-child(32) {
height: 224px;
line-height: 224px;
}
.masonry-with-columns div:nth-child(33) {
height: 122px;
line-height: 122px;
}
.masonry-with-columns div:nth-child(34) {
height: 303px;
line-height: 303px;
}
.masonry-with-columns div:nth-child(35) {
height: 159px;
line-height: 159px;
}
.masonry-with-columns div:nth-child(36) {
height: 320px;
line-height: 320px;
}
Horizontal option
import React from 'react';
export default function App() {
return (
<div className='masonry-with-columns-2' id='masonry-with-columns-2'>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
<div>9</div>
<div>10</div>
<div>11</div>
<div>12</div>
<div>13</div>
<div>14</div>
<div>15</div>
</div>
);
}
body {
margin: 0;
padding: 1rem;
}
.masonry-with-columns-2 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
.masonry-with-columns-2 div {
height: 150px;
line-height: 150px;
background: #9b1b30;
color: white;
margin: 0 1rem 1rem 0;
text-align: center;
font-weight: 900;
font-size: 2rem;
-webkit-box-flex: 1;
-webkit-flex: 1 0 auto;
-ms-flex: 1 0 auto;
flex: 1 0 auto;
}
.masonry-with-columns-2 div:nth-child(1) {
width: 222px;
}
.masonry-with-columns-2 div:nth-child(2) {
width: 102px;
}
.masonry-with-columns-2 div:nth-child(3) {
width: 155px;
}
.masonry-with-columns-2 div:nth-child(4) {
width: 365px;
}
.masonry-with-columns-2 div:nth-child(5) {
width: 132px;
}
.masonry-with-columns-2 div:nth-child(6) {
width: 106px;
}
.masonry-with-columns-2 div:nth-child(7) {
width: 199px;
}
.masonry-with-columns-2 div:nth-child(8) {
width: 164px;
}
.masonry-with-columns-2 div:nth-child(9) {
width: 424px;
}
.masonry-with-columns-2 div:nth-child(10) {
width: 467px;
}
.masonry-with-columns-2 div:nth-child(11) {
width: 350px;
}
.masonry-with-columns-2 div:nth-child(12) {
width: 168px;
}
.masonry-with-columns-2 div:nth-child(13) {
width: 296px;
}
.masonry-with-columns-2 div:nth-child(14) {
width: 440px;
}
.masonry-with-columns-2 div:nth-child(15) {
width: 110px;
}
.masonry-with-columns-2 div:nth-child(16) {
width: 413px;
}
.masonry-with-columns-2 div:nth-child(17) {
width: 333px;
}
.masonry-with-columns-2 div:nth-child(18) {
width: 441px;
}
.masonry-with-columns-2 div:nth-child(19) {
width: 74px;
}
.masonry-with-columns-2 div:nth-child(20) {
width: 122px;
}
.masonry-with-columns-2 div:nth-child(21) {
width: 189px;
}
.masonry-with-columns-2 div:nth-child(22) {
width: 91px;
}
.masonry-with-columns-2 div:nth-child(23) {
width: 269px;
}
.masonry-with-columns-2 div:nth-child(24) {
width: 394px;
}
.masonry-with-columns-2 div:nth-child(25) {
width: 139px;
}
.masonry-with-columns-2 div:nth-child(26) {
width: 240px;
}
.masonry-with-columns-2 div:nth-child(27) {
width: 184px;
}
.masonry-with-columns-2 div:nth-child(28) {
width: 261px;
}
.masonry-with-columns-2 div:nth-child(29) {
width: 358px;
}
.masonry-with-columns-2 div:nth-child(30) {
width: 393px;
}
.masonry-with-columns-2 div:nth-child(31) {
width: 370px;
}
.masonry-with-columns-2 div:nth-child(32) {
width: 399px;
}
.masonry-with-columns-2 div:nth-child(33) {
width: 263px;
}
.masonry-with-columns-2 div:nth-child(34) {
width: 135px;
}
.masonry-with-columns-2 div:nth-child(35) {
width: 221px;
}
.masonry-with-columns-2 div:nth-child(36) {
width: 233px;
}
Flexbox option
import React from 'react';
export default function App() {
return (
<div className='masonry-with-flex'>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
<div>9</div>
<div>10</div>
<div>11</div>
<div>12</div>
<div>13</div>
<div>14</div>
<div>15</div>
</div>
);
}
body {
margin: 0;
padding: 1rem;
}
.masonry-with-flex {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
max-height: 1000px;
}
.masonry-with-flex div {
width: auto;
background: #975a58;
color: white;
margin: 0 1rem 1rem 0;
text-align: center;
font-weight: 900;
font-size: 2rem;
}
.masonry-with-flex div:nth-child(1) {
height: 334px;
line-height: 334px;
}
.masonry-with-flex div:nth-child(2) {
height: 428px;
line-height: 428px;
}
.masonry-with-flex div:nth-child(3) {
height: 432px;
line-height: 432px;
}
.masonry-with-flex div:nth-child(4) {
height: 292px;
line-height: 292px;
}
.masonry-with-flex div:nth-child(5) {
height: 312px;
line-height: 312px;
}
.masonry-with-flex div:nth-child(6) {
height: 191px;
line-height: 191px;
}
.masonry-with-flex div:nth-child(7) {
height: 302px;
line-height: 302px;
}
.masonry-with-flex div:nth-child(8) {
height: 224px;
line-height: 224px;
}
.masonry-with-flex div:nth-child(9) {
height: 475px;
line-height: 475px;
}
.masonry-with-flex div:nth-child(10) {
height: 440px;
line-height: 440px;
}
.masonry-with-flex div:nth-child(11) {
height: 426px;
line-height: 426px;
}
.masonry-with-flex div:nth-child(12) {
height: 362px;
line-height: 362px;
}
.masonry-with-flex div:nth-child(13) {
height: 129px;
line-height: 129px;
}
.masonry-with-flex div:nth-child(14) {
height: 344px;
line-height: 344px;
}
.masonry-with-flex div:nth-child(15) {
height: 236px;
line-height: 236px;
}
.masonry-with-flex div:nth-child(16) {
height: 378px;
line-height: 378px;
}
.masonry-with-flex div:nth-child(17) {
height: 312px;
line-height: 312px;
}
.masonry-with-flex div:nth-child(18) {
height: 172px;
line-height: 172px;
}
.masonry-with-flex div:nth-child(19) {
height: 474px;
line-height: 474px;
}
.masonry-with-flex div:nth-child(20) {
height: 252px;
line-height: 252px;
}
.masonry-with-flex div:nth-child(21) {
height: 355px;
line-height: 355px;
}
.masonry-with-flex div:nth-child(22) {
height: 401px;
line-height: 401px;
}
.masonry-with-flex div:nth-child(23) {
height: 369px;
line-height: 369px;
}
.masonry-with-flex div:nth-child(24) {
height: 449px;
line-height: 449px;
}
.masonry-with-flex div:nth-child(25) {
height: 411px;
line-height: 411px;
}
.masonry-with-flex div:nth-child(26) {
height: 122px;
line-height: 122px;
}
.masonry-with-flex div:nth-child(27) {
height: 262px;
line-height: 262px;
}
.masonry-with-flex div:nth-child(28) {
height: 154px;
line-height: 154px;
}
.masonry-with-flex div:nth-child(29) {
height: 308px;
line-height: 308px;
}
.masonry-with-flex div:nth-child(30) {
height: 327px;
line-height: 327px;
}
.masonry-with-flex div:nth-child(31) {
height: 374px;
line-height: 374px;
}
.masonry-with-flex div:nth-child(32) {
height: 106px;
line-height: 106px;
}
.masonry-with-flex div:nth-child(33) {
height: 340px;
line-height: 340px;
}
.masonry-with-flex div:nth-child(34) {
height: 492px;
line-height: 492px;
}
.masonry-with-flex div:nth-child(35) {
height: 475px;
line-height: 475px;
}
.masonry-with-flex div:nth-child(36) {
height: 373px;
line-height: 373px;
}
Images option
import React { useCallback, useEffect } from 'react';
export default function App() {
const imagesMasonry = useCallback(() => {
const masonryWrapper = document.querySelector('.masonry-with-flex') as HTMLElement;
Array.from(masonryWrapper.children).forEach((child, i) => {
const order = i % 3;
(child as HTMLElement).style.order = `${order}`;
});
}, []);
useEffect(() => {
basicMasonry();
}, [imagesMasonry]);
return (
<div className='masonry-with-flex masonry-with-columns' style={{ maxHeight: '1200px' }}>
<img src='https://mdbootstrap.com/img/Photos/Others/food3.webp' style={{ width: '33.3%' }} />
<img src='https://mdbootstrap.com/img/Photos/Others/image06.webp' style={{ width: '33.3%' }} />
<img src='https://mdbootstrap.com/img/Photos/Others/image17.webp' style={{ width: '33.3%' }} />
<img src='https://mdbootstrap.com/img/Photos/Others/image02.webp' style={{ width: '33.3%' }} />
<img src='https://mdbootstrap.com/img/Photos/Others/image008.webp' style={{ width: '33.3%' }} />
<img src='https://mdbootstrap.com/img/Photos/Others/image010.webp' style={{ width: '33.3%' }} />
<img src='https://mdbootstrap.com/img/Photos/Others/image002.webp' style={{ width: '33.3%' }} />
<img src='https://mdbootstrap.com/img/Photos/Others/image005.webp' style={{ width: '33.3%' }} />
<img src='https://mdbootstrap.com/img/Photos/Others/image18.webp' style={{ width: '33.3%' }} />
</div>
);
}
.masonry-with-columns,
.masonry-with-flex {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
.masonry-with-columns div {
-webkit-box-flex: 1;
-webkit-flex: 1 0 auto;
-ms-flex: 1 0 auto;
flex: 1 0 auto;
}