Skip to content
UseQR
ESC

↑↓ MOVE↵ OPEN48 PLACES

Spec & internals

QR code SVG path structure

A QR code becomes SVG as path data on a square grid. UseQR merges every dark module into one path element with a single fill, uses integer coordinates at eight pixels per module, and sets shape-rendering to crispEdges on square styles — which is why the output has no anti-aliasing seams between modules.

View as MarkdownPaste this page into any AI assistant — it is plain, portable Markdown.

Two ways to draw the same matrix

Given a matrix of dark modules, an SVG generator has a choice:

One <rect> per module. Simple to emit, miserable to use: a version 5 code has around 700 dark modules, so the file carries ~700 elements, each independently styled, parsed and rendered. Design tools grind on selection, and renderers anti-alias every rectangle's edges separately.

One <path> for everything. Concatenate every module's outline into a single d attribute and fill it once:

<path d="M32 32h8v8h-8z M48 32h8v8h-8z …" fill="#000000"/>

Each M…h…v…z run is one 8 × 8 module; thousands of modules become one element, one fill, one node in every tool that opens the file. This is the structure UseQR emits — the whole data region is a single path, with the three eyes drawn as separate paths (their ring shape uses fill-rule="evenodd" to punch out the hole) so eye colour and shape can be styled independently.

The seam problem, and the three-part fix

The classic defect in QR SVGs is a grid of hairlines between modules — visible on screen at some zoom levels, occasionally even in print. It is anti-aliasing: when adjacent shapes share an edge at a fractional coordinate, the renderer blends each shape's edge with the background separately, leaving a semi-transparent seam where they meet.

The fix is threefold, and all three parts appear in UseQR's output:

  1. Integer coordinates. Modules are placed at (column + quietZone) × moduleSize with a default module size of 8 px and quiet zone of 4 modules — every square-module coordinate is a whole number, so edges land exactly on the pixel grid. (Curved styles round path coordinates to three decimals — precise enough that adjacent curves meet without gaps.)
  2. One merged path. Sub-paths of a single filled path are composited together, not blended edge-by-edge against the background, so shared edges cannot produce seams.
  3. shape-rendering="crispEdges" on the root, applied only for the square module style, telling renderers to prefer hard edges over anti-aliasing. Rounded, dot and organic module styles omit it — they want smooth curves, and their geometry does not tile edge-to-edge anyway.

The parts around the path

A complete generated file is small and predictable: an optional <defs> block (gradients, the logo's clipPath), a background <rect> (omitted entirely for transparent codes), the merged data path, three eye paths, then optional logo image and label text. The viewBox spans (modules + 2 × quietZone) × moduleSize, so the quiet zone is part of the document, not something the placing designer must remember to add.

One structural subtlety worth copying if you build your own: UseQR can emit an SVG Tiny 1.2 profile on request — no clipPath, no ARIA attributes, no shape-rendering — because print RIPs, cutters and older Illustrator versions silently drop full-SVG features they do not understand. Shipping markup a print shop's software ignores is how codes break between proof and product; the print rationale covers that hand-off.

How the same matrix becomes canvas pixels instead is on rendering a QR code from a matrix; and whatever the structure, /validate rasterising and decoding the result is the test that matters.

FAQ

Why does my QR code SVG have thin white lines between squares?

Anti-aliasing seams: adjacent shapes at fractional coordinates get their shared edges blended separately against the background. Fix it with integer module coordinates, merging modules into one path, and shape-rendering set to crispEdges.

Is one path better than many rects in a QR SVG?

Yes, for real use. One merged path means one element to style, faster parsing and rendering, no per-edge anti-aliasing between modules, and dramatically easier handling in design tools — a version 5 code is one node instead of roughly seven hundred.

What is shape-rendering crispEdges for?

It is an SVG hint telling renderers to favour sharp, unblended edges over anti-aliasing. On a square-module QR code it eliminates hairline seams; on rounded or dot styles it is omitted because those shapes should stay smooth.

Can I edit a QR code SVG in Illustrator or Figma?

You can recolour and scale it safely. Avoid reshaping or moving individual modules and never apply effects that shift geometry — and keep the quiet zone that the file's viewBox already includes. Verify the edited export still decodes before printing.

Try it — free, no signup

  • QR code anatomy — every region of the symbolA labelled tour of a QR code: finder patterns, separators, timing, alignment, format and version information, the data region and the quiet zone.
  • Rendering a QR code from a matrixFrom boolean matrix to pixels — module size, quiet zone, device pixel ratio on canvas, and choosing PNG or SVG output. With pseudo-code.
  • Vector vs raster QR codesSVG scales infinitely; a raster QR must be 300+ DPI at final printed size — a 3 cm code needs at least 354 pixels. The print-shop arithmetic.
  • How to make a QR code as an SVGChoose SVG at download or add format=svg to the API URL. A vector QR code scales to any size with perfectly sharp modules and weighs a few kilobytes.
  • Why you should print QR codes from SVGVector QR codes rasterise at the press's native resolution with exact module edges. The PNG-resample chain is how codes that looked sharp on screen die in print.