search

Found

info Overview

Output per-frame (x, y, w, h) JSON and CSS background-position rules for uniform-grid sprite sheets, with padding and margin for extrude-aware exports.

📘 How to Use

  1. Enter the image width and height in pixels
  2. Set the column and row counts, plus padding and margin if needed
  3. Switch between JSON and CSS tabs and review the frame coordinates

Sprite Sheet Coordinate Generator

px
px
px
px
Copied!
Article

Sprite Sheet Coordinate Generator | JSON Frames + CSS background-position in One View

Calculate per-frame (x, y, w, h) coordinates from a uniform-grid sprite sheet and output them as a JSON array and as CSS sprite .frame-N { background-position } rules simultaneously. Independent padding (outer border) and margin (gap between frames) cover TexturePacker and Aseprite exports that include extrude or spacing.

💡 About This Tool

Sprite sheets pack many frames into one PNG so a game engine or web page only fetches one image. Phaser, PixiJS, and Godot AnimatedSprite2D expect per-frame (x, y, w, h) data as JSON, while CSS sprites use background-position: -64px 0px style negative offsets to crop the visible window inside an element's box.

This tool calculates those numbers from the same inputs once and displays both formats on demand. Enter the image size, the grid dimensions, optional padding and margin, and the preview canvas overlays each frame with a cyan rectangle so you can confirm the slicing before passing the values into your code.

🧐 Frequently Asked Questions

Q: What is the difference between padding and margin here? A: Padding is the empty border around the outside of the sheet (the same value on all four edges). Margin is the gap between adjacent frames. They map roughly to TexturePacker's "border padding" and "shape padding", and to Aseprite's "border" and "spacing".

Q: Why is my output array empty? A: The frame width or height calculated as (image_size - padding*2 - margin*(count-1)) / count came out zero or negative, meaning padding plus margins consumed the whole image. Reduce padding/margin or the row/column count.

Q: What does the frame field in the JSON represent? A: A row-major index (left-to-right, top-to-bottom). frame: 0 is the top-left cell; with 4 columns, frame: 4 is the leftmost cell of the second row. This matches the frame indexing used by Phaser's spritesheet loader.

Q: Why are the CSS background-position values negative? A: CSS sprites work by shifting the source image up and to the left so the desired region falls into the element's box. A frame whose top-left corner is at (64, 0) needs the image pushed 64 pixels left: background-position: -64px 0px. When x or y is exactly 0 the output keeps 0px instead of -0px.

Q: My frame width came out with two decimal places. Why? A: The image width minus padding and margins does not divide evenly by the column count. The tool keeps two decimals so the rounding error stays visible. For pixel-perfect rendering, adjust the image dimensions or grid counts so the math divides cleanly.

📚 Uniform Grid vs Packed Atlas

Sprite sheets generally come in two flavors. Uniform grid sheets (the kind this tool handles) lay every frame on a fixed-size rectangular grid: the classic format for character walk cycles, tilesets, and icon collections where every frame shares the same bounding box. Packed atlases use rectangle-packing algorithms (TexturePacker, ShoeBox) to cram differently sized frames together with no wasted pixels, but you must rely on the tool's exported JSON to know where each frame ended up.

For uniform grids the math is simple enough that a generator like this can replace a heavyweight packer entirely. The trade-off: every cell allocates the same bounding box, so a small icon in a sheet of large frames wastes texture memory. Pick uniform when frames truly share a size (character animation, tile sets, icon sets at a fixed scale); reach for packed atlases when sizes vary (UI icons, decals, HUD elements).