Shoji

Thumbnails + originals

Two files per photo — a small one for the grid, the original for the lightbox — using the thumb/src fields and the Layout plugin. The grid below only ever loads the small images (labeled thumb); click one and the lightbox loads the — clearly bigger, clearly labeled — original instead. In a real integration these would be genuinely different file sizes (e.g. a 255px-tall fast-disk thumbnail vs. the full-resolution source); here they're inline SVGs sized to make the two tiers visually obvious instead.

width/height below are the original's true pixel dimensions, not the thumbnail's. Supplying them isn't just for the Layout plugin's layout math — the open animation and the open-transition placeholder (the low-res stand-in shown while the original decodes) both require them to show at all. Without them, Shoji doesn't guess a size for either one anymore — it shows the ordinary spinner and skips the "grows out of the thumbnail" animation entirely, revealing the real photo the instant it's ready instead of risking an inaccurate guess — see Transitions for the full explanation.

Shoji not yet initialized.

Code

The live demo above generates its images inline (SVGs, so this file has no external asset dependency) — the shape of the important part, the item objects themselves, is exactly this:

const gallery = new Shoji('#gallery', {
  items: [
    {
      id: 'p1',
      thumb: 'photo-1-thumb.jpg',      // small — this is what the grid tile loads
      src: 'photo-1-original.jpg',     // large — this is what the lightbox loads
      width: 1600,                     // the ORIGINAL's real pixel size — caps the open animation's growth
      height: 1200,
      caption: 'Photo 1',
    },
    { id: 'p2', thumb: 'photo-2-thumb.jpg', src: 'photo-2-original.jpg', width: 1600, height: 1200, caption: 'Photo 2' },
    { id: 'p3', thumb: 'photo-3-thumb.jpg', src: 'photo-3-original.jpg', width: 1600, height: 1200, caption: 'Photo 3' },
    { id: 'p4', thumb: 'photo-4-thumb.jpg', src: 'photo-4-original.jpg', width: 1600, height: 1200, caption: 'Photo 4' },
    { id: 'p5', thumb: 'photo-5-thumb.jpg', src: 'photo-5-original.jpg', width: 1600, height: 1200, caption: 'Photo 5' },
    { id: 'p6', thumb: 'photo-6-thumb.jpg', src: 'photo-6-original.jpg', width: 1600, height: 1200, caption: 'Photo 6' },
  ],
  plugins: [Shoji.Layout],
  layout: { type: 'justified', rowHeight: 180 },
});