Skip to main content

SVG Wave Generator

Create decorative SVG wave dividers for websites.

Reviewed by · Last reviewed

120px
3
Layers (1/3)
#1
100%
100%
SVG Code
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 120" preserveAspectRatio="none">
  <path d="M0 120 L0 0 C160 84 320 36 480 0 C640 36 800 84 960 0 C1120 84 1280 36 1440 0 L1440 120 Z" fill="#2563eb" fill-opacity="1" />
</svg>

How to Use the SVG Wave Generator

  1. Set wave height - controls the vertical amplitude of the curve, in pixels of the SVG viewBox.
  2. Pick a wave count (number of crests across the width). More crests produce a tighter, higher-frequency wave; fewer crests read as a single broad swell.
  3. Choose a fill color and opacity per layer. Up to three layers let you build a parallax-style depth effect with decreasing opacity on the back layers.
  4. Toggle flip to invert the path so the curve faces top or bottom, which matters when you stack the wave as a divider between sections.
  5. Copy the SVG markup for inline use, copy the CSS background (data URI encoded) for use as a background-image, or click Download SVG for a file asset.

How the Path Is Computed

The generator builds an SVG <path> element using the cubic Bezier command C as defined in the SVG 2 path specification. For a wave with N crests across a 1440-unit viewBox, the path lays down N+1 anchor points at (0,amp), (1440/N, 0), (2*1440/N, amp), and so on, alternating between high and low y positions. Between each pair of anchors the tool emits a cubic segment whose two control points sit at one-third and two-thirds of the horizontal distance, with y values equal to the anchor they flank - this produces the classic sinusoidal "S" with smooth tangent continuity (C1 continuity, in curve-math terms). After the last anchor the path closes downward to the viewBox\'s bottom corner and back to the origin, producing a filled wave band rather than a stroke. When you add a second or third layer, each is the same path primitive with a fresh random phase offset applied to the anchor y values, so the crests do not align visually even though the geometry is identical.

Real-World Uses

  • Marketing page section dividers to soften the transition between the hero and the first content block.
  • Footer mastheads where a wave silhouette against a dark color anchors the bottom of the page.
  • Card top or bottom edges for playful UI components like pricing tables or team bios.
  • Hero backgrounds with multiple overlapping layers at decreasing opacity to imitate ocean depth.
  • Email templates, because an inline SVG is one of the few graphics primitives that render consistently across Gmail, Outlook, and Apple Mail.

Common Gotchas

The most common issue is viewBox vs CSS size mismatch. The SVG is authored in a 1440x150 viewBox, but when rendered via background-image the browser stretches it, distorting the wave if the container aspect ratio differs. Add background-size: 100% auto or use preserveAspectRatio="none" to control the stretch. Second, data URI URL encoding: the background output percent-encodes # as %23 because otherwise browsers parse the hash as a fragment. Third, accessibility: a decorative wave should get aria-hidden="true" and an empty <title> so screen readers skip it - the tool emits markup without these attributes so add them at integration time. Finally, very high wave counts (>12) combined with small heights produce cubic segments that overshoot their anchors due to floating-point rounding.

Why SVG Is the Right Format

SVG 1.1 (W3C Recommendation 2011, now superseded by SVG 2 from 2018) defines an XML-based vector graphics format whose paths are resolution independent and whose file size scales with the number of drawn commands rather than the number of pixels. A wave divider described as one <path d="..."> is typically 200-600 bytes uncompressed, which is roughly 30x smaller than the equivalent 1440x150 PNG export at 1x and catastrophically smaller at 2x or 3x retina. SVG also renders through the GPU path as crisp curves at any zoom level, so the same wave looks sharp on a phone, a 4K display, and at print DPI. The alternative would be a CSS clip-path: polygon(), which also scales but approximates the curve as a high-vertex-count polygon; for smoothness you need 50-100 vertices, which ends up being a larger declaration than the SVG path.

Comparison to Other Wave Tools

Haikei and Shape Divider by ShapeDividerApp cover similar ground with more shape variants (blob fields, bauhaus layers, gradient meshes). Haikei\'s export output is comparable to this tool\'s. Figma plugins like "Waves" generate the same primitive inside the design file but force you to export SVG manually. If you only need a single wave and it will appear on one page, hand-authoring a cubic Bezier path in under 60 seconds with a line like <path d="M0,75 C360,0 1080,150 1440,75 L1440,150 L0,150 Z"/> may be faster than picking a tool, and is what you should do if your design already has tight integration with Tailwind\'s arbitrary-value classes. Reach for generators like this one when you need more than one layer, want to experiment with randomness, or are designing in the browser directly.

Frequently Asked Questions

Why does my wave look jagged at small heights?

At heights below about 40 pixels of viewBox, the cubic Bezier control points end up very close to the anchors, so the tangent is shallow and subtle subpixel rounding on the client shows up as a visible stair-step. The fix is either to increase the height, decrease the wave count (fewer crests at the same amplitude is visually smoother), or render the SVG inline so the browser uses its full path rasterizer instead of the background-image pipeline.

How do I make the wave responsive?

Set the SVG to a 100% width with <code>preserveAspectRatio="none"</code> so it stretches horizontally while keeping its pixel height. For a true fluid feel, drop the fixed height and give the SVG wrapper a viewport-relative height like <code>clamp(60px, 10vw, 150px)</code>. Avoid using it as a background-image at fixed size on tall viewports - the wave will tile or leave gaps.

Can I animate the wave?

Yes, and the cleanest way is to generate two or three frames in the tool with slightly different randomness, put them in a CSS keyframes animation with <code>animation-duration: 8s</code>, and cross-fade between them. For a true flowing wave, use an inline SVG and animate the <code>d</code> attribute via SMIL (<code>&lt;animate&gt;</code>) or Web Animations API with an interpolated path - that is heavier but achieves a continuous ripple.

Why does the CSS-background output have all that %23 garbage?

Because inside a <code>url("data:image/svg+xml,...")</code> value, the hash character is reserved (URLs use it for fragments), the angle brackets can confuse the CSS parser, and the double quote obviously has to be escaped. The tool percent-encodes the minimum set of characters that cause real problems in production browsers - enough for Chrome, Firefox, and Safari to parse the URI without stripping anything.

Is SVG the right format vs PNG?

For any curved or geometric shape, yes. SVG files for a wave divider are typically a few hundred bytes, scale crisply to any size, and let you change the color via CSS variables if you inline them. PNGs of the same wave are kilobytes at 1x and tens of kilobytes at 3x retina and cannot be restyled. The exception is complex raster textures (photo-realistic water surfaces) where PNG or WebP at a known pixel size wins.

How many layers should I use?

One layer is clean and usually correct. Two layers at 100% and 60% opacity give a gentle parallax suggestion. Three layers is the tool's maximum and reads as "full ocean illustration" - beautiful on a hero, overkill on a section divider. Avoid four-plus because the combined file size grows and the visual story becomes muddy.

Will the wave render in email clients?

Inline SVG renders in Apple Mail, Thunderbird, and recent Outlook on the web; it fails in Outlook on Windows (Word's renderer) and the Gmail classic mobile app. For email, render the wave to a PNG at 2x target size, or accept that a small population will see a missing image.

Can I change the color after pasting?

Yes, if you use the inline SVG output: replace the hardcoded fill hex with a CSS custom property via <code>fill="currentColor"</code> plus a <code>color: var(--wave-fill)</code> on the wrapper, and the wave restyles with the rest of your theme. The CSS-background output bakes the color into the data URI, so to restyle it you have to regenerate or hand-edit the encoded string.

What is the SVG viewBox and why does it matter?

The viewBox is the internal coordinate system the path is drawn in - 1440 units wide by 150 units tall in this tool's output. The CSS width and height of the rendered element then map onto that space through the preserveAspectRatio rule. Understanding this decouples design-time coordinates from deployment-time pixel sizes, which is why the same SVG looks identical on a phone and a 4K display.

Does the tool send my settings to a server?

No. Every slider drives local state in a Preact component; the path string is rebuilt in-memory on each change and written to the DOM's SVG element. The copy and download buttons use the Clipboard API and a programmatic anchor download respectively. Nothing touches a remote endpoint, nothing is analytics-tagged with your color choices.

More CSS & Design