By · Updated

CSS Wave Generator

Wavy Section Dividers as a Background

No ratings yet

OneTask is free, with no sign-up, and built by one person.
If this tool saved you time, a coffee helps keep new ones coming.

How the CSS Wave Generator works

This CSS wave generator builds a wavy section divider you can paste straight into a stylesheet. A wavy edge between two page sections is one of the most requested decorative effects and one of the most awkward to do by hand. This tool draws the wave as an SVG path, encodes it as a data URI and positions it on the chosen edge of a section, so the whole divider lives in a few lines of CSS.

How the CSS wave generator draws the divider

CSS cannot draw curves as a box edge — border-radius gives you one arc per corner and nothing else. The practical way to get a wavy edge is an SVG shape, and the cleanest way to ship an SVG shape is as a background-image data URI on an absolutely positioned pseudo-element or child. That is what the generated code does: the .wave element sits at the top or bottom of a position: relative section, spans the full width, and paints the wave in the colour of the next section so it looks as if that section is cutting into this one.

How the path is built. The wave is a chain of cubic Bézier curves along a 1440-unit-wide viewBox, one crest and one trough per wave, closed down to the bottom edge to make a filled shape. The preserveAspectRatio='none' attribute lets the browser stretch that viewBox to whatever width and height the element has, so the wave count stays fixed and the curves get wider or narrower with the viewport. That is usually what you want for a divider; if you need waves that keep their shape and repeat instead, set a fixed background-size width and repeat-x.

Top or bottom. A bottom wave sits at the section's lower edge and is painted in the colour of what follows. A top wave is the same path flipped with transform: scaleY(-1) and painted in the colour of what precedes. Either way the section itself needs position: relative so the absolutely positioned wave is placed against it, and usually overflow: hidden or enough padding on that edge so content does not sit under the wave.

Colours. The wave colour must match the neighbouring section's background exactly, including any gradient — a solid wave over a gradient section shows an obvious seam. For gradient sections, put the wave inside the gradient section instead, painted in the neighbour's solid colour.

Why not clip-path? clip-path: path() can cut a wavy edge off the section itself, which avoids the extra element, but it clips the section's content too and the path units are pixels, so it does not scale with the width. The SVG background approach scales cleanly and leaves the content alone. The clip-path generator on this site covers the other approach for polygons and simple shapes.

Accessibility and performance. The wave is purely decorative, so it belongs in CSS rather than in the HTML as an inline <svg>, keeping it out of the accessibility tree. As a background it is rendered once and cached; a data URI of this size adds well under a kilobyte to the stylesheet.

Fine-tuning. The generated path has a fixed crest amplitude of 90% of the half-height. Open the SVG path in the SVG path visualiser to adjust individual control points if you want asymmetric or layered waves, then paste the edited path back into the data URI.

FAQ

Why is there a hairline gap between the wave and the next section?

Sub-pixel rounding at the section boundary. Extend the wave by one pixel — bottom: -1px — or give the wave element a height one pixel taller than the SVG so it overlaps the neighbour and hides the seam.

Can I stack two waves for a layered look?

Yes. Add a second wave element with a different wave count or height and a semi-transparent colour, or generate two rules with different counts and place both at the same edge. The lower-opacity wave in front gives the common "double wave" hero footer.

Why does the wave look squashed on wide screens?

Because preserveAspectRatio='none' stretches the fixed number of waves across the full width. Either increase the wave count, or replace 100% 100% in background-size with a fixed width such as 600px 100% and set background-repeat: repeat-x so the waves tile at a constant size.

Does this work in every browser?

SVG data URIs as backgrounds work in every browser in use today. The only encoding requirement is that <, > and # are percent-encoded and the whole URI is quoted, which the generated code already handles.

Can I animate the wave?

Animate background-position-x on a tiled wave (fixed background-size, repeat-x) to make it drift sideways, which is cheap because the image is cached. Morphing the wave shape itself needs an inline SVG with animated path data rather than a background.

See also: all Shapes & SVG tools, Layout & Spacing, Shadows & Motion, UI Components, Forms & Inputs, Colour.

Related tools