How Online Jigsaw Puzzles Work

How an image becomes interlocking pieces, why neighbouring edges match exactly, and what a screen can and cannot reproduce.

Last updated 26 September 2026

8 min read

A jigsaw puzzle in a browser has to solve a problem cardboard solves with a steel die: how do you take a rectangular image and turn it into a few hundred irregular shapes that fit each other exactly, and only each other?

This is how it is done here. None of it is secret, and the mechanics are more interesting than they first appear.

Choosing the grid

Everything starts with a grid: some number of columns by some number of rows. The total is the piece count, which is why the number you pick is a target rather than a promise — the product of two whole numbers rarely lands exactly on 100 or 300.

The choice is not simply the closest product, because piece shape matters. Pieces should be roughly square. A long thin piece has a short edge with no room for a proper tab, which makes it both ugly and ambiguous to place. So the grid is chosen by weighing two things against each other: how close the total comes to what you asked for, and how close each cell comes to square.

The result is usually within a few per cent of the requested count. The board always reports the number it actually cut.

Drawing an edge

Now the interesting part. Every boundary between two neighbouring cells needs a curve — the classic jigsaw profile of a shoulder, a round knob, and another shoulder.

That shape is drawn as three joined cubic Bézier curves. A Bézier curve is defined by its endpoints and a couple of control points that pull the line towards them without being touched, which makes it a natural fit for a smooth bulge. The first curve runs from the corner to the neck of the knob, the second forms the knob itself, and the third runs from the far side of the neck to the next corner.

Every one of those control points is jittered slightly by a random amount, and the knob randomly points to one side or the other. That is what stops the puzzle looking mechanical: no two edges are quite identical, exactly as no two edges of a hand-cut wooden puzzle would be.

The randomness is seeded from the puzzle and the piece count, which means it is reproducible. The same puzzle at the same count cuts identically on every device and after every update — necessary, because otherwise a saved half-finished board would stop matching its own pieces.

Why neighbouring pieces fit exactly

Here is the part that has to be right, and the part where a naive approach fails.

The obvious method is to give each piece four edges and, for each one, calculate the matching shape of its neighbour. That works until floating-point arithmetic introduces tiny discrepancies, and then pieces that should mate exactly are a fraction of a pixel apart, which shows as a hairline gap in an assembled puzzle.

The approach here avoids the calculation entirely. Each internal edge is generated once and stored. The piece on one side traces that stored edge forwards; the piece on the other traces the identical points backwards. Reversing a list of points and reading the same curve segments produces the geometrically identical curve walked in the opposite direction.

Complementarity is therefore structural rather than arithmetic. There is no code path in which two neighbouring edges can disagree, because there is only ever one edge.

Turning outlines into pictures

With the edges defined, each piece's outline is assembled by tracing its top edge left to right, its right edge downwards, its bottom edge right to left, and its left edge upwards — a closed loop in the image's own coordinates.

That outline is then used as a stencil. The drawing surface is clipped to the shape, the whole image is drawn through it, and everything outside the outline is discarded. A light stroke along one side of the edge and a dark stroke along the other fakes the bevel of a die-cut piece, which is what stops an assembled puzzle looking like an unbroken photograph.

Each piece is saved as its own small picture, once, when the puzzle loads. This is the decision that makes large puzzles practical. Redrawing several hundred curved outlines on every animation frame would not hold a smooth frame rate anywhere; copying a few hundred small ready-made pictures is close to free. A 500-piece board redraws in about a millisecond.

Groups, and why they matter

A puzzle where pieces snap together but then have to be dragged individually is unplayable past about fifty pieces. Connected pieces must move as one.

The way that is represented matters more than it sounds. Each piece remembers where it belongs in the finished picture. A group of connected pieces stores a single offset from that finished position, and any piece's actual location is simply its solved position plus its group's offset.

Two consequences follow. Pieces within a group are in exact alignment by construction, so a large assembled block cannot gradually drift out of register no matter how many joins it has accumulated. And merging two groups is a single operation — the moved group adopts the settled group's offset — rather than a recalculation of every piece it contains.

Checking whether two pieces should snap becomes equally simple. If they are neighbours in the grid and their two groups' offsets are within a small tolerance, they belong together. The tolerance is scaled by how far you are zoomed in, so the snap feels the same whether you are working across the whole board or in one corner.

What a screen changes

Two differences from cardboard are worth understanding, because they affect how you play.

The board does not grow. A physical puzzle keeps the same piece size and asks for a bigger table. A screen is fixed, so more pieces means smaller pieces. Past a certain point the fragment of picture on each piece is too small to be useful and you are solving by shape alone. That is why counts here stop at 500 rather than going to 1000: the larger puzzle would work and would not be enjoyable.

Resolution is finite. Every piece is a small picture held in memory, and their total size grows quickly with both piece count and sharpness. Cutting at the highest possible resolution on a phone is a reliable way to have the browser close the tab. So the sharpness is chosen against a memory budget, and on a device reporting little memory the budget is smaller. You will not notice; the alternative would be very noticeable.

What it does not change

None of the machinery alters what you actually do. You still look at a fragment, work out where it belongs, and fit it to its neighbour. The engineering exists to get out of the way — so that the snap lands where you expect, the assembled block moves as one object, and the picture under your cursor is sharp enough to read.

If you want to see it working, pick any puzzle and cut the same image at two different piece counts. Same picture, same code, entirely different evening. Or read about choosing a piece count to decide which one to start with.

Common questions

How are the puzzle pieces created from an image?

The image is divided into a grid, and a curved edge is generated for every boundary between neighbouring cells. Each piece is then drawn by tracing its four edges into a closed outline, clipping the image to that outline, and saving the result as its own small picture. After that the puzzle is just those pictures being moved around.

How do two pieces always fit each other exactly?

Each internal edge is generated once and shared. The piece on one side traces that edge forwards and the piece on the other traces the identical curve backwards, so the two outlines are exact complements by construction rather than by calculation. There is no code path in which neighbouring edges can drift apart.

Why do joined pieces move together?

Because a group of connected pieces is stored as a single offset from the solved picture, not as a collection of individual positions. Every piece in the group keeps its solved relationship to the others automatically, which is why a large assembled block can be dragged as one object without gradually falling out of alignment.