Create print-ready 4×6 photo grids in your browser.
- Portrait photos → arranged into 2×2 grids (4 photos per sheet)
- Landscape photos → arranged into 2×1 stacks (2 photos per sheet)
- Export everything as a single ZIP containing high-quality JPGs
This is a lightweight, static project: everything lives in index.html.
Every month I gather about 40 images and I print them with a Liene Photo Printer. I add the photos to our family album/journal. This album serves to keeps memories of our year as a family and also generates gratitude. To save money on the photopaper, I put these images in a grid layout so I can print multiple images on one sheet. When creating these grids, I spent a lot of time on Canva or Figma sorting out portrait and landscape images in a grid. Trying to find the most optimum way to utilize photo paper. It cost me in time, though.
Here's a shot of our photo album.
I utilized my development experience to create this tool built in pure JavaScript. It has been one of the best things I have ever built. ✨ You can see it working on my website: magaliechetrit.com/photo-grid-maker.
- Drag & drop or file picker upload
- Automatically sorts photos into portrait vs landscape
- Generates print-ready canvases sized for 4×6 at 300 DPI
- One-click ZIP download (via JSZip)
- On-screen preview before download
- Helpful warnings when the number of photos doesn’t evenly fill a grid
Each output image is rendered to a canvas:
- Canvas size: 1200 × 1800 pixels (4×6 inches at 300 DPI)
- Portrait slot size: 600 × 900 pixels
- Landscape slot size: 1200 × 900 pixels
- Images are resized using a “cover” strategy (cropped to fill the slot)
Because this is a single HTML file, you can open it directly in a browser. For best results (and more consistent behavior across browsers), run a tiny local server.
cd photo-grid-maker
python3 -m http.server 8000Then open:
npx serve .- Open the app in your browser.
- Drag & drop photos onto the drop zone (or click to browse).
- Review the counts and any warnings.
- Click Generate Grids.
- Click Download All (ZIP).
The ZIP will contain files like:
portrait_grid_01.jpg,portrait_grid_02.jpg, …landscape_grid_01.jpg,landscape_grid_02.jpg, …
- If you see a warning about “empty slots”, add more photos to fill the last grid evenly.
- Since the app uses a fill-and-crop approach, keep important subjects away from the edges if you want to avoid accidental cropping.
index.html— UI + all logic (no build step)sample-photos/— example images to test with
- JSZip (loaded from a CDN) — used to create the downloadable ZIP
All processing happens locally in your browser.
- Photos are not uploaded to a server.
- Output is generated in-memory and downloaded directly.
- A list of file names
- Detect duplicate files
- Option to remove duplicates/files from list
- Date-based naming (e.g., january_2025_portrait_01.jpg) for file and folder
- Option to choose grid size (4 or 6 portraits per page)
- Option for bigger photo size, 5x7
- Button to generate and download the photo grid as a PDF
- Styling for a clean, user-friendly interface
No license. Feel free to use, misue and abuse it.
