SVG · Zero Dependencies · Copy or Download

SVG wave & blob generator

Generate smooth waves for section dividers or flowing blobs for backgrounds and UI elements. Drag the preview to shape them, then export as SVG, a CSS data URI, a JSX component or a PNG.

Wave type
Shape
Fills
Solid side
Fill
Preview backdrop

The backdrop is preview only — it is never written into the SVG.


              

viewBox is the coordinate system, not the size

The single most useful thing to understand about SVG is the separation between viewBox and the element's rendered dimensions. The viewBox declares an internal coordinate space — 0 0 24 24 means the drawing occupies a 24-by-24 grid — while width, height or CSS decide how large that grid is painted. Every coordinate inside the file is expressed in viewBox units and scales automatically.

This is why an SVG icon set standardises on one viewBox: the paths can then be swapped freely and stroke widths stay consistent. It is also why an SVG copied out of a design tool at 1,024 units wide looks wrong beside icons drawn at 24 — the shapes are fine, the coordinate space is not.

When the viewBox aspect ratio differs from the rendered box, preserveAspectRatio decides what happens. The default, xMidYMid meet, scales to fit entirely and centres, leaving empty space. slice fills instead and crops the overflow, and none stretches the drawing non-uniformly. Setting it to none is occasionally what you want for a decorative divider, and almost never what you want for an icon.

Strokes are centred, which changes your dimensions

SVG strokes straddle the path: half the stroke width falls inside the shape and half outside. A 100-unit square with a 10-unit stroke therefore occupies 110 units, overflowing its own viewBox by 5 units on every side and getting visibly clipped at the edges.

Unlike CSS borders there is no stroke-align property in any shipping browser, so the fix is geometric: inset the shape by half the stroke width. Draw that square from 5,5 to 95,95 rather than 0,0 to 100,100 and the stroked result lands exactly on the intended bounds. For circles, reduce the radius by half the stroke.

Related gotcha: stroke-width scales with the drawing. An icon enlarged from 24 to 96 pixels gets a stroke four times thicker, which is usually right for a single icon and wrong when mixing sizes. vector-effect: non-scaling-stroke keeps the stroke at a constant device width regardless of scale, which is what you want for diagram rules and map outlines.

Path data, fill rules and file size

The d attribute is a compact command language. Uppercase letters take absolute coordinates and lowercase take coordinates relative to the current point, which is why exported paths are usually a wall of lowercase commands — relative values have fewer digits and compress better. M moves without drawing, L draws a line, C and Q draw cubic and quadratic Béziers, A draws an elliptical arc, and Z closes the current subpath.

When a path contains more than one subpath, fill-rule decides which enclosed regions count as inside. The default nonzero counts the winding direction of crossings, so an inner subpath drawn in the same direction as the outer one fills solid. evenodd counts crossings regardless of direction, so alternate regions become holes. A donut or a letter O that renders as a solid blob is nearly always a winding-direction problem, fixable either by reversing the inner subpath or by switching to evenodd.

For file size, coordinate precision is the biggest and easiest win — design tools routinely export six or more decimal places, and for a 24-unit viewBox two is generous. Stripping editor metadata, empty groups and redundant transforms typically halves the bytes with no visual change. Inlining an SVG in your HTML avoids a request and lets CSS restyle it with currentColor, which is what makes icons follow surrounding text colour automatically.

What this generator writes, and why it is small

A wave is one path per layer inside a 1440 × height viewBox with preserveAspectRatio="none", so it stretches to any container width without letterboxing. Each path is sampled from its profile function and fitted with a Catmull-Rom spline converted to cubic Béziers — the curve passes exactly through every sample rather than near it, which is what a chain of quadratics with control points sitting on the samples cannot do.

Sampling density is the file-size lever. Measured against the true sine with getPointAtLength, the fit at ten samples per period deviates by 0.25px on a 60px amplitude; at eight it is 0.53px, and at fourteen it is 0.09px for seventy per cent more bytes. Ten is the setting here, and every coordinate is rounded to two decimals — a 1440-unit grid has no use for the fourteen digits a naive interpolation produces. A two-layer sine divider lands around 1.5 KB.

Amplitude is expressed as a percentage of the wave's own height and the baseline is held at least that far from both edges, so no combination of the sliders can push a crest outside the viewBox and get it clipped. Blobs are fitted the other way round: the outline's true bounding box is solved from the cubic extrema of every segment, then scaled and centred so the shape touches its frame on the long axis. Fitting the control points alone is not enough, because a spline bulges outside its own control polygon — at three points that overshoot runs about ten per cent past the edge.

The CSS tab writes the shape as a data: URI. Attributes are single-quoted so the whole thing survives inside a double-quoted url(), and only the characters that actually break CSS parsing are percent-encoded — <, >, #, % and braces — which keeps it far shorter and far more readable than base64. The wave gets a concrete pixel width there rather than width="100%": a data URI with no intrinsic width falls back to the browser's 300×150 default, and background-size: 100% auto would then render a nine-to-one divider at two-to-one.

SVG shapes FAQ

How do I use an SVG wave as a section divider?

Copy the SVG code and paste it between two sections of your HTML. Set the SVG's fill to match the background colour of the section below it, then position it at the bottom of the section above. Add display: block to remove the small gap browsers add below SVGs.

Can I use the SVG as a CSS background image?

Yes, and the CSS tab writes it for you — no external encoder needed. It emits a ready-to-paste rule with the shape as a data: URI, single-quoted inside url() and percent-encoded only where CSS actually requires it, which is much shorter than base64. The wave version is pinned to a concrete pixel width so background-size gets the right aspect ratio.

What can I drag in the preview?

For a wave, dragging up and down moves the baseline and dragging left and right changes the frequency; the dot on the first crest sets the amplitude, and the scroll wheel does the same. For a blob, every control point on the outline is a handle you can drag anywhere inside the frame, which is how you get a shape no slider combination would give you. Ctrl/+Z undoes any of it.

Are the blobs reproducible?

Yes. Each blob comes from a numbered seed, so typing the same seed with the same Points and Irregularity always gives the same shape, and the arrows step through neighbouring seeds. Sculpting a shape by hand marks it as edited and detaches it from the seed; changing Points, Irregularity or the seed regenerates from scratch.

What are the wave types?

Sine is the plain sinusoid. Asymmetric skews the phase so the swells lean, which reads as more natural for a landscape-style divider. Bumps is a rectified sine — scalloped domes that all sit on one side of the baseline. Zigzag is a triangle wave sampled exactly on its corners so the peaks stay sharp at any frequency.

What size is the exported file?

The byte count is shown next to the output tabs, and it is genuinely small: a two-layer sine divider is around 1.5 KB, a blob around 400 to 700 bytes. Coordinates are rounded to two decimals and waves are sampled at ten points per period, which is the density at which the curve deviates from a true sine by a quarter of a pixel.

What is the viewBox width?

Waves use a 1440 × (height) viewBox with preserveAspectRatio="none", so they stretch to any container width. Blobs use a square viewBox matching the size you set, and the outline is fitted so it touches the frame rather than floating inside a transparent margin. Set width: 100% on the SVG element to make either one responsive.

Why is my stroke clipped at the edge of the shape?

SVG strokes are centred on the path, so half the width sits outside it and overflows the viewBox. Inset the geometry by half the stroke width — draw a stroked square from 5,5 rather than 0,0 for a 10-unit stroke.

Why is my donut shape filling in solid?

The inner subpath winds in the same direction as the outer one, so the default nonzero fill rule treats it as solid. Reverse the inner path's direction or set fill-rule="evenodd".