Sitemap

How to make wave backgrounds in CSS

4 min readNov 4, 2022

--

I wanted to have some waves in the background of my content, like this:

Press enter or click to view image in full size

This was the SVG that the designer handed to me (if you don’t have a wave SVG, you can generate one at https://getwaves.io/):

Press enter or click to view image in full size

I thought it should be easy to implement and was surprised by the problems I would face. As it turned out, the given SVG background was leading me in the wrong direction.

Why using background-image is a bad idea for waves:

My first idea was to put the SVG wave as a background for a div container that contains the content, like this:

<div class="gradient-wave-bg">
<h1>Projekte</h1>
....
</div>

There is a tool https://yoksel.github.io/url-encoder/ which allows you to quickly convert an SVG to the required CSS background-image property.

Basically, I had to remove height from SVG, set width to 100%, and then make a CSS class like this:

.gradient-wave-bg{
padding:100px;
background-size:100%;
background-repeat: no-repeat;
background-image: url("data:image/svg+xml,%3Csvg width='100%' viewBox='0 0 1600 1262' ........");
}

But as I had dynamic content, I run into two major issues. For some content, the wave would not display at full height, showing a sudden end without gradient/opacity dissolving:

Press enter or click to view image in full size

This could be solved by setting a min-height to the container, but it would create a large gap when a user had not enough content.

Another problem was, in case of large content, the wave was not recognized any longer:

Press enter or click to view image in full size

In short, I was presented with those two issues:

Press enter or click to view image in full size

If you don’t have dynamic content, and the SVG background works for desktop and mobile views, then this solution is good. But I had to look for something different.

Alternative: Split SVG wave into gradient and wave

The idea for this solution is to only use the SVG for the top wave, but use a CSS gradient for the content.

Press enter or click to view image in full size

In my example, I had to reduce the SVG only to the top part. This can be done by simply changing the height of the SVG viewbox:

Press enter or click to view image in full size

Next, I took the bottom color of the SVG box and created a CSS gradient using this tool: https://cssgradient.io/

The HTML was like this:

<div>
<svg ....>
<div class="my-gradient">
My content
</div>
</div>

But this is not working well, as the content is not overlaying the wave

Press enter or click to view image in full size

To fix this, we could add a negative margin to the “my-gradient” box, but of course, this would break the gradient design, as it would also start higher:

Press enter or click to view image in full size

The trick is, to let the gradient start after X pixels, where X the negative margin that you have to move up.

In principle, that is the solution to the problem, where the content is moved up 350px:

<style>
.my-gradient{
background: linear-gradient(0deg, rgba(255,255,255,1) 0%, rgba(254,226,226,0.8) 25%, rgba(254,226,226,1) calc(100% - 350px),rgba(255,255,255, 0) calc(100% - 349px), rgba(255,255,255,0) 100%);
margin-top:-350px;
}
</style>

This will now work:

Press enter or click to view image in full size

Of course, the height of the SVG depends on the width and thus varies on the screen size (in the case of full width). This can be handled by adjusting negative margins (and the implicit gradient offset) with media queries.

Remark: This presented article only works if your SVG gradient is straight vertically or horizontally. If your gradient is inclined (for example 40 degree), you can use the same approach, but calculating the correct css-gradient is complex and depending on the screen-size. For this, its perhaps better to go with the first proposed solution, to use the SVG as background with the mentioned downsited. Otherwise, you could also use Inkscope to make the gradient straight. If these are no options, you can do it with math and JS, but its really complicated, see https://stackoverflow.com/questions/74251937/how-to-continue-gradient-from-svg-with-css/74256001#74256001

--

--

Dr. Adam Nielsen
Dr. Adam Nielsen

Written by Dr. Adam Nielsen

PHD in math. and Laravel / Vue Full-Stack-Developer