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.
SVG wave generator
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.
<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
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
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
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
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
The same curve comes out in every format, with the fill and the layer stack already applied.
The wave as a standalone file with its viewBox intact, for an img tag, an asset pipeline or a design tool.
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.
The whole wave encoded as a data URI inside a background-image rule, with background-size and position already set. No extra request.
A raster copy at 512, 1024 or 2048 pixels wide for slides, documents and anywhere an SVG will not go.
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.
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
Build the curve, match it to the section it meets, and take the format that fits how your page is built.
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.
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.
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.
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
Each link opens the generator with the curve, height and fill already set.
A mid amplitude across five points at the default height. The everyday divider between a hero and the section under it.
Eight points at low amplitude with three stacked layers and a lime-to-sky gradient running left to right.
Four points at high amplitude, flipped so the fill sits above the curve, at 240 units tall. For closing a dark section.
Ten points at moderate amplitude across the full 480-unit height, with a warm gradient top to bottom and two layers.
In depth
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.
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 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.
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
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.
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.
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.
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.
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
Set the points and the amplitude, match the fill to the section it meets, and paste the markup or the background rule.