
Lumosaic is a lightweight, responsive photo gallery library that automatically arranges photos of varying orientations into perfectly aligned rows spanning full container width.
It calculates image dimensions and distributes them intelligently to create a balanced, responsive gallery layout that preserves the original aspect ratios of your images.
Features:
- Intelligent Row Algorithm: Calculates optimal image placement to create perfectly aligned rows that fill container width.
- Automatic Dimension Detection: Retrieves width and height from PNG, JPEG, and WebP files by reading binary headers.
- Responsive Breakpoints: Adjusts row heights automatically for mobile, tablet, and desktop screen sizes.
- Flexible Data Input: Accepts image objects with dimensions, URL arrays, or existing DOM elements.
- Built-in Shuffle Function: Randomizes image order with a single method call.
- Video Support: Displays play button overlays on video cover images.
How To Use It:
1. Download the package and load Lumosaic’s JavaScript & CSS files in the document.
<link rel="stylesheet" href="/lumosaic.css" /> <script src="/lumosaic.js"></script>
2. Create a container element for your photo gallery.
<div id="gallery-container"></div>
3. Initialize the gallery with an array of image objects:
const images = [
{
src: "1.jpg",
width: 800,
height: 600
},
{
src: "2.jpg",
width: 600,
height: 800
},
{
src: "3.jpg",
width: 800,
height: 800
},
// more images here
];// Initialize Lumosaic on the container element
new Lumosaic("gallery-container", images).init();4. You can also pass an array of image URLs. Lumosaic will automatically detect dimensions:
// Simple URL array
const imageUrls = [
"/path/to/1.jpg",
"/path/to/2.jpg",
"/path/to/3.jpg",
];
// Enable automatic dimension retrieval
new Lumosaic("gallery-container", imageUrls).init({
shouldRetrieveWidthAndHeight: true
});5. You can convert existing HTML image elements into a Lumosaic gallery:
<div id="source-images"> <img src="1.jpg" /> <img src="2.jpg" /> <img src="3.jpg" /> </div> <div id="gallery-container"></div>
// Pass the ID of the source container
// The source element will be removed after processing
new Lumosaic("gallery-container", "source-images").init();6. Use the following data attributes for more control:
<div id="source-images">
<img
data-src="full-resolution.jpg"
data-preview="thumbnail.jpg"
data-width="1920"
data-height="1080"
/>
</div>7. All configuration options.
rowHeightSM(float): Height-to-width ratio for mobile devices (screen width < 768px). Default is0.25.rowHeightMD(float): Height-to-width ratio for tablets (screen width ≥ 768px and < 1024px). Default is0.2.rowHeightXL(float): Height-to-width ratio for desktops (screen width ≥ 1024px). Default is0.18.rowHeight(float): Overrides all breakpoint-specific ratios with a single value. Default isnone.shouldRetrieveWidthAndHeight(boolean): Automatically fetches image dimensions from file headers when width and height are not provided. Default isfalse.fallbackImageWidth(integer): Width in pixels used when dimension retrieval fails. Default is1000.fallbackImageHeight(integer): Height in pixels used when dimension retrieval fails. Default is1000.maxImageRatio(float): Maximum width-to-height ratio allowed. Images exceeding this limit will have their width adjusted. Default is1.6.minImageRatio(float): Minimum width-to-height ratio allowed. Images below this limit will have their width adjusted. Default is0.65.maxRows(integer): Maximum number of rows to display. Set to0for unlimited rows. Default is0.stretchLastRow(boolean): Stretches the final row to fill container width by redistributing images from previous rows. Default istrue.shuffleImages(boolean): Randomizes image order before rendering. Default isfalse.gap(integer): Spacing in pixels between images horizontally and between rows vertically. Default is4.playButtonOnVideoCover(boolean): Displays a play button overlay on video cover images. Default istrue.observeWindowWidth(boolean): Triggers gallery re-render when window or container width changes. Default isfalse.
new Lumosaic("gallery-container", "source-images").init({
rowHeightSM: 0.25,
rowHeightMD: 0.2,
rowHeightXL: 0.18,
shouldRetrieveWidthAndHeight: false,
fallbackImageWidth: 1000,
fallbackImageHeight: 1000,
maxImageRatio: 1.6,
minImageRatio: 0.65,
maxRows: 0,
stretchLastRow: true,
shuffleImages: false,
gap: 4,
playButtonOnVideoCover: true,
observeWindowWidth: true
});8. API methods.
// Initialize the gallery and store the instance
const gallery = new Lumosaic("gallery-container", images).init({
maxRows: 3,
gap: 10
});
// Shuffle all images and re-render the gallery
gallery.shuffleImages();
// Replace the entire image collection
// Accepts the same data types as the constructor
const newImages = [
{ src: "new-image-1.jpg", width: 800, height: 600 },
{ src: "new-image-2.jpg", width: 600, height: 800 }
];
gallery.replaceImages(newImages);
// Update configuration options
// The gallery will re-render with new settings
gallery.updateOptions({
gap: 20,
maxRows: 5,
rowHeight: 0.15
});
// Destroy the gallery instance
// Removes all DOM elements and disconnects observers
gallery.destroy();9. Lumosaic works directly with the Obsidium lightbox. Initialize Obsidium after Lumosaic completes rendering:
const images = [
{ src: "1.jpg", width: 800, height: 600 },
{ src: "2.jpg", width: 800, height: 600 },
{ src: "3.jpg", width: 800, height: 800 },
];
// Initialize Lumosaic, then bind Obsidium
const lumosaic = new Lumosaic("gallery-container", images).init().then(() => {
// Obsidium binds to the rendered gallery
new Obsidium("#gallery-container").init();
});FAQs:
Q: Can Lumosaic handle images loaded dynamically after page load?
A: Yes. Call the replaceImages() method with the new image array. Lumosaic will process the new images and re-render the gallery.
Q: How does Lumosaic perform with large image collections?
A: The library uses DocumentFragment for rendering to minimize reflows. For galleries with hundreds of images, set maxRows to limit the initial render.
Q: Can I use Lumosaic with images from different domains?
A: Yes, but automatic dimension detection requires CORS headers from the image server. If the server doesn’t send proper CORS headers, the fetch will fail and Lumosaic will use fallback dimensions.







