PageSourceSearch

https://react-photo-album.com/

html react-photo-album.com collected 2026-09-25 22:14:01 UTC 94,514 bytes, 157 lines download raw bytes

1<!DOCTYPE html><html lang="en" class="inter_709f7113-module__S4rG8G__variable fira_code_af5fb8ee-module__X-BCKq__variable"><head><meta charSet="utf-8"/><link rel="preconnect" href="https://assets.react-photo-album.com"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" href="https://assets.react-photo-album.com/_next/static/immutable/media/83afe278b6a6bb3c-s.p.45535valc9rzk.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="https://assets.react-photo-album.com/_next/static/immutable/media/b8b552e8609c5636-s.p.1mao1hin7sitq.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" as="image" imageSrcSet="https://images.react-photo-album.com/logo.a08aca3c.640x640.256w.webp 1x, https://images.react-photo-album.com/logo.a08aca3c.640x640.384w.webp 2x"/><link rel="preload" href="https://img.shields.io/npm/v/react-photo-album.svg?color=blue" as="image"/><link rel="preload" href="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fregistry.npmjs.org%2Freact-photo-album%2Flatest&amp;query=%24.bundleSize&amp;label=bundle%20size&amp;color=blue&amp;cacheSeconds=3600" as="image"/><link rel="preload" href="https://img.shields.io/npm/l/react-photo-album.svg?color=blue" as="image"/><link rel="preload" as="image" imageSrcSet="https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.32w.jpg 32w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.48w.jpg 48w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.64w.jpg 64w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.96w.jpg 96w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.128w.jpg 128w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.256w.jpg 256w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.384w.jpg 384w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.640w.jpg 640w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.750w.jpg 750w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.828w.jpg 828w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.1080w.jpg 1080w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.1200w.jpg 1200w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.1920w.jpg 1920w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.2000w.jpg 2048w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.2000w.jpg 3840w" imageSizes="(max-width: 429px) calc(100vw - 32px), (max-width: 699px) calc(100vw - 48px), (max-width: 1287px) calc(100vw - 240px - 48px), 1000px"/><link rel="preload" as="image" imageSrcSet="https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.32w.jpg 32w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.48w.jpg 48w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.64w.jpg 64w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.96w.jpg 96w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.128w.jpg 128w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.256w.jpg 256w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.384w.jpg 384w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.640w.jpg 640w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.750w.jpg 750w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.828w.jpg 828w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.1080w.jpg 1080w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.1200w.jpg 1200w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.1920w.jpg 1920w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.2000w.jpg 2048w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.2000w.jpg 3840w" imageSizes="(max-width: 429px) calc(100vw - 32px), (max-width: 699px) calc(100vw - 48px), (max-width: 1287px) calc(100vw - 240px - 48px), 1000px"/><link rel="preload" as="image" imageSrcSet="https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.32w.jpg 32w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.48w.jpg 48w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.64w.jpg 64w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.96w.jpg 96w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.128w.jpg 128w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.256w.jpg 256w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.384w.jpg 384w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.640w.jpg 640w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.750w.jpg 750w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.828w.jpg 828w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.1080w.jpg 1080w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.1200w.jpg 1200w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.1920w.jpg 1920w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.2000w.jpg 2048w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.2000w.jpg 3840w" imageSizes="(max-width: 429px) calc(100vw - 32px), (max-width: 699px) calc(100vw - 48px), (max-width: 1287px) calc(100vw - 240px - 48px), 1000px"/><link rel="preload" href="https://cdn.jsdelivr.net/gh/igordanchenko/sponsors/sponsors.svg" as="image"/><link rel="stylesheet" href="https://assets.react-photo-album.com/_next/static/immutable/chunks/2h86bkwzmn_lt.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="https://assets.react-photo-album.com/_next/static/immutable/chunks/36k8in9a291ok.js"/>
1<script src="https://assets.react-photo-album.com/_next/static/immutable/chunks/0hw-nq04guk_f.js" async=""></script>
1<script src="https://assets.react-photo-album.com/_next/static/immutable/chunks/0lyzihd-7_-q7.js" async=""></script>
1<script src="https://assets.react-photo-album.com/_next/static/immutable/chunks/3wc_kxht-4htf.js" async=""></script>
1<script src="https://assets.react-photo-album.com/_next/static/immutable/chunks/turbopack-2_pg2nb8oj9yr.js" async=""></script>
1<script src="https://assets.react-photo-album.com/_next/static/immutable/chunks/1ty7z5-qzonhg.js" async=""></script>
1<script src="https://assets.react-photo-album.com/_next/static/immutable/chunks/3-sc2wqugqoo_.js" async=""></script>
1<script src="https://assets.react-photo-album.com/_next/static/immutable/chunks/1xdqp_r9jcv98.js" async=""></script>
1<meta name="theme-color" content="#1a237e"/><title>React Photo Album - Responsive photo gallery component for React</title><meta name="description" content="React Photo Album is a responsive photo gallery component for React. React Photo Album supports rows, columns, and masonry layouts."/><link rel="manifest" href="/site.webmanifest"/><meta name="msapplication-TileColor" content="#1a237e"/><meta name="thumbnail" content="https://images.react-photo-album.com/thumbnails/playground.cd1bf9f5.1600x1600.1600w.jpg"/><link rel="canonical" href="https://react-photo-album.com"/><meta property="og:title" content="React Photo Album"/><meta property="og:description" content="React Photo Album is a responsive photo gallery component for React. React Photo Album supports rows, columns, and masonry layouts."/><meta property="og:url" content="https://react-photo-album.com"/><meta property="og:site_name" content="React Photo Album"/><meta property="og:locale" content="en_US"/><meta property="og:type" content="website"/><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="React Photo Album"/><meta name="twitter:description" content="React Photo Album is a responsive photo gallery component for React. React Photo Album supports rows, columns, and masonry layouts."/><link rel="icon" href="/favicon-16x16.png" sizes="16x16" type="image/png"/><link rel="icon" href="/favicon-32x32.png" sizes="32x32" type="image/png"/><link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180"/><link rel="mask-icon" href="/safari-pinned-tab.svg" color="#1a237e"/><meta name="next-size-adjust" content=""/>
1<script id="select-theme">!function(){var e,l,a,n=null===(e=(l=window).matchMedia)||void 0===e?void 0:e.call(l,"(prefers-color-scheme: dark)");function t(){"dark"===localStorage.theme||!("theme"in localStorage)&&null!=n&&n.matches?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark")}t(),null==n||null===(a=n.addEventListener)||void 0===a||a.call(n,"change",t)}();</script>
1<script src="https://assets.react-photo-album.com/_next/static/immutable/chunks/0c0hxoamwjsbw.js" noModule=""></script>
1</head><body><div hidden=""><!--$--><!--/$--></div><div class="mx-auto max-w-screen-xl"><header class="fixed inset-x-0 top-0 w-full z-50 bg-primary text-secondary shadow-toolbar print:text-primary"><nav class="flex items-center w-full h-16 mx-auto px-4 md:px-6 text-xl xs:text-[1.375rem] sm:text-2xl max-w-screen-xl"><button type="button" class="not-prose relative box-border outline-0 outline-none m-0 border-0 cursor-pointer select-none align-middle no-underline hover:no-underline overflow-hidden transition duration-300 [-webkit-tap-highlight-color:transparent] p-2 shrink-0 rounded-full hover:bg-secondary/5 block md:hidden mr-2 -ml-2.5 text-2xl xs:text-3xl print:!hidden" title="Navigation Menu"><svg aria-hidden="true" focusable="false" viewBox="0 0 24 24" class="select-none fill-current w-[1em] h-[1em]"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"></path></svg></button><a class="p-2 -ml-2 mr-auto font-bold rounded-lg focus:outline-none focus-visible:ring focus-visible:no-underline" href="/">React Photo Album</a><button type="button" class="not-prose relative box-border outline-0 outline-none m-0 border-0 cursor-pointer select-none align-middle no-underline hover:no-underline overflow-hidden transition duration-300 [-webkit-tap-highlight-color:transparent] p-2 shrink-0 rounded-full hover:bg-secondary/5 text-2xl xs:text-3xl print:!hidden hidden [@media(min-width:23.125rem)]:block [:is(html.dark)_&amp;]:hidden" title="Switch to Dark Mode"><svg aria-hidden="true" focusable="false" viewBox="0 0 24 24" class="select-none fill-current w-[1em] h-[1em]"><path d="M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9 9-4.03 9-9c0-.46-.04-.92-.1-1.36-.98 1.37-2.58 2.26-4.4 2.26-2.98 0-5.4-2.42-5.4-5.4 0-1.81.89-3.42 2.26-4.4-.44-.06-.9-.1-1.36-.1z"></path></svg></button><button type="button" class="not-prose relative box-border outline-0 outline-none m-0 border-0 cursor-pointer select-none align-middle no-underline hover:no-underline overflow-hidden transition duration-300 [-webkit-tap-highlight-color:transparent] p-2 shrink-0 rounded-full hover:bg-secondary/5 text-2xl xs:text-3xl print:!hidden hidden [@media(min-width:23.125rem)]:block [:is(html:not(.dark))_&amp;]:hidden" title="Switch to Light Mode"><svg aria-hidden="true" focusable="false" viewBox="0 0 24 24" class="select-none fill-current w-[1em] h-[1em]"><path d="M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zM2 13h2c.55 0 1-.45 1-1s-.45-1-1-1H2c-.55 0-1 .45-1 1s.45 1 1 1zm18 0h2c.55 0 1-.45 1-1s-.45-1-1-1h-2c-.55 0-1 .45-1 1s.45 1 1 1zM11 2v2c0 .55.45 1 1 1s1-.45 1-1V2c0-.55-.45-1-1-1s-1 .45-1 1zm0 18v2c0 .55.45 1 1 1s1-.45 1-1v-2c0-.55-.45-1-1-1s-1 .45-1 1zM5.99 4.58c-.39-.39-1.03-.39-1.41 0-.39.39-.39 1.03 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0s.39-1.03 0-1.41L5.99 4.58zm12.37 12.37c-.39-.39-1.03-.39-1.41 0-.39.39-.39 1.03 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0 .39-.39.39-1.03 0-1.41l-1.06-1.06zm1.06-10.96c.39-.39.39-1.03 0-1.41-.39-.39-1.03-.39-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0l1.06-1.06zM7.05 18.36c.39-.39.39-1.03 0-1.41-.39-.39-1.03-.39-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0l1.06-1.06z"></path></svg></button><a href="https://www.npmjs.com/package/react-photo-album" target="_blank" rel="noreferrer noopener" class="not-prose relative box-border outline-0 outline-none m-0 border-0 cursor-pointer select-none align-middle no-underline hover:no-underline overflow-hidden transition duration-300 [-webkit-tap-highlight-color:transparent] p-2 shrink-0 rounded-full hover:bg-secondary/5 text-2xl xs:text-3xl print:!hidden hidden [@media(min-width:20.625rem)]:block" title="NPM Package"><svg aria-hidden="true" focusable="false" viewBox="0 0 24 24" class="select-none fill-current w-[1em] h-[1em]"><path fill-rule="evenodd" clip-rule="evenodd" d="M2 2h20v20h-20v-20M5.421 5.421h13.158v13.158h-3.333v-9.825h-3.246v9.825h-6.579v-13.158Z"></path></svg></a><a href="https://github.com/igordanchenko/react-photo-album" target="_blank" rel="noreferrer noopener" class="not-prose relative box-border outline-0 outline-none m-0 border-0 cursor-pointer select-none align-middle no-underline hover:no-underline overflow-hidden transition duration-300 [-webkit-tap-highlight-color:transparent] p-2 shrink-0 rounded-full hover:bg-secondary/5 -mr-2 text-2xl xs:text-3xl print:!hidden hidden [@media(min-width:18.7
15rem)]:block" title="GitHub Repository"><svg aria-hidden="true" focusable="false" viewBox="0 0 24 24" class="select-none fill-current w-[1em] h-[1em]"><path d="M12 1.27a11 11 0 00-3.48 21.46c.55.09.73-.28.73-.55v-1.84c-3.03.64-3.67-1.46-3.67-1.46-.55-1.29-1.28-1.65-1.28-1.65-.92-.65.1-.65.1-.65 1.1 0 1.73 1.1 1.73 1.1.92 1.65 2.57 1.2 3.21.92a2 2 0 01.64-1.47c-2.47-.27-5.04-1.19-5.04-5.5 0-1.1.46-2.1 1.2-2.84a3.76 3.76 0 010-2.93s.91-.28 3.11 1.1c1.8-.49 3.7-.49 5.5 0 2.1-1.38 3.02-1.1 3.02-1.1a3.76 3.76 0 010 2.93c.83.74 1.2 1.74 1.2 2.94 0 4.21-2.57 5.13-5.04 5.4.45.37.82.92.82 2.02v3.03c0 .27.1.64.73.55A11 11 0 0012 1.27"></path></svg></a></nav></header><div class="hidden md:block w-[15rem] print:hidden"><div class="fixed mt-16 inset-y-0 w-[15rem] bg-background dark:bg-background-invert overflow-auto border-solid border-r border-r-paper-border dark:border-r-paper-border-invert"><nav class="flex flex-col py-3 bg-background dark:bg-background-invert z-20"><a class="pr-4 py-[0.625rem] outline-0 hover:bg-menu-hover dark:hover:bg-menu-hover-invert focus-visible:bg-menu-focus dark:focus-visible:bg-menu-focus-invert pl-6 font-bold dark:text-link-underline-invert" href="/">Introduction</a><a class="pr-4 py-[0.625rem] outline-0 hover:bg-menu-hover dark:hover:bg-menu-hover-invert focus-visible:bg-menu-focus dark:focus-visible:bg-menu-focus-invert pl-6" href="/documentation">Documentation</a><a class="pr-4 py-[0.625rem] outline-0 hover:bg-menu-hover dark:hover:bg-menu-hover-invert focus-visible:bg-menu-focus dark:focus-visible:bg-menu-focus-invert pl-6" href="/examples">Examples</a><a class="pr-4 py-[0.625rem] outline-0 hover:bg-menu-hover dark:hover:bg-menu-hover-invert focus-visible:bg-menu-focus dark:focus-visible:bg-menu-focus-invert pl-10" href="/examples/rows">Rows Layout</a><a class="pr-4 py-[0.625rem] outline-0 hover:bg-menu-hover dark:hover:bg-menu-hover-invert focus-visible:bg-menu-focus dark:focus-visible:bg-menu-focus-invert pl-10" href="/examples/columns">Columns Layout</a><a class="pr-4 py-[0.625rem] outline-0 hover:bg-menu-hover dark:hover:bg-menu-hover-invert focus-visible:bg-menu-focus dark:focus-visible:bg-menu-focus-invert pl-10" href="/examples/masonry">Masonry Layout</a><a class="pr-4 py-[0.625rem] outline-0 hover:bg-menu-hover dark:hover:bg-menu-hover-invert focus-visible:bg-menu-focus dark:focus-visible:bg-menu-focus-invert pl-10" href="/examples/playground">Playground</a><a class="pr-4 py-[0.625rem] outline-0 hover:bg-menu-hover dark:hover:bg-menu-hover-invert focus-visible:bg-menu-focus dark:focus-visible:bg-menu-focus-invert pl-10" href="/examples/customization">Customization</a><a class="pr-4 py-[0.625rem] outline-0 hover:bg-menu-hover dark:hover:bg-menu-hover-invert focus-visible:bg-menu-focus dark:focus-visible:bg-menu-focus-invert pl-10" href="/examples/sortable-gallery">Sortable Gallery</a><a class="pr-4 py-[0.625rem] outline-0 hover:bg-menu-hover dark:hover:bg-menu-hover-invert focus-visible:bg-menu-focus dark:focus-visible:bg-menu-focus-invert pl-10" href="/examples/nextjs">Next.js Image</a><a class="pr-4 py-[0.625rem] outline-0 hover:bg-menu-hover dark:hover:bg-menu-hover-invert focus-visible:bg-menu-focus dark:focus-visible:bg-menu-focus-invert pl-10" href="/examples/lightbox">Lightbox</a><a class="pr-4 py-[0.625rem] outline-0 hover:bg-menu-hover dark:hover:bg-menu-hover-invert focus-visible:bg-menu-focus dark:focus-visible:bg-menu-focus-invert pl-10" href="/examples/infinite-scroll">Infinite Scroll</a><a class="pr-4 py-[0.625rem] outline-0 hover:bg-menu-hover dark:hover:bg-menu-hover-invert focus-visible:bg-menu-focus dark:focus-visible:bg-menu-focus-invert pl-10" href="/examples/zero-cls-ssr">Zero CLS SSR</a><a class="pr-4 py-[0.625rem] outline-0 hover:bg-menu-hover dark:hover:bg-menu-hover-invert focus-visible:bg-menu-focus dark:focus-visible:bg-menu-focus-invert pl-10" href="/examples/server">Server Component</a><div class="flex sm:hidden text-2xl p-4 justify-around"><a href="https://github.com/igordanchenko/react-photo-album" target="_blank" rel="noreferrer noopener" class="not-prose relative box-border outline-0 outline-none m-0 border-0 cursor-pointer select-none align-middle no-underline hover:no-underline overflow-hidden transition duration-300 [-webkit-tap-highlight-color:transparent] p-2 shrink-0 rounded-full hover:bg-secondary/5" title="GitHub Repository"><svg aria-hidden="true" focusable="false" viewBox="0 0 24 24" class="select-none fill-current w-[1em] h-[1em]"><path d="M12 1.27a11 11 0 00-3.48 21.46c.55.09.73-.28.73-.55v-1.84c-3.03.64-3.67-1.46-3.67-1.46-.55-1.29-1.28-1.65-1.28-1.65-.92-.65.1-.65.1-.65 1.1 0 1.73 1.1 1.73 1.1.92 1.65 2.57 1.2 3.21.92a2 2 0 01.64-1.47c-2.47-.27-5.04-1.19-5.04-5.5 0-1.1.46-2.1 1.2-2.84a3.76 3.76 0 010-2.93s.91-.28 3.11 1.1c1.8-.49 3.7-.49 5.5 0 2.1-1.38 3.02-1.1 3.02-1.1a3.76 3.76 0 010 2.93c.83.74 1.2 1.74 1.2 2.94 0 4.21-2.57 5.13-5.04 5.4.45.37.82.92.82 2.02v3.03c0 .27.1.64.73.55A11 11 0 0012 1.27"></path></svg></a><a href="https://www.npmjs.com/package/react-photo-album" target="_blank" rel="noreferrer noopener" class="not-prose relative box-border outline-0 outline-none m-0 border-0 cursor-pointer select-none align-middle no-underline hover:no-underline overflow-hidden transition duration-300 [-webkit-tap-highlight-color:transparent] p-2 shrink-0 rounded-full hover:bg-secondary/5" title="NPM Package"><svg aria-hidden="true" focusable="false" viewBox="0 0 24 24" class="select-none fill-current w-[1em] h-[1em]"><path fill-rule="evenodd" clip-rule="evenodd" d="M2 2h20v20h-20v-20M5.421 5.421h13.158v13.158h-3.333v-9.825h-3.246v9.825h-6.579v-13.158Z"></path></svg></a><button type="button" class="not-prose relative box-border outline-0 outline-none m-0 border-0 cursor-pointer select-none align-middle no-underline hover:no-underline overflow-hidden transition duration-300 [-webkit-tap-highlight-color:transparent] p-2 shrink-0 rounded-full hover:bg-secondary/5 [:is(html.dark)_&amp;]:hidden" title="Switch to Dark Mode"><svg aria-hidden="true" focusable="false" viewBox="0 0 24 24" class="select-none fill-current w-[1em] h-[1em]"><path d="M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9 9-4.03 9-9c0-.46-.04-.92-.1-1.36-.98 1.37-2.58 2.26-4.4 2.26-2.98 0-5.4-2.42-5.4-5.4 0-1.81.89-3.42 2.26-4.4-.44-.06-.9-.1-1.36-.1z"></path></svg></button><button type="button" class="not-prose relative box-border outline-0 outline-none m-0 border-0 cursor-pointer select-none align-middle no-underline hover:no-underline overflow-hidden transition duration-300 [-webkit-tap-highlight-color:transparent] p-2 shrink-0 rounded-full hover:bg-secondary/5 [:is(html:not(.dark))_&amp;]:hidden" title="Switch to Light Mode"><svg aria-hidden="true" focusable="false" viewBox="0 0 24 24" class="select-none fill-current w-[1em] h-[1em]"><path d="M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zM2 13h2c.55 0 1-.45 1-1s-.45-1-1-1H2c-.55 0-1 .45-1 1s.45 1 1 1zm18 0h2c.55 0 1-.45 1-1s-.45-1-1-1h-2c-.55 0-1 .45-1 1s.45 1 1 1zM11 2v2c0 .55.45 1 1 1s1-.45 1-1V2c0-.55-.45-1-1-1s-1 .45-1 1zm0 18v2c0 .55.45 1 1 1s1-.45 1-1v-2c0-.55-.45-1-1-1s-1 .45-1 1zM5.99 4.58c-.39-.39-1.03-.39-1.41 0-.39.39-.39 1.03 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0s.39-1.03 0-1.41L5.99 4.58zm12.37 12.37c-.39-.39-1.03-.39-1.41 0-.39.39-.39 1.03 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0 .39-.39.39-1.03 0-1.41l-1.06-1.06zm1.06-10.96c.39-.39.39-1.03 0-1.41-.39-.39-1.03-.39-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0l1.06-1.06zM7.05 18.36c.39-.39.39-1.03 0-1.41-.39-.39-1.03-.39-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0l1.06-1.06z"></path></svg></button></div></nav></div></div><main class="max-w-none md:ml-[15rem] print:md:ml-0 mt-16 py-8 px-4 md:px-6 scroll-mt-20 prose prose-slate dark:prose-invert"><div align="center"><img alt="" width="180" height="180" decoding="async" data-nimg="1" class="my-0" style="color:transparent" srcSet="https://images.react-photo-album.com/logo.a08aca3c.640x640.256w.webp 1x, https://images.react-photo-album.com/logo.a08aca3c.640x640.384w.webp 2x" src="https://images.react-photo-album.com/logo.a08aca3c.640x640.384w.webp"/>
1<h1 id="ReactPhotoAlbum">React Photo Album<a href="#ReactPhotoAlbum" title="Direct link to React Photo Album" aria-label="Direct link to React Photo Album"></a></h1><p class="badges not-prose"><a href="https://www.npmjs.com/package/react-photo-album" target="_blank" rel="noreferrer noopener"><img src="https://img.shields.io/npm/v/react-photo-album.svg?color=blue" alt="NPM Version" style="width:calc(1rem / 16 * 80);height:calc(1rem / 16 * 20)"/></a>
2<a href="https://github.com/igordanchenko/react-photo-album/blob/main/.size-limit.json" target="_blank" rel="noreferrer noopener"><img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fregistry.npmjs.org%2Freact-photo-album%2Flatest&amp;query=%24.bundleSize&amp;label=bundle%20size&amp;color=blue&amp;cacheSeconds=3600" alt="Bundle Size" style="width:calc(1rem / 16 * 126);height:calc(1rem / 16 * 20)"/></a>
3<a href="https://github.com/igordanchenko/react-photo-album/blob/main/LICENSE" target="_blank" rel="noreferrer noopener"><img src="https://img.shields.io/npm/l/react-photo-album.svg?color=blue" alt="License MIT" style="width:calc(1rem / 16 * 78);height:calc(1rem / 16 * 20)"/></a></p><p>React Photo Album is a responsive photo gallery component with rows, columns,
4and masonry layouts. <br/> Inspired by
5<a href="https://github.com/neptunian/react-photo-gallery" target="_blank" rel="noreferrer noopener">react-photo-gallery</a>,
6re-engineered from the ground up.</p></div>
7<h2 id="Overview">Overview<a href="#Overview" title="Direct link to Overview" aria-label="Direct link to Overview"></a></h2>
8<ul>
9<li><strong>Built for React:</strong> works with React 18+</li>
10<li><strong>SSR friendly:</strong> produces server-side rendered markup that looks
11pixel-perfect on the client even before hydration</li>
12<li><strong>Responsive images:</strong> responsive images with automatic resolution switching
13are supported out of the box</li>
14<li><strong>Feature-packed:</strong> supports 3 layout options (rows, columns, and masonry),
15responsive images, custom data attributes, and is fully configurable and
16customizable</li>
17<li><strong>TypeScript:</strong> type definitions come built-in with the package</li>
18<li><strong>Performance:</strong> built with performance in mind to support large photo albums</li>
19</ul>
20<h2 id="Layouts">Layouts<a href="#Layouts" title="Direct link to Layouts" aria-label="Direct link to Layouts"></a></h2>
21<h3 id="Layouts_Rows">Rows<a href="#Layouts_Rows" title="Direct link to Rows" aria-label="Direct link to Rows"></a></h3>
22<p><img alt="React Photo Album | Rows Layout" width="2000" height="1906" decoding="async" data-nimg="1" class="my-0" style="color:transparent" sizes="(max-width: 429px) calc(100vw - 32px), (max-width: 699px) calc(100vw - 48px), (max-width: 1287px) calc(100vw - 240px - 48px), 1000px" srcSet="https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.32w.jpg 32w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.48w.jpg 48w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.64w.jpg 64w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.96w.jpg 96w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.128w.jpg 128w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.256w.jpg 256w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.384w.jpg 384w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.640w.jpg 640w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.750w.jpg 750w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.828w.jpg 828w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.1080w.jpg 1080w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.1200w.jpg 1200w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.1920w.jpg 1920w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.2000w.jpg 2048w, https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.2000w.jpg 3840w" src="https://images.react-photo-album.com/layouts/rows.0a16b150.2000x1906.2000w.jpg"/></p>
23<h3 id="Layouts_Columns">Columns<a href="#Layouts_Columns" title="Direct link to Columns" aria-label="Direct link to Columns"></a></h3>
24<p><img alt="React Photo Album | Columns Layout" width="2000" height="1586" decoding="async" data-nimg="1" class="my-0" style="color:transparent" sizes="(max-width: 429px) calc(100vw - 32px), (max-width: 699px) calc(100vw - 48px), (max-width: 1287px) calc(100vw - 240px - 48px), 1000px" srcSet="https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.32w.jpg 32w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.48w.jpg 48w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.64w.jpg 64w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.96w.jpg 96w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.128w.jpg 128w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.256w.jpg 256w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.384w.jpg 384w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.640w.jpg 640w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.750w.jpg 750w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.828w.jpg 828w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.1080w.jpg 1080w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.1200w.jpg 1200w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.1920w.jpg 1920w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.2000w.jpg 2048w, https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.2000w.jpg 3840w" src="https://images.react-photo-album.com/layouts/columns.2aa2453c.2000x1586.2000w.jpg"/></p>
25<h3 id="Layouts_Masonry">Masonry<a href="#Layouts_Masonry" title="Direct link to Masonry" aria-label="Direct link to Masonry"></a></h3>
26<p><img alt="React Photo Album | Masonry Layout" width="2000" height="1856" decoding="async" data-nimg="1" class="my-0" style="color:transparent" sizes="(max-width: 429px) calc(100vw - 32px), (max-width: 699px) calc(100vw - 48px), (max-width: 1287px) calc(100vw - 240px - 48px), 1000px" srcSet="https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.32w.jpg 32w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.48w.jpg 48w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.64w.jpg 64w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.96w.jpg 96w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.128w.jpg 128w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.256w.jpg 256w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.384w.jpg 384w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.640w.jpg 640w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.750w.jpg 750w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.828w.jpg 828w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.1080w.jpg 1080w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.1200w.jpg 1200w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.1920w.jpg 1920w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.2000w.jpg 2048w, https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.2000w.jpg 3840w" src="https://images.react-photo-album.com/layouts/masonry.e4db4daa.2000x1856.2000w.jpg"/></p>
27<h2 id="Documentation">Documentation<a href="#Documentation" title="Direct link to Documentation" aria-label="Direct link to Documentation"></a></h2>
28<p><a href="/documentation">https://react-photo-album.com/documentation</a></p>
29<h2 id="Examples">Examples<a href="#Examples" title="Direct link to Examples" aria-label="Direct link to Examples"></a></h2>
30<p><a href="/examples">https://react-photo-album.com/examples</a></p>
31<h2 id="Changelog">Changelog<a href="#Changelog" title="Direct link to Changelog" aria-label="Direct link to Changelog"></a></h2>
32<p><a href="https://github.com/igordanchenko/react-photo-album/releases" target="_blank" rel="noreferrer noopener">https://github.com/igordanchenko/react-photo-album/releases</a></p>
33<h2 id="Installation">Installation<a href="#Installation" title="Direct link to Installation" aria-label="Direct link to Installation"></a></h2>
34<pre><code class="language-shell"><span class="token function">npm</span> <span class="token function">install</span> react-photo-album
35</code></pre>
36<h2 id="Requirements">Requirements<a href="#Requirements" title="Direct link to Requirements" aria-label="Direct link to Requirements"></a></h2>
37<ul>
38<li>React 18+</li>
39<li>Node 18+</li>
40<li>modern ESM-compatible bundler</li>
41</ul>
42<h2 id="MinimalSetupExample">
42Minimal Setup Example<a href="#MinimalSetupExample" title="Direct link to Minimal Setup Example" aria-label="Direct link to Minimal Setup Example"></a></h2>
43<pre><code class="language-tsx"><span class="token keyword">import</span> <span class="token punctuation">{</span> RowsPhotoAlbum <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&quot;react-photo-album&quot;</span><span class="token punctuation">;</span>
44<span class="token keyword">import</span> <span class="token string">&quot;react-photo-album/rows.css&quot;</span><span class="token punctuation">;</span>
45
46<span class="token keyword">const</span> photos <span class="token operator">=</span> <span class="token punctuation">[</span>
47  <span class="token punctuation">{</span> src<span class="token operator">:</span> <span class="token string">&quot;/image1.jpg&quot;</span><span class="token punctuation">,</span> width<span class="token operator">:</span> <span class="token number">800</span><span class="token punctuation">,</span> height<span class="token operator">:</span> <span class="token number">600</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
48  <span class="token punctuation">{</span> src<span class="token operator">:</span> <span class="token string">&quot;/image2.jpg&quot;</span><span class="token punctuation">,</span> width<span class="token operator">:</span> <span class="token number">1600</span><span class="token punctuation">,</span> height<span class="token operator">:</span> <span class="token number">900</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
49<span class="token punctuation">]</span><span class="token punctuation">;</span>
50
51<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">Gallery</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
52  <span class="token keyword">return</span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">RowsPhotoAlbum</span></span> <span class="token attr-name">photos</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>photos<span class="token punctuation">}</span></span> <span class="token punctuation">/&gt;</span></span><span class="token punctuation">;</span>
53<span class="token punctuation">}</span>
54</code></pre>
55<h2 id="HowItWorks">How It Works<a href="#HowItWorks" title="Direct link to How It Works" aria-label="Direct link to How It Works"></a></h2>
56<h3 id="HowItWorks_RowsLayout">Rows Layout<a href="#HowItWorks_RowsLayout" title="Direct link to Rows Layout" aria-label="Direct link to Rows Layout"></a></h3>
57<p>Rows layout fills the container space by arranging photos into rows that are
58similar in height, with the height of each row being as close to the
59<code>targetRowHeight</code> as possible. This layout is inspired by the Knuth and Plass
60line-breaking algorithm and uses dynamic programming to find optimal row breaks
61in a DAG (directed acyclic graph) where photo indices are nodes and each
62possible row is an edge connecting its first and last photo. The cost of each
63edge is a weighted squared deviation from the <code>targetRowHeight</code>. This algorithm
64produces rows that are similar in height and photos that are not stretched or
65abnormally shrunk (as happens in a naive implementation). It solves the issue of
66panoramas shrinking rows, stragglers, or stretched images in the last row.</p>
67<h3 id="HowItWorks_ColumnsLayout">Columns Layout<a href="#HowItWorks_ColumnsLayout" title="Direct link to Columns Layout" aria-label="Direct link to Columns Layout"></a></h3>
68<p>Columns layout fills the container space by arranging photos into a predefined
69number of columns, determined by the <code>columns</code> parameter. This layout uses a
70dynamic programming algorithm to find the optimal partition of photos into the
71specified number of groups (columns) that produces the most balanced layout.
72Column widths are then adjusted proportionally based on their content&#x27;s aspect
73ratios so that all columns render at equal height.</p>
74<h3 id="HowItWorks_MasonryLayout">Masonry Layout<a href="#HowItWorks_MasonryLayout" title="Direct link to Masonry Layout" aria-label="Direct link to Masonry Layout"></a></h3>
75<p>Masonry layout arranges photos into columns of equal width by placing each photo
76into the shortest column. This layout does not fill the container space flush to
77its bottom edge, but the columns end up being as close in height to each other
78as possible.</p>
79<h3 id="HowItWorks_ResponsiveImages">Responsive Images<a href="#HowItWorks_ResponsiveImages" title="Direct link to Responsive Images" aria-label="Direct link to Responsive Images"></a></h3>
80<p>React Photo Album can automatically produce <code>sizes</code> and <code>srcset</code> image
81attributes. In the case of SSR, React Photo Album includes <code>sizes</code> and <code>srcset</code>
82image attributes in the server-rendered markup, allowing browsers to pick images
83of the most appropriate resolution depending on the end-user viewport size. To
84utilize images with automatic resolution switching, provide images of different
85resolutions in the photo <code>srcSet</code> attribute. To further improve app
86responsiveness and bandwidth utilization, you can specify the <code>sizes</code> prop that
87describes the width of the photo album in various viewports.</p>
88<pre><code class="language-tsx"><span class="token keyword">import</span> <span class="token punctuation">{</span> RowsPhotoAlbum <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&quot;react-photo-album&quot;</span><span class="token punctuation">;</span>
89<span class="token keyword">import</span> <span class="token string">&quot;react-photo-album/rows.css&quot;</span><span class="token punctuation">;</span>
90
91<span class="token keyword">const</span> photos <span class="token operator">=</span> <span class="token punctuation">[</span>
92  <span class="token punctuation">{</span>
93    src<span class="token operator">:</span> <span class="token string">&quot;/image1_800x600.jpg&quot;</span><span class="token punctuation">,</span>
94    width<span class="token operator">:</span> <span class="token number">800</span><span class="token punctuation">,</span>
95    height<span class="token operator">:</span> <span class="token number">600</span><span class="token punctuation">,</span>
96    srcSet<span class="token operator">:</span> <span class="token punctuation">[</span>
97      <span class="token punctuation">{</span> src<span class="token operator">:</span> <span class="token string">&quot;/image1_400x300.jpg&quot;</span><span class="token punctuation">,</span> width<span class="token operator">:</span> <span class="token number">400</span><span class="token punctuation">,</span> height<span class="token operator">:</span> <span class="token number">300</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
98      <span class="token punctuation">{</span> src<span class="token operator">:</span> <span class="token string">&quot;/image1_200x150.jpg&quot;</span><span class="token punctuation">,</span> width<span class="token operator">:</span> <span class="token number">200</span><span class="token punctuation">,</span> height<span class="token operator">:</span> <span class="token number">150</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
99    <span class="token punctuation">]</span><span class="token punctuation">,</span>
100  <span class="token punctuation">}</span><span class="token punctuation">,</span>
101  <span class="token punctuation">{</span>
102    src<span class="token operator">:</span> <span class="token string">&quot;/image2_1600x900.jpg&quot;</span><span class="token punctuation">,</span>
103    width<span class="token operator">:</span> <span class="token number">1600</span><span class="token punctuation">,</span>
104    height<span class="token operator">:</span> <span class="token number">900</span><span class="token punctuation">,</span>
105    srcSet<span class="token operator">:</span> <span class="token punctuation">[</span>
106      <span class="token punctuation">{</span> src<span class="token operator">:</span> <span class="token string">&quot;/image2_800x450.jpg&quot;</span><span class="token punctuation">,</span> width<span class="token operator">:</span> <span class="token number">800</span><span class="token punctuation">,</span> height<span class="token operator">:</span> <span class="token number">450</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
107      <span class="token punctuation">{</span> src<span class="token operator">:</span> <span class="token string">&quot;/image2_400x225.jpg&quot;</span><span class="token punctuation">,</span> width<span class="token operator">:</span> <span class="token number">400</span><span class="token punctuation">,</span> height<span class="token operator">:</span> <span class="token number">225</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
108    <span class="token punctuation">]</span><span class="token punctuation">,</span>
109  <span class="token punctuation">}</span><span class="token punctuation">,</span>
110<span class="token punctuation">]</span><span class="token punctuation">;</span>
111
112<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">Gallery</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
113  <span class="token keyword">return</span> <span class="token punctuation">(</span>
114    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">RowsPhotoAlbum</span></span>
115      <span class="token attr-name">photos</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>photos<span class="token punctuation">}</span></span>
116      <span class="token attr-name">sizes</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span>
117        size<span class="token operator">:</span> <span class="token string">&quot;1168px&quot;</span><span class="token punctuation">,</span>
118        sizes<span class="token operator">:</span> <span class="token punctuation">[</span>
119          <span class="token punctuation">{</span>
120            viewport<span class="token operator">:</span> <span class="token string">&quot;(max-width: 1200px)&quot;</span><span class="token punctuation">,</span>
121            size<span class="token operator">:</span> <span class="token string">&quot;calc(100vw - 32px)&quot;</span><span class="token punctuation">,</span>
122          <span class="token punctuation">}</span><span class="token punctuation">,</span>
123        <span class="token punctuation">]</span><span class="token punctuation">,</span>
124      <span class="token punctuation">}</span><span class="token punctuation">}</span></span>
125    <span class="token punctuation">/&gt;</span></span>
126  <span class="token punctuation">)</span><span class="token punctuation">;</span>
127<span class="token punctuation">}</span>
128</code></pre>
129<h3 id="HowItWorks_SSR">SSR<a href="#HowItWorks_SSR" title="Direct link to SSR" aria-label="Direct link to SSR"></a></h3>
130<p>React Photo Album extensively uses CSS flexbox and CSS <code>calc</code> functions to
131calculate images&#x27; dimensions on the client. Thanks to this approach, server-side
132rendered markup looks pixel-perfect on the client even before hydration. To
133enable server-side rendering, specify the <code>defaultContainerWidth</code> prop.
134Otherwise, React Photo Album produces empty markup on the server and renders on
135the client only after hydration. Please note that unless your photo album is of
136constant width that always matches the <code>defaultContainerWidth</code> value, you will
137most likely see a layout shift immediately after hydration. Alternatively, you
138can provide a fallback skeleton in the <code>skeleton</code> prop that will be rendered in
139SSR and swapped with the actual photo album markup after hydration. Please also
140refer to the
141<a href="/documentation#Server-SideRendering(SSR)">Server-Side Rendering</a>
142documentation for a comprehensive list of available solutions.</p>
143<h2 id="Sponsors">Sponsors<a href="#Sponsors" title="Direct link to Sponsors" aria-label="Direct link to Sponsors"></a></h2>
144<p>This project is supported by the following companies, organizations, and
145individuals who help make its continued development and maintenance possible.</p>
146<p align="center"><a target="_blank" rel="noreferrer noopener" href="https://cdn.jsdelivr.net/gh/igordanchenko/sponsors/sponsors.svg"><img src="https://cdn.jsdelivr.net/gh/igordanchenko/sponsors/sponsors.svg" alt="Sponsors"/></a></p>
147<p>Support this project by becoming a
148<a href="https://github.com/sponsors/igordanchenko" target="_blank" rel="noreferrer noopener">sponsor</a>. Both recurring and
149one-time contributions are very much appreciated.</p>
150<h2 id="Credits">Credits<a href="#Credits" title="Direct link to Credits" aria-label="Direct link to Credits"></a></h2>
151<p>Thanks to Sandra G (aka <a href="https://github.com/neptunian" target="_blank" rel="noreferrer noopener">neptunian</a>) for authoring
152the original
153<a href="https://github.com/neptunian/react-photo-gallery" target="_blank" rel="noreferrer noopener">react-photo-gallery</a> library
154that served as inspiration and foundation for
155<a href="https://github.com/igordanchenko/react-photo-album" target="_blank" rel="noreferrer noopener">react-photo-album</a>.</p>
156<h2 id="License">License<a href="#License" title="Direct link to License" aria-label="Direct link to License"></a></h2>
157<p>MIT © 2021 <a href="https://github.com/igordanchenko" target="_blank" rel="noreferrer noopener">Igor Danchenko</a></p><!--$--><!--/$--><hr class="print:hidden"/><nav aria-label="Quick links" class="flex flex-wrap gap-4 -mt-4 not-prose print:hidden"><span class="flex flex-grow justify-end"><a class="inline-flex group font-bold p-3 outline-0" href="/documentation"><span class="link group-hover:decoration-2 group-focus-visible:decoration-2">Documentation</span><span class="group-hover:text-link-underline dark:group-hover:text-link-underline-invert ml-2">»</span></a></span></nav></main><div aria-hidden="true" class="fixed bottom-4 w-10 h10 text-2xl transition duration-200 print:hidden right-[max(1rem,_1rem_+_(100%_-_80rem)_/_2)] scale-0"><button type="button" class="not-prose relative box-border outline-0 outline-none m-0 border-0 cursor-pointer select-none align-middle no-underline hover:no-underline overflow-hidden transition duration-300 [-webkit-tap-highlight-color:transparent] p-2 shrink-0 rounded-full text-text bg-secondary hover:bg-secondary-dark shadow-fab active:shadow-fab-active" title="Scroll to Top"><svg aria-hidden="true" focusable="false" viewBox="0 0 24 24" class="select-none fill-current w-[1em] h-[1em]">
157<path d="M7.41 15.41 12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path></svg></button></div></div>
157<script src="https://assets.react-photo-album.com/_next/static/immutable/chunks/36k8in9a291ok.js" id="_R_" async=""></script>
157<script>(self.__next_f=self.__next_f||[]).push([0])</script>
157<script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[79520,[\"https://assets.react-photo-album.com/_next/static/immutable/chunks/1ty7z5-qzonhg.js\",\"https://assets.react-photo-album.com/_next/static/immutable/chunks/3-sc2wqugqoo_.js\"],\"\"]\n3:I[8044,[\"https://assets.react-photo-album.com/_next/static/immutable/chunks/1ty7z5-qzonhg.js\",\"https://assets.react-photo-album.com/_next/static/immutable/chunks/3-sc2wqugqoo_.js\"],\"default\"]\n4:I[2120,[\"https://assets.react-photo-album.com/_next/static/immutable/chunks/1ty7z5-qzonhg.js\",\"https://assets.react-photo-album.com/_next/static/immutable/chunks/3-sc2wqugqoo_.js\"],\"default\"]\n8:I[68027,[\"https://assets.react-photo-album.com/_next/static/immutable/chunks/1ty7z5-qzonhg.js\",\"https://assets.react-photo-album.com/_next/static/immutable/chunks/3-sc2wqugqoo_.js\"],\"default\",1]\n:HL[\"https://assets.react-photo-album.com/_next/static/immutable/chunks/2h86bkwzmn_lt.css\",\"style\"]\n:HL[\"https://assets.react-photo-album.com/_next/static/immutable/media/83afe278b6a6bb3c-s.p.45535valc9rzk.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"https://assets.react-photo-album.com/_next/static/immutable/media/b8b552e8609c5636-s.p.1mao1hin7sitq.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n0:{\"P\":null,\"c\":[\"\",\"\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"__PAGE__\",{},\"$undefined\",\"$undefined\",4608]},\"$undefined\",\"$undefined\",4624],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"https://assets.react-photo-album.com/_next/static/immutable/chunks/2h86bkwzmn_lt.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"https://assets.react-photo-album.com/_next/static/immutable/chunks/1ty7z5-qzonhg.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"https://assets.react-photo-album.com/_next/static/immutable/chunks/3-sc2wqugqoo_.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"className\":\"inter_709f7113-module__S4rG8G__variable fira_code_af5fb8ee-module__X-BCKq__variable\",\"children\":[[\"$\",\"head\",null,{\"children\":[[\"$\",\"script\",null,{\"id\":\"select-theme\",\"dangerouslySetInnerHTML\":{\"__html\":\"!function(){var e,l,a,n=null===(e=(l=window).matchMedia)||void 0===e?void 0:e.call(l,\\\"(prefers-color-scheme: dark)\\\");function t(){\\\"dark\\\"===localStorage.theme||!(\\\"theme\\\"in localStorage)\u0026\u0026null!=n\u0026\u0026n.matches?document.documentElement.classList.add(\\\"dark\\\"):document.documentElement.classList.remove(\\\"dark\\\")}t(),null==n||null===(a=n.addEventListener)||void 0===a||a.call(n,\\\"change\\\",t)}();\"}}],[[\"$\",\"$L2\",null,{\"id\":\"gtag.js\",\"strategy\":\"lazyOnload\",\"src\":\"https://www.googletagmanager.com/gtag/js?id=G-XL5341CQ1R\"}],[\"$\",\"$L2\",null,{\"id\":\"google-analytics\",\"strategy\":\"lazyOnload\",\"children\":\"window.dataLayer=window.dataLayer||[];function gtag(){window.dataLayer.push(arguments);}gtag('js',new Date());gtag('config','G-XL5341CQ1R')\"}]]]}],[\"$\",\"$L3\",null,{}],[\"$\",\"$L4\",null,{\"logo\":\"React Photo Album\",\"siteTitle\":\"React Photo Album\",\"navigation\":[{\"href\":\"/\",\"title\":\"Introduction\",\"titleOverride\":\"React Photo Album - Responsive photo gallery component for React\",\"description\":\"React Photo Album is a responsive photo gallery component for React. React Photo Album supports rows, columns, and masonry layouts.\",\"thumbnail\":\"https://images.react-photo-album.com/thumbnails/playground.cd1bf9f5.1600x1600.1600w.jpg\"},{\"href\":\"/documentation\",\"title\":\"Documentation\",\"description\":\"React Photo Album allows you to build a responsive photo gallery in React in minutes. To get started, follow the Installation and Minimal Setup Example guides, or feel free to explore the collection of CodeSandbox demos.\"},{\"href\":\"/examples\",\"title\":\"Examples\",\"description\":\"Learn how to use React Photo Album by exploring basic examples with live demos, source code, and ready-to-use code sandboxes.\",\"children\":[{\"href\":\"/examples/rows\",\"t
157itle\":\"Rows Layout\",\"description\":\"Introductory example using rows layout.\",\"thumbnail\":\"https://images.react-photo-album.com/thumbnails/rows.c2875cf5.1540x1540.1540w.jpg\"},{\"href\":\"/examples/columns\",\"title\":\"Columns Layout\",\"description\":\"Introductory example using columns layout.\",\"thumbnail\":\"https://images.react-photo-album.com/thumbnails/columns.6c8946ef.1540x1540.1540w.jpg\"},{\"href\":\"/examples/masonry\",\"title\":\"Masonry Layout\",\"description\":\"Introductory example using masonry layout.\",\"thumbnail\":\"https://images.react-photo-album.com/thumbnails/masonry.5a78159f.1540x1540.1540w.jpg\"},{\"href\":\"/examples/playground\",\"title\":\"Playground\",\"description\":\"Here is an interactive playground to test various parameters in real-time.\",\"thumbnail\":\"https://images.react-photo-album.com/thumbnails/playground.cd1bf9f5.1600x1600.1600w.jpg\"},{\"href\":\"/examples/customization\",\"title\":\"Customization\",\"description\":\"Photo album photos and container elements can be customized via custom render functions.\"},{\"href\":\"/examples/sortable-gallery\",\"title\":\"Sortable Gallery\",\"description\":\"Here is an example of a sortable gallery built with @dnd-kit. You can re-arrange photos via drag-and-drop.\",\"thumbnail\":\"https://images.react-photo-album.com/thumbnails/playground.cd1bf9f5.1600x1600.1600w.jpg\"},{\"href\":\"/examples/nextjs\",\"title\":\"Next.js Image\",\"description\":\"An example showing how to use Next.js Image component with custom renderPhoto function.\"},{\"href\":\"/examples/lightbox\",\"title\":\"Lightbox\",\"description\":\"Here is an example of a photo gallery with a lightbox. You can click any photo to open it in a lightbox. This example is built with yet-another-react-lightbox.\",\"thumbnail\":\"https://images.react-photo-album.com/thumbnails/lightbox.80f97fc7.1600x1600.1600w.jpg\"},{\"href\":\"/examples/infinite-scroll\",\"title\":\"Infinite Scroll\",\"description\":\"An example demonstrating the use of the experimental InfiniteScroll component.\"},{\"href\":\"/examples/zero-cls-ssr\",\"title\":\"Zero CLS SSR\",\"description\":\"An example demonstrating the use of the experimental SSR component that helps to achieve zero CLS in SSR.\"},{\"href\":\"/examples/server\",\"title\":\"Server Component\",\"description\":\"An example demonstrating the use of the experimental ServerPhotoAlbum component.\"}]}],\"npmLink\":\"https://www.npmjs.com/package/react-photo-album\",\"githubLink\":\"https://github.com/igordanchenko/react-photo-album\",\"layoutSize\":\"$undefined\",\"npmLinkDisplay\":\"hidden [@media(min-width:20.625rem)]:block\",\"githubLinkDisplay\":\"hidden [@media(min-width:18.75rem)]:block\",\"themeToggleDisplay\":\"hidden [@media(min-width:23.125rem)]:block\",\"children\":\"$L5\"}]]}]]}],{\"children\":[\"$L6\",{},null,false,null]},null,false,null],\"$L7\",false]],\"m\":\"$undefined\",\"G\":[\"$8\",[\"$L9\"]],\"S\":true,\"h\":null,\"r\":\"$undefined\",\"s\":\"$undefined\",\"a\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"PNlk3oCrILqU2Uab1bAa0\"}\na:I[39756,[\"https://assets.react-photo-album.com/_next/static/immutable/chunks/1ty7z5-qzonhg.js\",\"https://assets.react-photo-album.com/_next/static/immutable/chunks/3-sc2wqugqoo_.js\"],\"default\"]\nb:I[37457,[\"https://assets.react-photo-album.com/_next/static/immutable/chunks/1ty7z5-qzonhg.js\",\"https://assets.react-photo-album.com/_next/static/immutable/chunks/3-sc2wqugqoo_.js\"],\"default\"]\nd:I[97367,[\"https://assets.react-photo-album.com/_next/static/immutable/chunks/1ty7z5-qzonhg.js\",\"https://assets.react-photo-album.com/_next/static/immutable/chunks/3-sc2wqugqoo_.js\"],\"OutletBoundary\"]\ne:\"$Sreact.suspense\"\n10:I[97367,[\"https://assets.react-photo-album.com/_next/static/immutable/chunks/1ty7z5-qzonhg.js\",\"https://assets.react-photo-album.com/_next/static/immutable/chunks/3-sc2wqugqoo_.js\"],\"ViewportBoundary\"]\n12:I[97367,[\"https://assets.react-photo-album.com/_next/static/immutable/chunks/1ty7z5-qzonhg.js\",\"https://assets.react-photo-album.com/_next/static/immutable/chunks/3-sc2wqugqoo_.js\"],\"MetadataBoundary\"]\n5:[\"$\",\"$La\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$Lb\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"div\",null,{\"className\":\"not-prose flex justify-center mt-10\",\"children\":[\"$\",\"div\",null,{\"children\":[\"$\",\"h1\",null,{\"className\":\"font-mono text-xl overflow-hidden border-r-4 border-r-secondary whitespace-nowrap my-0 mx-auto tracking-widest animate-[typewriter_1.5s_steps(30,_end),_typewriter-caret_.5s_step-end_infinite]\",\"children\":\"404, page not found.\"}]}]}],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]\n6:[\"$\",\"$1\",\"c\",{\"children\":[\"$Lc\",[[\"$\",\"script\",\"script-0\",{\"src\":\"https://assets.react-photo-album.com/_next/static/immutable/chunks/1xdqp_r9jcv98.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"$Ld\",null,{\"children\":[\"$\",\"$e\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@f\"}]}]]}]\n7:[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$L10\",null,{\"children\":\"$L11\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$L12\",null,{\"children\":[\"$\",\"$e\",null,{\"name\":\"Next.Metadata\",\"children\":\"$L13\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}]\n9:[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"https://assets.react-photo-album.com/_next/static/immutable/chunks/2h86bkwzmn_lt.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]\n11:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"2\",{\"name\":\"theme-color\",\"content\":\"#1a237e\"}]]\n14:I[27201,[\"https://assets.react-photo-album.com/_next/static/immutable/chunks/1ty7z5-qzonhg.js\",\"https://assets.react-photo-album.com/_next/static/immutable/chunks/3-sc2wqugqoo_.js\"],\"IconMark\"]\nf:null\n13:[[\"$\",\"title\",\"0\",{\"children\":\"React Photo Album - Responsive photo gallery component for React\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"React Photo Album is a responsive photo gallery component for React. React Photo Album supports rows, columns, and masonry layouts.\"}],[\"$\",\"link\",\"2\",{\"rel\":\"manifest\",\"href\":\"/site.webmanifest\",\"crossOrigin\":\"$undefined\"}],[\"$\",\"meta\",\"3\",{\"name\":\"msapplication-TileColor\",\"content\":\"#1a237e\"}],[\"$\",\"meta\",\"4\",{\"name\":\"thumbnail\",\"content\":\"https://images.react-photo-album.com/thumbnails/playground.cd1bf9f5.1600x1600.1600w.jpg\"}],[\"$\",\"link\",\"5\",{\"rel\":\"canonical\",\"href\":\"https://react-photo-album.com\"}],[\"$\",\"meta\",\"6\",{\"property\":\"og:title\",\"content\":\"React Photo Album\"}],[\"$\",\"meta\",\"7\",{\"property\":\"og:description\",\"content\":\"React Photo Album is a responsive photo gallery component for React. React Photo Album supports rows, columns, and masonry layouts.\"}],[\"$\",\"meta\",\"8\",{\"property\":\"og:url\",\"content\":\"https://react-photo-album.com\"}],[\"$\",\"meta\",\"9\",{\"property\":\"og:site_name\",\"content\":\"React Photo Album\"}],[\"$\",\"meta\",\"10\",{\"property\":\"og:locale\",\"content\":\"en_US\"}],[\"$\",\"meta\",\"11\",{\"property\":\"og:type\",\"content\":\"website\"}],[\"$\",\"meta\",\"12\",{\"name\":\"twitter:card\",\"content\":\"summary\"}],[\"$\",\"meta\",\"13\",{\"name\":\"twitter:title\",\"content\":\"React Photo Album\"}],[\"$\",\"meta\",\"14\",{\"name\":\"twitter:description\",\"content\":\"React Photo Album is a responsive photo gallery component for React. React Photo Album supports rows, columns, and masonry layouts.\"}],[\"$\",\"link\",\"15\",{\"rel\":\"icon\",\"href\":\"/favicon-16x16.png\",\"sizes\":\"16x16\",\"type\":\"image/png\"}],[\"$\",\"link\",\"16\",{\"rel\":\"icon\",\"href\":\"/favicon-32x32.png\",\"sizes\":\"32x32\",\"type\":\"image/png\"}],[\"$\",\"link\",\"17\",{\"rel\":\"apple-touch-icon\",\"href\":\"/apple-touch-icon.png\",\"sizes\":\"180x180\"}],[\"$\",\"link\",\"18\",{\"rel\":\"mask-icon\",\"href\":\"/safari-pinned-tab.svg\",\"color\":\"#1a237e\"}],[\"$\",\"$L14\",\"19\",{}]]\n"])</script>
157<script>self.__next_f.push([1,"15:I[5500,[\"https://assets.react-photo-album.com/_next/static/immutable/chunks/1ty7z5-qzonhg.js\",\"https://assets.react-photo-album.com/_next/static/immutable/chunks/3-sc2wqugqoo_.js\",\"https://assets.react-photo-album.com/_next/static/immutable/chunks/1xdqp_r9jcv98.js\"],\"Image\"]\n:HL[\"https://img.shields.io/npm/v/react-photo-album.svg?color=blue\",\"image\"]\n:HL[\"https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fregistry.npmjs.org%2Freact-photo-album%2Flatest\u0026query=%24.bundleSize\u0026label=bundle%20size\u0026color=blue\u0026cacheSeconds=3600\",\"image\"]\n:HL[\"https://img.shields.io/npm/l/react-photo-album.svg?color=blue\",\"image\"]\nc:[[\"$\",\"div\",null,{\"align\":\"center\",\"children\":[[\"$\",\"$L15\",null,{\"priority\":true,\"src\":\"/logo.a08aca3c.640x640.webp\",\"width\":180,\"height\":180,\"className\":\"my-0\",\"alt\":\"\"}],[\"$\",\"h1\",null,{\"id\":\"ReactPhotoAlbum\",\"children\":[\"React Photo Album\",[\"$\",\"a\",null,{\"href\":\"#ReactPhotoAlbum\",\"title\":\"Direct link to React Photo Album\",\"aria-label\":\"Direct link to React Photo Album\"}]]}],[\"$\",\"p\",null,{\"className\":\"badges not-prose\",\"children\":[[\"$\",\"a\",null,{\"ref\":\"$undefined\",\"href\":\"https://www.npmjs.com/package/react-photo-album\",\"target\":\"_blank\",\"rel\":\"noreferrer noopener\",\"children\":[\"$\",\"img\",null,{\"src\":\"https://img.shields.io/npm/v/react-photo-album.svg?color=blue\",\"alt\":\"NPM Version\",\"width\":\"$undefined\",\"height\":\"$undefined\",\"style\":{\"width\":\"calc(1rem / 16 * 80)\",\"height\":\"calc(1rem / 16 * 20)\"}}]}],\"\\n\",[\"$\",\"a\",null,{\"ref\":\"$undefined\",\"href\":\"https://github.com/igordanchenko/react-photo-album/blob/main/.size-limit.json\",\"target\":\"_blank\",\"rel\":\"noreferrer noopener\",\"children\":[\"$\",\"img\",null,{\"src\":\"https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fregistry.npmjs.org%2Freact-photo-album%2Flatest\u0026query=%24.bundleSize\u0026label=bundle%20size\u0026color=blue\u0026cacheSeconds=3600\",\"alt\":\"Bundle Size\",\"width\":\"$undefined\",\"height\":\"$undefined\",\"style\":{\"width\":\"calc(1rem / 16 * 126)\",\"height\":\"calc(1rem / 16 * 20)\"}}]}],\"\\n\",[\"$\",\"a\",null,{\"ref\":\"$undefined\",\"href\":\"https://github.com/igordanchenko/react-photo-album/blob/main/LICENSE\",\"target\":\"_blank\",\"rel\":\"noreferrer noopener\",\"children\":[\"$\",\"img\",null,{\"src\":\"https://img.shields.io/npm/l/react-photo-album.svg?color=blue\",\"alt\":\"License MIT\",\"width\":\"$undefined\",\"height\":\"$undefined\",\"style\":{\"width\":\"calc(1rem / 16 * 78)\",\"height\":\"calc(1rem / 16 * 20)\"}}]}]]}],[\"$\",\"p\",null,{\"children\":[\"React Photo Album is a responsive photo gallery component with rows, columns,\\nand masonry layouts. \",[\"$\",\"br\",null,{}],\" Inspired by\\n\",[\"$\",\"a\",null,{\"ref\":\"$undefined\",\"href\":\"https://github.com/neptunian/react-photo-gallery\",\"target\":\"_blank\",\"rel\":\"noreferrer noopener\",\"children\":\"react-photo-gallery\"}],\",\\nre-engineered from the ground up.\"]}]]}],\"\\n\",[\"$\",\"h2\",null,{\"id\":\"Overview\",\"children\":[\"Overview\",[\"$\",\"a\",null,{\"href\":\"#Overview\",\"title\":\"Direct link to Overview\",\"aria-label\":\"Direct link to Overview\"}]]}],\"\\n\",[\"$\",\"ul\",null,{\"children\":[\"\\n\",[\"$\",\"li\",null,{\"children\":[[\"$\",\"strong\",null,{\"children\":\"Built for React:\"}],\" works with React 18+\"]}],\"\\n\",[\"$\",\"li\",null,{\"children\":[[\"$\",\"strong\",null,{\"children\":\"SSR friendly:\"}],\" produces server-side rendered markup that looks\\npixel-perfect on the client even before hydration\"]}],\"\\n\",[\"$\",\"li\",null,{\"children\":[[\"$\",\"strong\",null,{\"children\":\"Responsive images:\"}],\" responsive images with automatic resolution switching\\nare supported out of the box\"]}],\"\\n\",[\"$\",\"li\",null,{\"children\":[[\"$\",\"strong\",null,{\"children\":\"Feature-packed:\"}],\" supports 3 layout options (rows, columns, and masonry),\\nresponsive images, custom data attributes, and is fully configurable and\\ncustomizable\"]}],\"\\n\",[\"$\",\"li\",null,{\"children\":[[\"$\",\"strong\",null,{\"children\":\"TypeScript:\"}],\" type definitions come built-in with the package\"]}],\"\\n\",[\"$\",\"li\",null,{\"children\":[[\"$\",\"strong\",null,{\"children\":\"Performance:\"}],\" built with performance in mind to support large photo albums\"]}],\"\\n\"]}],\"\\n\",[\"$\",\"h2\",null,{\"id\":\"Layouts\",\"children\":[\"Layouts\",[\"$\",\"a\",null,{\"href\":\"#Layouts\",\"title\":\"Direct link to Layouts\",\"aria-label\":\"Direct link to Layouts\"}]]}],\"\\n\",[\"$\",\"h3\",null,{\"id\":\"Layouts_Rows\",\"children\":[\"Rows\",[\"$\",\"a\",null,{\"href\":\"#Layouts_Rows\",\"t
157itle\":\"Direct link to Rows\",\"aria-label\":\"Direct link to Rows\"}]]}],\"\\n\",[\"$\",\"p\",null,{\"children\":[\"$\",\"$L15\",null,{\"priority\":true,\"src\":\"/layouts/rows.0a16b150.2000x1906.jpg\",\"width\":2000,\"height\":1906,\"className\":\"my-0\",\"alt\":\"React Photo Album | Rows Layout\",\"sizes\":\"(max-width: 429px) calc(100vw - 32px), (max-width: 699px) calc(100vw - 48px), (max-width: 1287px) calc(100vw - 240px - 48px), 1000px\"}]}],\"\\n\",[\"$\",\"h3\",null,{\"id\":\"Layouts_Columns\",\"children\":[\"Columns\",[\"$\",\"a\",null,{\"href\":\"#Layouts_Columns\",\"title\":\"Direct link to Columns\",\"aria-label\":\"Direct link to Columns\"}]]}],\"\\n\",[\"$\",\"p\",null,{\"children\":[\"$\",\"$L15\",null,{\"priority\":true,\"src\":\"/layouts/columns.2aa2453c.2000x1586.jpg\",\"width\":2000,\"height\":1586,\"className\":\"my-0\",\"alt\":\"React Photo Album | Columns Layout\",\"sizes\":\"(max-width: 429px) calc(100vw - 32px), (max-width: 699px) calc(100vw - 48px), (max-width: 1287px) calc(100vw - 240px - 48px), 1000px\"}]}],\"\\n\",\"$L16\",\"\\n\",\"$L17\",\"\\n\",\"$L18\",\"\\n\",\"$L19\",\"\\n\",\"$L1a\",\"\\n\",\"$L1b\",\"\\n\",\"$L1c\",\"\\n\",\"$L1d\",\"\\n\",\"$L1e\",\"\\n\",\"$L1f\",\"\\n\",\"$L20\",\"\\n\",\"$L21\",\"\\n\",\"$L22\",\"\\n\",\"$L23\",\"\\n\",\"$L24\",\"\\n\",\"$L25\",\"\\n\",\"$L26\",\"\\n\",\"$L27\",\"\\n\",\"$L28\",\"\\n\",\"$L29\",\"\\n\",\"$L2a\",\"\\n\",\"$L2b\",\"\\n\",\"$L2c\",\"\\n\",\"$L2d\",\"\\n\",\"$L2e\",\"\\n\",\"$L2f\",\"\\n\",\"$L30\",\"\\n\",\"$L31\",\"\\n\",\"$L32\",\"\\n\",\"$L33\",\"\\n\",\"$L34\",\"\\n\",\"$L35\",\"\\n\",\"$L36\",\"\\n\",\"$L37\"]\n"])</script>
157<script>self.__next_f.push([1,"38:I[22016,[\"https://assets.react-photo-album.com/_next/static/immutable/chunks/1ty7z5-qzonhg.js\",\"https://assets.react-photo-album.com/_next/static/immutable/chunks/3-sc2wqugqoo_.js\",\"https://assets.react-photo-album.com/_next/static/immutable/chunks/1xdqp_r9jcv98.js\"],\"default\"]\n:HL[\"https://cdn.jsdelivr.net/gh/igordanchenko/sponsors/sponsors.svg\",\"image\"]\n16:[\"$\",\"h3\",null,{\"id\":\"Layouts_Masonry\",\"children\":[\"Masonry\",[\"$\",\"a\",null,{\"href\":\"#Layouts_Masonry\",\"title\":\"Direct link to Masonry\",\"aria-label\":\"Direct link to Masonry\"}]]}]\n17:[\"$\",\"p\",null,{\"children\":[\"$\",\"$L15\",null,{\"priority\":true,\"src\":\"/layouts/masonry.e4db4daa.2000x1856.jpg\",\"width\":2000,\"height\":1856,\"className\":\"my-0\",\"alt\":\"React Photo Album | Masonry Layout\",\"sizes\":\"(max-width: 429px) calc(100vw - 32px), (max-width: 699px) calc(100vw - 48px), (max-width: 1287px) calc(100vw - 240px - 48px), 1000px\"}]}]\n18:[\"$\",\"h2\",null,{\"id\":\"Documentation\",\"children\":[\"Documentation\",[\"$\",\"a\",null,{\"href\":\"#Documentation\",\"title\":\"Direct link to Documentation\",\"aria-label\":\"Direct link to Documentation\"}]]}]\n19:[\"$\",\"p\",null,{\"children\":[\"$\",\"$L38\",null,{\"ref\":\"$undefined\",\"href\":\"/documentation\",\"prefetch\":false,\"children\":\"https://react-photo-album.com/documentation\"}]}]\n1a:[\"$\",\"h2\",null,{\"id\":\"Examples\",\"children\":[\"Examples\",[\"$\",\"a\",null,{\"href\":\"#Examples\",\"title\":\"Direct link to Examples\",\"aria-label\":\"Direct link to Examples\"}]]}]\n1b:[\"$\",\"p\",null,{\"children\":[\"$\",\"$L38\",null,{\"ref\":\"$undefined\",\"href\":\"/examples\",\"prefetch\":false,\"children\":\"https://react-photo-album.com/examples\"}]}]\n1c:[\"$\",\"h2\",null,{\"id\":\"Changelog\",\"children\":[\"Changelog\",[\"$\",\"a\",null,{\"href\":\"#Changelog\",\"title\":\"Direct link to Changelog\",\"aria-label\":\"Direct link to Changelog\"}]]}]\n1d:[\"$\",\"p\",null,{\"children\":[\"$\",\"a\",null,{\"ref\":\"$undefined\",\"href\":\"https://github.com/igordanchenko/react-photo-album/releases\",\"target\":\"_blank\",\"rel\":\"noreferrer noopener\",\"children\":\"https://github.com/igordanchenko/react-photo-album/releases\"}]}]\n1e:[\"$\",\"h2\",null,{\"id\":\"Installation\",\"children\":[\"Installation\",[\"$\",\"a\",null,{\"href\":\"#Installation\",\"title\":\"Direct link to Installation\",\"aria-label\":\"Direct link to Installation\"}]]}]\n1f:[\"$\",\"pre\",null,{\"children\":[\"$\",\"code\",null,{\"className\":\"language-shell\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token function\",\"children\":\"npm\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token function\",\"children\":\"install\"}],\" react-photo-album\\n\"]}]}]\n20:[\"$\",\"h2\",null,{\"id\":\"Requirements\",\"children\":[\"Requirements\",[\"$\",\"a\",null,{\"href\":\"#Requirements\",\"title\":\"Direct link to Requirements\",\"aria-label\":\"Direct link to Requirements\"}]]}]\n21:[\"$\",\"ul\",null,{\"children\":[\"\\n\",[\"$\",\"li\",null,{\"children\":\"React 18+\"}],\"\\n\",[\"$\",\"li\",null,{\"children\":\"Node 18+\"}],\"\\n\",[\"$\",\"li\",null,{\"children\":\"modern ESM-compatible bundler\"}],\"\\n\"]}]\n22:[\"$\",\"h2\",null,{\"id\":\"MinimalSetupExample\",\"children\":[\"Minimal Setup Example\",[\"$\",\"a\",null,{\"href\":\"#MinimalSetupExample\",\"title\":\"Direct link to Minimal Setup Example\",\"aria-label\":\"Direct link to Minimal Setup Example\"}]]}]\n23:[\"$\",\"pre\",null,{\"children\":[\"$\",\"code\",null,{\"className\":\"language-tsx\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token keyword\",\"children\":\"import\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\" RowsPhotoAlbum \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token keyword\",\"children\":\"from\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"\\\"react-photo-album\\\"\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\";\"}],\"\\n\",[\"$\",\"span\",null,{\"className\":\"token keyword\",\"children\":\"import\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"\\\"react-photo-album/rows.css\\\"\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\";\"}],\"\\n\\n\",[\"$\",\"span\",null,{\"className\":\"token keyword\",\"children\":\"const\"}],\" photos \",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\"=\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"[\"}],\"\\n  \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\" src\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"\\\"/image1.jpg\\\"\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\" width\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token number\",\"children\":\"800\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\" height\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token number\",\"children\":\"600\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n  \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\" src\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"\\\"/image2.jpg\\\"\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\" width\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token number\",\"children\":\"1600\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\" height\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token number\",\"children\":\"900\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n\",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"]\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\";\"}],\"\\n\\n\",[\"$\",\"span\",null,{\"className\":\"token keyword\",\"children\":\"export\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token keyword\",\"children\":\"default\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token keyword\",\"children\":\"function\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token function\",\"children\":\"Gallery\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"(\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\")\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\"\\n  \",[\"$\",\"span\",null,{\"className\":\"token keyword\",\"children\":\"return\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token tag\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token tag\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"\u003c\"}],[\"$\",\"span\",null,{\"className\":\"token class-name\",\"children\":\"RowsPhotoAlbum\"}]]}],\" \",[\"$\",\"span\",null,{\"className\":\"token attr-name\",\"children\":\"photos\"}],[\"$\",\"span\",null,{\"className\":\"token script language-javascript\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token script-punctuation punctuation\",\"children\":\"=\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\"photos\",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}]]}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"/\u003e\"}]]}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\";\"}],\"\\n\",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}],\"\\n\"]}]}]\n24:[\"$\",\"h2\",null,{\"id\":\"HowItWorks\",\"children\":[\"How It Works\",[\"$\",\"a\",null,{\"href\":\"#HowItWorks\",\"title\":\"Direct link to How It Works\",\"aria-label\":\"Direct link to How It Works\"}]]}]\n25:[\"$\",\"h3\",null,{\"id\":\"HowItWorks_RowsLayout\",\"children\":[\"Rows Layout\",[\"$\",\"a\",null,{\"href\":\"#HowItWorks_RowsLayout\",\"title\":\"Direct link to Rows Layout\",\"aria-label\":\"Direct link to Rows Layout\"}]]}]\n26:[\"$\",\"p\",null,{\"children\":[\"Rows layout fills the container space by arranging photos into rows that are\\nsimilar in height, with the height of each row being as close to the\\n\",[\"$\",\"code\",null,{\"children\":\"targetRowHeight\"}],\" as possible. This layout is inspired by the Knuth and Plass\\nline-breaking algorithm and uses dynamic programming to find optimal row breaks\\nin a DAG (directed acyclic graph) where photo indices are nodes and each\\npossible row is an edge connecting its first and last photo. The cost of each\\nedge is a weighted squared deviation from the \",[\"$\",\"code\",null,{\"children\":\"targetRowHeight\"}],\". This algorithm\\nproduces rows that are similar in height and photos that are not stretched or\\nabnormally shrunk (as happens in a naive implementation). It solves the issue of\\npanoramas shrinking rows, stragglers, or stretched images in the last row.\"]}]\n27:[\"$\",\"h3\",null,{\"id\":\"HowItWorks_ColumnsLayout\",\"children\":[\"Columns Layout\",[\"$\",\"a\",null,{\"href\":\"#HowItWorks_ColumnsLayout\",\"title\":\"Direct link to Columns Layout\",\"aria-label\":\"Direct link to Columns Layout\"}]]}]\n28:[\"$\",\"p\",null,{\"children\":[\"Columns layout fills the container space by arranging photos into a predefined\\nnumber of columns, determined by the \",[\"$\",\"code\",null,{\"children\":\"columns\"}],\" parameter. This layout uses a\\ndynamic programming algorithm to find the optimal partition of photos into the\\nspecified number of groups (columns) that produces the most balanced layout.\\nColumn widths are then adjusted proportionally based on their content's aspect\\nratios so that all c
157olumns render at equal height.\"]}]\n29:[\"$\",\"h3\",null,{\"id\":\"HowItWorks_MasonryLayout\",\"children\":[\"Masonry Layout\",[\"$\",\"a\",null,{\"href\":\"#HowItWorks_MasonryLayout\",\"title\":\"Direct link to Masonry Layout\",\"aria-label\":\"Direct link to Masonry Layout\"}]]}]\n2a:[\"$\",\"p\",null,{\"children\":\"Masonry layout arranges photos into columns of equal width by placing each photo\\ninto the shortest column. This layout does not fill the container space flush to\\nits bottom edge, but the columns end up being as close in height to each other\\nas possible.\"}]\n2b:[\"$\",\"h3\",null,{\"id\":\"HowItWorks_ResponsiveImages\",\"children\":[\"Responsive Images\",[\"$\",\"a\",null,{\"href\":\"#HowItWorks_ResponsiveImages\",\"title\":\"Direct link to Responsive Images\",\"aria-label\":\"Direct link to Responsive Images\"}]]}]\n2c:[\"$\",\"p\",null,{\"children\":[\"React Photo Album can automatically produce \",[\"$\",\"code\",null,{\"children\":\"sizes\"}],\" and \",[\"$\",\"code\",null,{\"children\":\"srcset\"}],\" image\\nattributes. In the case of SSR, React Photo Album includes \",[\"$\",\"code\",null,{\"children\":\"sizes\"}],\" and \",[\"$\",\"code\",null,{\"children\":\"srcset\"}],\"\\nimage attributes in the server-rendered markup, allowing browsers to pick images\\nof the most appropriate resolution depending on the end-user viewport size. To\\nutilize images with automatic resolution switching, provide images of different\\nresolutions in the photo \",[\"$\",\"code\",null,{\"children\":\"srcSet\"}],\" attribute. To further improve app\\nresponsiveness and bandwidth utilization, you can specify the \",[\"$\",\"code\",null,{\"children\":\"sizes\"}],\" prop that\\ndescribes the width of the photo album in various viewports.\"]}]\n2d:[\"$\",\"pre\",null,{\"children\":[\"$\",\"code\",null,{\"className\":\"language-tsx\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token keyword\",\"children\":\"import\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\" RowsPhotoAlbum \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token keyword\",\"children\":\"from\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"\\\"react-photo-album\\\"\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\";\"}],\"\\n\",[\"$\",\"span\",null,{\"className\":\"token keyword\",\"children\":\"import\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"\\\"react-photo-album/rows.css\\\"\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\";\"}],\"\\n\\n\",[\"$\",\"span\",null,{\"className\":\"token keyword\",\"children\":\"const\"}],\" photos \",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\"=\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"[\"}],\"\\n  \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\"\\n    src\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"\\\"/image1_800x600.jpg\\\"\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n    width\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token number\",\"children\":\"800\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n    height\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token number\",\"children\":\"600\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n    srcSet\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"[\"}],\"\\n      \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\" src\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"\\\"/image1_400x300.jpg\\\"\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\" width\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token number\",\"children\":\"400\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\" height\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token number\",\"children\":\"300\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n      \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\" src\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"\\\"/image1_200x150.jpg\\\"\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\" width\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token number\",\"children\":\"200\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\" height\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token number\",\"children\":\"150\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n    \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"]\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n  \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n  \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\"\\n    src\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"\\\"/image2_1600x900.jpg\\\"\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n    width\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token number\",\"children\":\"1600\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n    height\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token number\",\"children\":\"900\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n    srcSet\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"[\"}],\"\\n      \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\" src\",\"$L39\",\" \",\"$L3a\",\"$L3b\",\" width\",\"$L3c\",\" \",\"$L3d\",\"$L3e\",\" height\",\"$L3f\",\" \",\"$L40\",\" \",\"$L41\",\"$L42\",\"\\n      \",\"$L43\",\" src\",\"$L44\",\" \",\"$L45\",\"$L46\",\" width\",\"$L47\",\" \",\"$L48\",\"$L49\",\" height\",\"$L4a\",\" \",\"$L4b\",\" \",\"$L4c\",\"$L4d\",\"\\n    \",\"$L4e\",\"$L4f\",\"\\n  \",\"$L50\",\"$L51\",\"\\n\",\"$L52\",\"$L53\",\"\\n\\n\",\"$L54\",\" \",\"$L55\",\" \",\"$L56\",\" \",\"$L57\",\"$L58\",\"$L59\",\" \",\"$L5a\",\"\\n  \",\"$L5b\",\" \",\"$L5c\",\"\\n    \",\"$L5d\",\"\\n  \",\"$L5e\",\"$L5f\",\"\\n\",\"$L60\",\"\\n\"]}]}]\n2e:[\"$\",\"h3\",null,{\"id\":\"HowItWorks_SSR\",\"children\":[\"SSR\",[\"$\",\"a\",null,{\"href\":\"#HowItWorks_SSR\",\"title\":\"Direct link to SSR\",\"aria-label\":\"Direct link to SSR\"}]]}]\n2f:[\"$\",\"p\",null,{\"children\":[\"React Photo Album extensively uses CSS flexbox and CSS \",[\"$\",\"code\",null,{\"children\":\"calc\"}],\" functions to\\ncalculate images' dimensions on the client. Thanks to this approach, server-side\\nrendered markup looks pixel-perfect on the client even before hydration. To\\nenable server-side rendering, specify the \",[\"$\",\"code\",null,{\"children\":\"defaultContainerWidth\"}],\" prop.\\nOtherwise, React Photo Album produces empty markup on the server and renders on\\nthe client only after hydration. Please note that unless your photo album is of\\nconstant width that always matches the \",[\"$\",\"code\",null,{\"children\":\"defaultContainerWidth\"}],\" value, you will\\nmost likely see a layout shift immediately after hydration. Alternatively, you\\ncan provide a fallback skeleton in the \",[\"$\",\"code\",null,{\"children\":\"skeleton\"}],\" prop that will be rendered in\\nSSR and swapped with the actual photo album markup after hydration. Please also\\nrefer to the\\n\",[\"$\",\"$L38\",null,{\"ref\":\"$undefined\",\"href\":\"/documentation#Server-SideRendering(SSR)\",\"prefetch\":false,\"children\":\"Server-Side Rendering\"}],\"\\ndocumentation for a comprehensive list of available solutions.\"]}]\n30:[\"$\",\"h2\",null,{\"id\":\"Sponsors\",\"children\":[\"Sponsors\",[\"$\",\"a\",null,{\"href\":\"#Sponsors\",\"title\":\"Direct link to Sponsors\",\"aria-label\":\"Direct link to Sponsors\"}]]}]\n31:[\"$\",\"p\",null,{\"children\":\"This project is supported by the following companies, organizations, and\\nindividuals who help make its continued development and maintenance possible.\"}]\n32:[\"$\",\"p\",null,{\"align\":\"center\",\"children\":[\"$\",\"a\",null,{\"target\":\"_blank\",\"rel\":\"noreferrer noopener\",\"href\":\"https://cdn.jsdelivr.net/gh/igordanchenko/sponsors/sponsors.svg\",\"children\":[\"$\",\"img\",null,{\"src\":\"https://cdn.jsdelivr.net/gh/igordanchenko/sponsors/sponsors.svg\",\"alt\":\"Sponsors\",\"width\":\"$undefined\",\"height\"
157:\"$undefined\"}]}]}]\n33:[\"$\",\"p\",null,{\"children\":[\"Support this project by becoming a\\n\",[\"$\",\"a\",null,{\"ref\":\"$undefined\",\"href\":\"https://github.com/sponsors/igordanchenko\",\"target\":\"_blank\",\"rel\":\"noreferrer noopener\",\"children\":\"sponsor\"}],\". Both recurring and\\none-time contributions are very much appreciated.\"]}]\n34:[\"$\",\"h2\",null,{\"id\":\"Credits\",\"children\":[\"Credits\",[\"$\",\"a\",null,{\"href\":\"#Credits\",\"title\":\"Direct link to Credits\",\"aria-label\":\"Direct link to Credits\"}]]}]\n35:[\"$\",\"p\",null,{\"children\":[\"Thanks to Sandra G (aka \",[\"$\",\"a\",null,{\"ref\":\"$undefined\",\"href\":\"https://github.com/neptunian\",\"target\":\"_blank\",\"rel\":\"noreferrer noopener\",\"children\":\"neptunian\"}],\") for authoring\\nthe original\\n\",[\"$\",\"a\",null,{\"ref\":\"$undefined\",\"href\":\"https://github.com/neptunian/react-photo-gallery\",\"target\":\"_blank\",\"rel\":\"noreferrer noopener\",\"children\":\"react-photo-gallery\"}],\" library\\nthat served as inspiration and foundation for\\n\",[\"$\",\"a\",null,{\"ref\":\"$undefined\",\"href\":\"https://github.com/igordanchenko/react-photo-album\",\"target\":\"_blank\",\"rel\":\"noreferrer noopener\",\"children\":\"react-photo-album\"}],\".\"]}]\n36:[\"$\",\"h2\",null,{\"id\":\"License\",\"children\":[\"License\",[\"$\",\"a\",null,{\"href\":\"#License\",\"title\":\"Direct link to License\",\"aria-label\":\"Direct link to License\"}]]}]\n37:[\"$\",\"p\",null,{\"children\":[\"MIT © 2021 \",[\"$\",\"a\",null,{\"ref\":\"$undefined\",\"href\":\"https://github.com/igordanchenko\",\"target\":\"_blank\",\"rel\":\"noreferrer noopener\",\"children\":\"Igor Danchenko\"}]]}]\n"])</script>
157<script>self.__next_f.push([1,"39:[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}]\n3a:[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"\\\"/image2_800x450.jpg\\\"\"}]\n3b:[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}]\n3c:[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}]\n3d:[\"$\",\"span\",null,{\"className\":\"token number\",\"children\":\"800\"}]\n3e:[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}]\n3f:[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}]\n40:[\"$\",\"span\",null,{\"className\":\"token number\",\"children\":\"450\"}]\n41:[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}]\n42:[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}]\n43:[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}]\n44:[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}]\n45:[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"\\\"/image2_400x225.jpg\\\"\"}]\n46:[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}]\n47:[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}]\n48:[\"$\",\"span\",null,{\"className\":\"token number\",\"children\":\"400\"}]\n49:[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}]\n4a:[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}]\n4b:[\"$\",\"span\",null,{\"className\":\"token number\",\"children\":\"225\"}]\n4c:[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}]\n4d:[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}]\n4e:[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"]\"}]\n4f:[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}]\n50:[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}]\n51:[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}]\n52:[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"]\"}]\n53:[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\";\"}]\n54:[\"$\",\"span\",null,{\"className\":\"token keyword\",\"children\":\"export\"}]\n55:[\"$\",\"span\",null,{\"className\":\"token keyword\",\"children\":\"default\"}]\n56:[\"$\",\"span\",null,{\"className\":\"token keyword\",\"children\":\"function\"}]\n57:[\"$\",\"span\",null,{\"className\":\"token function\",\"children\":\"Gallery\"}]\n58:[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"(\"}]\n59:[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\")\"}]\n5a:[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}]\n5b:[\"$\",\"span\",null,{\"className\":\"token keyword\",\"children\":\"return\"}]\n5c:[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"(\"}]\n5d:[\"$\",\"span\",null,{\"className\":\"token tag\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token tag\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"\u003c\"}],[\"$\",\"span\",null,{\"className\":\"token class-name\",\"children\":\"RowsPhotoAlbum\"}]]}],\"\\n      \",[\"$\",\"span\",null,{\"className\":\"token attr-name\",\"children\":\"photos\"}],[\"$\",\"span\",null,{\"className\":\"token script language-javascript\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token script-punctuation punctuation\",\"children\":\"=\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\"photos\",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}]]}],\"\\n      \",[\"$\",\"span\",null,{\"className\":\"token attr-name\",\"children\":\"sizes\"}],[\"$\",\"span\",null,{\"className\":\"token script language-javascript\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token script-punctuation punctuation\",\"children\":\"=\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\"\\n        size\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"\\\"1168px\\\"\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n        sizes\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"[\"}],\"\\n          \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\"\\n            viewport\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"\\\"(max-width: 1200px)\\\"\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n            size\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"\\\"calc(100vw - 32px)\\\"\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n          \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n        \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"]\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n      \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}]]}],\"\\n    \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"/\u003e\"}]]}]\n5e:[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\")\"}]\n5f:[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\";\"}]\n60:[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}]\n"])</script>
157</body></html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.