SVG wave generator

Section dividers with a soft edge.

A horizontal wave drawn across a 1440-unit canvas at one of four heights. Set how many points the curve passes through, how far it travels, and how many layers stack behind it, then take the SVG, the markup, a CSS background or a PNG.

Seed 82 · 1440×320 · 5 points
Height
Units on a 1440 wide canvas
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 320" preserveAspectRatio="none" width="100%"><path d="M0,156.1Q360,82,540,153.8Q720,225.5,900,225.3Q1080,225.1,1260,181.5T1440,137.8L1440,320L0,320Z" fill="#1e8fe5"/></svg>

Overview

One curve, the width of the page.

The canvas is 1440 units wide and 160, 240, 320 or 480 units tall. Points places between 3 and 12 control positions evenly across that width, Amplitude from 1 to 9 decides how far each one may rise or fall, and the seed behind Shuffle picks which way they go. The curve is closed along the bottom edge so the shape fills as a solid band rather than a stroke.

Flip turns the whole thing over: the curve sits at the bottom of the box and the fill sits above it, which is what you need when the divider belongs to the section above rather than the one below. Layers stacks one, two or three copies of the curve at decreasing opacity, each offset slightly, so the edge reads as depth instead of a single hard line.

Design

Two numbers, every shape

Points controls rhythm and Amplitude controls drama. Three points at high amplitude gives one long swell; ten points at low amplitude gives a ripple.

Code

A band, not a line

The path closes along the bottom of the viewBox, so the export is a filled shape ready to sit flush against the section beneath it.

Layout

Built to stretch

The 1440-unit grid is a ratio, not a pixel size. Set preserveAspectRatio to none and the wave spans any viewport at the height you choose.

Export

Four files and two ways to paste.

The same curve comes out in every format, with the fill and the layer stack already applied.

SVG file

The wave as a standalone file with its viewBox intact, for an img tag, an asset pipeline or a design tool.

SVG markup

The svg element ready to paste inline, so the fill can be set from a CSS custom property and matched to the section it meets.

CSS background image

The whole wave encoded as a data URI inside a background-image rule, with background-size and position already set. No extra request.

PNG

A raster copy at 512, 1024 or 2048 pixels wide for slides, documents and anywhere an SVG will not go.

A link that rebuilds it

Points, amplitude, seed, height, flip, layers and the fill all travel in the query string as pts, amp, se, h, fl, ly and c or g with ga.

Solid or gradient fill

One color, or two stops with a direction in CSS degrees. The gradient is written into the SVG as a linearGradient, not flattened.

How it works

Four steps to a divider.

Build the curve, match it to the section it meets, and take the format that fits how your page is built.

  1. 01

    Set the rhythm

    Choose Points between 3 and 12. Three to five reads as a gentle swell across a wide screen; eight or more reads as a ripple and needs less amplitude to stay calm.

  2. 02

    Set the travel

    Amplitude runs from 1 to 9 and decides how far the curve may leave the middle of the box. Shuffle rerolls the direction of each point without changing the count.

  3. 03

    Aim it at a section

    Pick a height of 160, 240, 320 or 480, flip it if the wave belongs to the section above, and set the fill to the color of the section it is pointing into.

  4. 04

    Export

    Take the inline markup if the fill has to follow your theme, or the CSS background image if the divider is decoration and you would rather keep the markup clean.

Examples

Four dividers to start from.

Each link opens the generator with the curve, height and fill already set.

In depth

What a wave divider has to get right.

The job a divider does

A section divider marks where one band of a page ends and the next begins. A straight border does that in one pixel; a wave does it with a shape, which reads as a deliberate transition rather than a rule. The important detail is that the divider belongs to a boundary between two colors, so it has exactly one job: carry the color of one section into the other.

That is why the fill matters more than the curve. Set the wave's fill to the background color of the section it points into and the divider disappears into the layout, leaving only the curved edge. Set it to a third color and you have added a stripe, which is a different design decision and usually an accident. The generator keeps the fill on the same panel as the shape controls for exactly this reason: they are not independent choices.

Points and Amplitude set the character. Three to five points across 1440 units gives one long swell that reads at any screen size. Ten or twelve gives a ripple, effective at 160 units tall and noisy at 480. Amplitude should come down as the point count goes up, because the peaks crowd together and the eye reads steepness rather than height.

Stretching the curve across any width

The 1440-unit grid is a ratio, not a measurement. An SVG normally preserves that ratio, letterboxing itself inside a wider container, which for a divider is wrong: you want the wave to span the full viewport whatever its width, and you want the height to stay exactly what you set. That is what preserveAspectRatio="none" does. It tells the browser to scale the x and y axes independently to fill the box, so a 1440 by 240 wave stretched across a 2560-pixel screen stays 240 pixels tall and simply gets wider.

The distortion that comes with it is the point rather than a defect. A wave stretched horizontally flattens on a wide monitor and steepens on a phone, which is close to what you would draw by hand for each. It only matters if the shape carries detail that has to keep its proportions, which a wave does not.

Inline markup and a CSS background behave differently here. Inline, the svg element takes width: 100% and the height you chose, and preserveAspectRatio does the work. As a background image the equivalent is background-size: 100% 100%, which stretches the image to the box in the same way; cover would crop it instead. The export sets these for you.

Layers, flipping and placement

Layers draws the same curve two or three times, each copy offset and set at a lower opacity than the one in front. The effect is a soft band of related edges instead of one hard line, which suits a large hero and reads as depth. Keep the layer count at one when the divider is short: at 160 units the copies overlap too closely to separate, and the only result is a muddier color. Because every layer shares the same fill, a gradient stays consistent across the stack.

Flip decides which side of the curve is solid. Unflipped, the curve runs along the top of the box and the fill hangs below it, so the divider reaches down into the section beneath. Flipped, the curve sits at the bottom and the fill rises above it, which is what you want when the wave closes the section above. Getting this wrong is the most common mistake with dividers, and the giveaway is a thin strip of the wrong color between the wave and the content.

Placement is the last piece. A divider is usually an element at the end of one section or the start of the next, with the two flush against each other. A small negative margin on the side that meets the content closes any subpixel gap at fractional zoom levels: about -1px is enough. Set display: block on the svg as well, since an inline element picks up a few pixels of line-height underneath it and produces the same stripe you were avoiding.

Size and performance

A wave is a handful of numbers, so the file is small: a single path with three to twelve curve commands, a viewBox and a fill, usually well under a kilobyte before compression. Layers multiply that by two or three and a gradient adds a defs block, and the result is still smaller than any image of the same divider. Choosing more points costs a few bytes each, so the shape you like is almost always the shape you can afford.

The choice between inline markup and a CSS background is about control rather than weight. Inline, the fill can come from a custom property and follow a dark theme, and the path can be targeted from CSS. As a background image the markup stays clean, but the fill is baked into the data URI, so a theme switch means a second rule. For one light palette the background route is simpler; for anything themed, paste the markup.

Either way the divider is decoration, so keep it out of the accessibility tree: aria-hidden on inline SVG, an empty alt on an img, nothing at all for a background image. And avoid animating the path itself. If a divider has to move, translate the whole element slowly instead, which the browser can composite rather than repaint.

Questions

Divider questions, answered.

Why is the canvas 1440 units wide?

It matches the width most designs are laid out at, which makes the numbers easy to reason about, and it is only a ratio. With preserveAspectRatio set to none the same path stretches to any viewport width while the height stays at the 160, 240, 320 or 480 you picked.

Should I paste the markup or use the CSS background?

Paste the markup when the fill has to follow a theme or a custom property, because the path stays targetable from CSS. Use the CSS background image when the divider is fixed decoration and you would rather keep the markup clean; the fill is baked into the data URI, so a second theme needs a second rule.

There is a thin line between my wave and the next section.

That is a subpixel gap from fractional scaling. Set display: block on the svg element so it does not sit on a text baseline, and give it about -1px of margin on the side that meets the content.

When should I flip the wave?

Flip it when the divider belongs to the section above. Unflipped, the curve runs along the top and the fill hangs below, reaching into the section beneath. Flipped, the curve sits at the bottom and the fill rises above it.

How many layers is too many?

Three is the maximum and it suits a tall divider at 320 or 480 units. At 160 units the copies overlap so closely that they read as one muddier color, so keep short dividers on a single layer.

Get started

End a section with a curve.

Set the points and the amplitude, match the fill to the section it meets, and paste the markup or the background rule.