Sprite Sheet Generator

One image, one request, and the CSS that points at each sprite inside it.

Drop images here or click to choose several files — icons or sprites, selected together

Runs in your browser. Every sprite is read from your disk by your browser and drawn onto a canvas here. The sheet is composed and encoded locally, and the CSS is generated from the coordinates the tool just used. Nothing is uploaded.

What the sprite Sheet Generator does

A sprite sheet packs many small images into one file. A page then shows an individual sprite by setting that file as a background and shifting it with background-position so only the wanted region is visible through an element of the right size. One file, one request, many icons.

This generator packs your images, previews the sheet, and writes the CSS — a shared base class carrying the background image, plus one class per sprite with its exact width, height and negative offset. The class names come from your filenames, cleaned into valid CSS identifiers, so arrow-left.png becomes .icon-arrow-left.

Padding is not decoration. Without it, browsers rendering at fractional zoom levels or on high-density screens can sample a pixel from the neighbouring sprite, producing a thin unwanted line along an icon's edge. Four to eight pixels of transparent padding prevents it.

The uniform-cell option places every sprite in a cell as large as the biggest one, which keeps the maths simple and makes the sheet a regular grid. Turning it off packs each sprite at its natural size using a shelf algorithm, which produces a smaller file and less regular coordinates — both handled correctly in the generated CSS.

Worth being honest about when this technique is worth it. Sprite sheets were a major optimisation under HTTP/1.1, where browsers opened a limited number of connections and each request carried real overhead. Under HTTP/2 and HTTP/3, many small files are multiplexed over one connection and the saving is much smaller. Sprites still help when icons are always used together, and they avoid a flash of unstyled icons — but for flat single-colour icons, an inline SVG sprite is usually a better answer.

How to use it

  1. Select all your icons at once. Filenames become the CSS class names, so name them sensibly first.
  2. Choose a grid and set padding to at least 4px to avoid edge bleed.
  3. Download the PNG as sprites.png and copy the CSS.
  4. Put both in your project and apply two classes to an element: the base class and the sprite class.

A worked example

Four 32-pixel icons packed into a 2 × 2 grid with 4px padding produce a 76 × 76 sheet and this CSS:

.icon {
  background-image: url('sprites.png');
  background-repeat: no-repeat;
  display: inline-block;
}

.icon-arrow-left {
  width: 32px;
  height: 32px;
  background-position: -4px -4px;
}
.icon-arrow-right {
  width: 32px;
  height: 32px;
  background-position: -40px -4px;
}

Used in markup as <span class="icon icon-arrow-left"></span>. Note that the positions are negative: the background is shifted left and up so the wanted sprite lands in the element's visible box. That sign is the thing hand-written sprite CSS most often gets wrong.

Frequently asked questions

Are sprite sheets still worth using?

Less than they were. Under HTTP/1.1 each request was expensive and sprites were a major win; HTTP/2 and HTTP/3 multiplex many small files cheaply. They still help for icon sets always used together, and they avoid icons appearing one at a time. For flat icons, an SVG sprite is usually better.

Why does my sprite show a sliver of the one next to it?

Sub-pixel rendering at non-integer zoom levels or on high-density screens. Increase the padding to 4–8 pixels of transparent space between sprites, which is what the padding control is for.

How do I use the generated CSS?

Save the sheet as sprites.png next to your stylesheet, paste the CSS in, and apply two classes to an element: the base class for the background and the specific class for the position and size.

Can I use this for a CSS animation?

Yes — that is the other classic use. Pack the animation frames in a single row, then animate background-position with steps() timing so it jumps frame to frame rather than sliding.