Tutorial

Creating Custom SVG Patterns from Scratch

A step-by-step workflow for designing, refining, and exporting a production-ready SVG background pattern from zero.

13 min read Jan 2026 3 PDF downloads

Step 1: Define the Concept

Before writing a single line of SVG, sketch the pattern on paper. Decide: (1) What is the basic motif? (2) How does it repeat — simple translation, rotation, reflection? (3) What is the tile boundary? (4) What colours? A 5-minute sketch prevents hours of debugging. Photograph your sketch to reference while coding.

Step 2: Choose the Tile Size

The tile size determines how the pattern scales. Small tiles (10–20px) create fine grain textures. Medium tiles (30–60px) are the sweet spot for most patterns. Large tiles (80–200px) create bold, graphic repeats. Choose a tile size that makes the geometry clean — e.g., a hexagonal pattern tile width is always a multiple of r × √3.

Step 3: Draw the Shapes

Use SVG shape primitives: <circle> for dots, <rect> for rectangles, <line> for straight lines, <polyline> and <polygon> for multi-point shapes, and <path> for curves and complex shapes. The <path> element's d attribute uses commands: M (move to), L (line to), C (cubic curve), A (arc), Z (close path).

<!-- Building a simple moroccan tile step by step -->

<!-- Step 1: Start with the outer octagon -->
<path d="M 20,0 L 40,0 L 60,20 L 60,40
         L 40,60 L 20,60 L 0,40 L 0,20 Z"
      fill="none" stroke="#6366f1" stroke-width="1.5"/>

<!-- Step 2: Add inner diamond -->
<polygon points="30,10 50,30 30,50 10,30"
         fill="none" stroke="#6366f1" stroke-width="1"/>

Step 4: Ensure Seamless Tiling

Test tiling by temporarily wrapping your SVG in a <pattern> element and applying it to a large rectangle. Zoom out in the browser to see 20+ tiles at once. Fix any misaligned edges by mirroring shapes that cross boundaries. Any shape touching the edge must re-enter from the opposite edge at the exact same position.

Step 5: Optimize the SVG

Remove unnecessary whitespace, round coordinates to 1 decimal place, eliminate unused attributes, and merge any shapes that can be combined into a single <path>. Run the SVG through SVGO: npx svgo --multipass input.svg -o output.svg. A well-optimized 60px tile pattern should be under 300 bytes.

Step 6: Base64 Encode & Test

In browser DevTools console: btoa(decodeURIComponent(encodeURIComponent(svgString))) handles Unicode characters correctly. Note: simple ASCII SVG content can use plain btoa(). Test the resulting data URI across Chrome, Firefox, and Safari. Also test on a real iPhone and Android device — mobile browsers occasionally render SVG patterns differently.

Step 7: Build Colour Variants

Once the base pattern geometry is solid, create colour variants. Use template literals (JavaScript) or string replacement (PHP) to swap the colour values. Build a systematic set: light mode with your brand's primary colour, a dark mode variant, a high-contrast variant, and a monochrome variant. Archive all variants with their use-case documentation.