Skip to content

Getting Started

Terminal window
npm install justified-gallery

Then import the library and its stylesheet. Justified Gallery is an ES module with zero dependencies, so any bundler (Vite, webpack, Next.js, Nuxt…) picks it up as is:

import { JustifiedGallery } from 'justified-gallery';
import 'justified-gallery/style.css';

You can also load it straight from a CDN. Link the stylesheet in the <head>, so it’s ready before the gallery is shown, and import the library from a module script:

<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/justified-gallery@4/dist/assets/justified-gallery.css"
/>
<script type="module">
import { JustifiedGallery } from 'https://cdn.jsdelivr.net/npm/justified-gallery@4/+esm';
const container = document.getElementById('gallery');
const gallery = new JustifiedGallery(container);
gallery.init();
</script>

Make sure to add the justified-gallery class directly to the container in your HTML, as shown below. The stylesheet uses this class to keep the gallery hidden until the layout is ready, avoiding a flash of unstyled, unpositioned images — but only if the class is already there when the page loads, since init() doesn’t add it until your script runs. See Performance Tips for more details.

Here we have a container div that holds a list of links pointing to the original-size images; inside each link there is a thumbnail. When the gallery is initialized, the thumbnails are resized to fill all the available space (i.e. justification).

<div id="gallery" class="justified-gallery">
<a href="path/to/image1.jpg">
<img alt="caption for image 1" src="path/to/image1_thumbnail.jpg" />
</a>
<a href="path/to/image2.jpg">
<img alt="caption for image 2" src="path/to/image2_thumbnail.jpg" />
</a>
...
</div>

Create a JustifiedGallery instance on the container and call init(). Keep the instance around: when the gallery leaves the page (e.g. a route change in a single-page app), call destroy() to stop watching for resizes and restore the original markup.

import { JustifiedGallery } from 'justified-gallery';
import 'justified-gallery/style.css';
const container = document.getElementById('gallery')!;
const gallery = new JustifiedGallery(container);
gallery.init();
// later, when you no longer need it:
gallery.destroy();

Type declarations ship with the package, so the constructor, the options and the methods are typed out of the box, with no extra @types package to install. The settings type isn’t exported from the package entry; if you want to declare your options separately, derive it from the constructor:

import { JustifiedGallery } from 'justified-gallery';
type GalleryOptions = NonNullable<ConstructorParameters<typeof JustifiedGallery>[1]>;
const options: GalleryOptions = {
rowHeight: 160,
margins: 4,
};
const gallery = new JustifiedGallery(container, options);
gallery.init();

The lastRow option and the event names received by triggerEvent are typed as string enums that aren’t exported either, so in TypeScript a plain string needs a cast (lastRow: 'nojustify' as GalleryOptions['lastRow']), and event names are best compared as strings (String(name) === 'jg.complete'). The JavaScript snippets in these docs use the plain strings.

An important configuration of the library is the rowHeight. Consider that you have set a height of 160px; the algorithm tries to build rows with that height:

Three justified rows of thumbnails, with the height of the middle row measured at 160pxThree justified rows of thumbnails, with the height of the middle row measured at 160px

However, the justification may resize the images, and, as a consequence, the row height may be a little different from 160px. This means that the row height is intended as your preferred height (i.e. a lower bound). You can always use the maxRowHeight option to limit the height of the rows, but remember that this option crops the images if they need to be bigger to be justified.

The algorithm builds the rows one after the other until it reaches the last one, which may not have enough images to fill the entire width. In this case you can decide (with the lastRow option) to leave a blank space (aligning the images to the left, center, or right), to justify the images, or to hide the last row if there is too much blank space.

The following is an example where we use smaller images (rowHeight: 70). Furthermore, we don’t justify the last row (lastRow: 'nojustify'), and we are using a margin of 3px (margins: 3).

<div id="gallery" class="justified-gallery">
<a href="path/to/image1.jpg">
<img alt="caption for image 1" src="path/to/image1_thumbnail.jpg" />
</a>
<a href="path/to/image2.jpg" title="Just in a dream Place">
<img alt="caption for image 2" src="path/to/image2_thumbnail.jpg" />
</a>
...
</div>
const gallery = new JustifiedGallery(container, {
rowHeight: 70,
lastRow: 'nojustify',
margins: 3,
});
gallery.init();

If on the server side you have different sizes of the same images (e.g. a thumbnail for small devices, a bigger thumbnail for retina displays, etc.), the library can automatically load the best available thumbnail for the displayed size, so the images always look sharp without downloading more pixels than needed.

To do that you simply have to set the sizeRangeSuffixes option. For example, to match Flickr’s suffixes, you would set it in the following way:

const gallery = new JustifiedGallery(container, {
sizeRangeSuffixes: {
100: '_t', // up to 100px on the longest side
240: '_m', // 100px to 240px
320: '_n',
500: '',
640: '_z',
1024: '_b', // more than 640px
},
});
gallery.init();

In this way the library derives the paths of the other thumbnails of the same image by only changing the filename suffix. For example, with an entry with the thumbnail path/to/image1_t.jpg, the library could load the thumbnail path/to/image1_b.jpg.

The keys can also be written as 'lt100', 'lt240', and so on — the numeric part is what matters. The Flickr-style map above is also the default value of sizeRangeSuffixes, so if your files follow other conventions (or you only have one thumbnail per image) remember to override it, for example with a single range with an empty suffix ({0: ''}) to always use the thumbnail provided in the HTML. For full control over the thumbnail URLs, use the thumbnailPath option instead.

Explore all the options available for Justified Gallery.