Sprite Sheet Generator — Pack Images into One Sheet, Free
Combine any number of images into a single packed sprite sheet with matching CSS, JSON, and TexturePacker-style coordinates. Auto-trim, shelf packing, and @2x/@3x export — 100% free, runs entirely in your browser.
What it does
This tool takes a batch of separate images — icons, game frames, UI states, whatever — and packs them into one combined sprite sheet PNG, plus the coordinate data you need to actually use it: a CSS file with a background-position rule per sprite, a plain JSON atlas, and a TexturePacker-style JSON hash that Phaser, PixiJS, and most game engines can read directly. Everything happens in your browser; nothing is uploaded anywhere.
How it works
You get a choice of two packing strategies. Uniform grid sizes every cell to your largest sprite — simple and predictable, at the cost of some wasted space around smaller images. Shelf packing sorts sprites tallest-first and rows them to fit snugly, which usually produces a noticeably smaller sheet when your sprites vary in size.
Turn on auto-trim and the tool scans each image’s alpha channel to find the actual bounding box of its visible pixels, then packs that tighter box instead of the full canvas — a 200×200 icon with a 40×40 glyph centered in transparent space packs as a 40×40 sprite, with the trim offset recorded in the atlas so consuming code can still position it correctly. Enable power-of-two rounding if your target engine or GPU expects sheet dimensions like 512 or 1024. For pixel-art projects that need matching @2x/@3x asset sets, the tool can export the same sheet at multiple scales in one pass, each with its own coordinate files, using crisp nearest-neighbor scaling rather than a blurry resize.
How to use it
- Drag in your images, or click to browse. Reorder them with the arrow buttons and rename any sprite inline — names default to the sanitized filename.
- Pick a packing mode, padding, and background (transparent or a solid color).
- Toggle auto-trim and power-of-two as needed, and check off any extra export scales.
- Click Generate sheet to see the packed result, then either preview and download the PNG on its own, or grab Download everything as .zip for the sheet plus all three coordinate formats.
Your dropped files are saved in this browser tab automatically, so a refresh won’t lose your batch — clear them any time with the “Clear all” button. If the finished sheet needs to be smaller for shipping, run the PNG through the Compress tool afterward; if you need it as a JPEG or WebP instead, the Format converter handles that in one step.
FAQ
Does this rotate sprites to pack them more tightly? No — sprites are always packed axis-aligned, in their original orientation. Rotation-aware packing adds real complexity for a fairly small space saving in most icon/UI sprite sets, so it’s intentionally left out.
What’s the difference between the generic JSON and the TexturePacker-style JSON? The generic format is a flat array of {name, x, y, w, h} — easy to parse for a custom loader. The TexturePacker-style file follows the frames/meta hash shape that Phaser, PixiJS, and several other engines expect out of the box, including trimmed and sourceSize fields when auto-trim removed transparent padding.
Can I combine sprites of very different sizes on one sheet? Yes — that’s exactly where shelf packing outperforms the uniform grid mode, since it doesn’t force every cell to match your largest image.
Will this work for a large batch, like 100+ icons? Yes, though very large sheets take a moment to pack and render since everything runs on your device rather than a server. If you hit the browser’s file-count warning, it’s just a heads-up, not a hard limit.
Is there a tool that does the opposite — cutting a sheet back into individual frames? Yes — the Sprite Sheet Cutter does exactly that, including grid, cell-size, and auto-detected splitting with an atlas JSON import.
Privacy
Your images are processed entirely in your browser and never uploaded. The current batch is kept in this browser’s local storage so it survives a page refresh, and stays there until you clear it or clear your browser data.