
Justified Gallery is a dependency-free JavaScript library that arranges mixed-aspect-ratio images into responsive justified rows.
Each row adapts to the available gallery width, with configurable height, spacing, and behavior for an incomplete final row.
Version 4 uses an ES module class API and no longer requires jQuery. The legacy Justified Gallery page on jQueryScript retains the jQuery 3.8.1 setup for older projects.
Features
- Responsive justified rows for portrait, landscape, and square images.
- Configurable row height, maximum row height, spacing, and gallery border.
- 6 modes for handling an incomplete final row.
- Automatic captions from image alternative text or entry titles.
- CSS selector and function-based filtering.
- Custom sorting or randomized entry order.
- Right-to-left gallery layouts.
- Maximum row count for compact gallery previews.
- Automatic layout recalculation after container width changes.
How To Use It
Installation
Install the package through npm:
npm install justified-gallery
Import the JavaScript class and stylesheet:
import { JustifiedGallery } from 'justified-gallery';
import 'justified-gallery/style.css';
Basic Usage
The default gallery entry selector is a. Each entry normally contains an image or SVG.
Keep the justified-gallery class in the initial markup when the stylesheet loads before JavaScript. This keeps unfinished entries hidden until their calculated positions are ready.
<div id="gallery" class="justified-gallery">
<a href="images/mountain-large.jpg" title="Mountain lake">
<img
src="images/mountain-thumb.jpg"
alt="Mountain lake at sunrise"
>
</a>
<a href="images/coast-large.jpg" title="Rocky coast">
<img
src="images/coast-thumb.jpg"
alt="Rocky coast beside the ocean"
>
</a>
<a href="images/forest-large.jpg" title="Forest trail">
<img
src="images/forest-thumb.jpg"
alt="Trail through a pine forest"
>
</a>
<a href="images/city-large.jpg" title="City skyline">
<img
src="images/city-thumb.jpg"
alt="City skyline after sunset"
>
</a>
</div>
The default thumbnail system expects filename variants such as _m, _z, and _b. Keep conventional image URLs unchanged with thumbnailPath when your files do not follow that suffix scheme.
const galleryElement = document.getElementById('gallery');
const gallery = new JustifiedGallery(galleryElement, {
rowHeight: 180,
margins: 8,
lastRow: 'nojustify',
thumbnailPath: function(currentPath) {
return currentPath;
}
});
gallery.init();
Load It Directly From A CDN
Load its stylesheet in the document head:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/assets/justified-gallery.css" >
Import the JavaScript file from a module script:
<script type="module">
import { JustifiedGallery } from 'https://cdn.jsdelivr.net/npm/[email protected]/dist/justified-gallery.js';
const galleryElement = document.getElementById('gallery');
const gallery = new JustifiedGallery(galleryElement, {
rowHeight: 180,
margins: 8,
thumbnailPath: function(currentPath) {
return currentPath;
}
});
gallery.init();
</script>
Configuration Options
sizeRangeSuffixes(object): Maps image dimensions to filename suffixes. Default:{100: '_t', 240: '_m', 320: '_n', 500: '', 640: '_z', 1024: '_b'}.thumbnailPath(function | undefined): Creates the thumbnail URL from the existing URL, calculated width, calculated height, and image element. It takes priority oversizeRangeSuffixes. Default:undefined.rowHeight(number): Preferred row height in pixels. Default:120.maxRowHeight(number | string | false): Caps row height in pixels or as a percentage ofrowHeight, such as'150%'. Default:false.maxRowsCount(number): Maximum number of displayed rows.0disables the limit. Default:0.margins(number): Space between gallery entries in pixels. Default:1.border(number): Outer gallery border in pixels. A negative value uses the margin value.0removes the border. Default:-1.lastRow(string): Controls an incomplete final row. Accepted values are'justify','nojustify','left','center','right', and'hide'. Default:'nojustify'.justifyThreshold(number): Ratio between0and1that determines when an incomplete row is justified despite the selected last-row mode. Default:0.9.waitThumbnailsLoad(boolean): Waits for thumbnail dimensions before calculating the layout. Default:true.captions(boolean): Enables image captions. The imagealtattribute is checked first, followed by the entrytitleattribute. Default:true.rel(string | null): Sets therelattribute on analyzed gallery entries. Default:null.target(string | null): Sets thetargetattribute on analyzed gallery entries. Default:null.extension(RegExp): Matches the file extension used during automatic thumbnail URL rewriting. Default:/\.[^.\\/]+$/.refreshTime(number): Interval in milliseconds between gallery width checks. Default:200.refreshSensitivity(number): Minimum width change in pixels before the gallery recalculates its layout. Default:0.randomize(boolean): Randomizes gallery entry order before layout. A customsortfunction takes precedence. Default:false.rtl(boolean): Reverses row direction for right-to-left layouts. Default:false.sort(function | false): Comparator function for sorting gallery entries before layout. Default:false.filter(string | function | false): Limits displayed entries with a CSS selector or filter function. Default:false.selector(string): CSS selector used for gallery entries. Default:'a'.imgSelector(string): Selector used to find an image or SVG inside each entry. Default:'img, a > img, svg, a > svg'.triggerEvent(function): Receives lifecycle event names during layout, resize, completion, and destruction. The default function performs no action.
Last Row Alignment
lastRow controls the position and sizing of entries when the final row does not fill the available width.
const gallery = new JustifiedGallery(
document.getElementById('gallery'),
{
rowHeight: 160,
margins: 6,
lastRow: 'center'
}
);
gallery.init();
Available modes:
justify nojustify left center right hide
Image Captions
Captions are enabled by default. Justified Gallery checks the image alt text first and falls back to the entry title.
<div id="gallery" class="justified-gallery">
<a href="large/photo-1.jpg" title="Alternative caption">
<img
src="thumb/photo-1.jpg"
alt="Cabin beside a frozen lake"
>
</a>
</div>
Disable captions during initialization when the gallery should contain images only:
const gallery = new JustifiedGallery(
document.getElementById('gallery'),
{
captions: false
}
);
gallery.init();
Sorting, Filtering, And Random Order
sort accepts a comparison function that receives gallery entry elements.
const gallery = new JustifiedGallery(
document.getElementById('gallery'),
{
sort: function(a, b) {
return Number(a.dataset.order) - Number(b.dataset.order);
}
}
);
gallery.init();
A string passed to filter works as a CSS selector:
<div id="gallery" class="justified-gallery">
<a class="featured" href="large/1.jpg">
<img src="thumb/1.jpg" alt="Mountain">
</a>
<a href="large/2.jpg">
<img src="thumb/2.jpg" alt="Beach">
</a>
<a class="featured" href="large/3.jpg">
<img src="thumb/3.jpg" alt="Forest">
</a>
</div>
const gallery = new JustifiedGallery(
document.getElementById('gallery'),
{
filter: '.featured'
}
);
gallery.init();
Custom Thumbnail URLs
thumbnailPath receives the original image URL, calculated display width, calculated display height, and image element. Image CDN URLs can use the calculated dimensions directly.
const gallery = new JustifiedGallery(
document.getElementById('gallery'),
{
thumbnailPath: function(currentPath, width, height) {
const url = new URL(currentPath, window.location.href);
url.searchParams.set('w', Math.ceil(width));
url.searchParams.set('h', Math.ceil(height));
return url.toString();
}
}
);
gallery.init();
Lifecycle API
Create an instance with a gallery element and an optional settings object:
const gallery = new JustifiedGallery(element, options);
Initialize image analysis, row layout, captions, and width monitoring:
gallery.init();
Remove the gallery instance and its generated layout state:
gallery.destroy();
Lifecycle Callback
triggerEvent receives a lifecycle event name.
const gallery = new JustifiedGallery(
document.getElementById('gallery'),
{
triggerEvent: function(name) {
if (name === 'jg.complete') {
console.log('Gallery layout complete');
}
if (name === 'jg.resize') {
console.log('Gallery layout recalculated');
}
}
}
);
gallery.init();
Available values:
jg.rowflush: A completed row has been positioned.jg.resize: The gallery has been rebuilt after a width change.jg.complete: The initial gallery layout has finished.jg.destroy: The instance has been destroyed.
Alternatives
- Responsive Justified Photo Gallery In JavaScript – Cube Gallery
- Responsive Justified Photo Gallery In JavaScript – flow-gallery
- Flickr-like Photo Grid In Vanilla JavaScript







