Home > Web Front-end > CSS Tutorial > How to Create Wavy Shapes & Patterns in CSS

How to Create Wavy Shapes & Patterns in CSS

Christopher Nolan
Release: 2025-03-10 09:41:10
Original
739 people have browsed it

How to Create Wavy Shapes & Patterns in CSS

Creating wave shapes in CSS can be a challenge. We often try to simulate wave effects using border-radius attributes and a large number of approximations, but this can become more complex when dealing with wave patterns.

While SVG is a more efficient way to create wave shapes, CSS can also achieve good results, and the code does not have to be too complicated. Even better, I provide an online generator to simplify the process!

Using the generator, you can see that the generated CSS code contains only two gradients and one CSS mask property - that's all, and you can create various wave shapes and patterns. In addition, we can easily control the size and curvature of the wave.

Some values ​​may look like "magic numbers", but there is actually a logical basis behind them. We will dissect the code and uncover all the secrets of creating waves.

This article is a follow-up to a previous article about creating various zigzag, range-limited, scalloped, and wavy borders. I highly recommend reading that article because it uses the same technique described here, but in more detail.

The mathematical principle behind waves

Strictly speaking, there is no magical formula to create wave shapes. Any shape with an upper and lower curve can be called a wave, so we do not limit ourselves to complex mathematical calculations. Instead, we will use geometric basis to reproduce the waves.

Let's start with a simple example using two circular shapes:

We have two circles with the same radius adjacent to each other. Have you seen that red line? It covers the upper half of the first round and the lower half of the second round. Now imagine you take that line and repeat it.

We have seen the waves. Now let's fill the bottom (or top) section to get the following results:

Look! We get a wave shape and we can use a variable to control the radius of the circle. This is one of the easiest waves we can create and the one I showed in my previous post.

Let's add some complexity by taking the first legend and moving the circle a little:

We still have two circles with the same radius, but they are no longer aligned horizontally. In this case, the red line no longer covers half of the area of ​​each circle, but a smaller area. This area is limited by the dotted red line. The line passes through the point where two circles meet.

Now take that line and repeat it and you will get another wave, a smoother one.

I think you understand. By controlling the position and size of the circle, we can create any wave we want. We can even create variables for them, which I will call P and S respectively.

You may have noticed that in the online generator, we use two inputs to control the waves. They are mapped to the variables mentioned above. S is the "size of the wave" and P is the "curvature of the wave".

I define P as P = m*S, where m is the variable you adjust when updating the curvature of the wave. This allows us to always maintain the same curvature, even if we update S.

m can be any value between 0 and 2. 0 will give our first special case where two circles are aligned horizontally. 2 is a maximum value. We can be bigger, but after some testing, I found that any value greater than 2 will produce a bad flat shape.

Let us not forget the radius of our circular shape! This can also be defined using S and P, as shown below:

<code>R = sqrt(P² + S²)/2
R = sqrt(m²*S² + S²)/2
R = S*sqrt(m² + 1)/2</code>
Copy after login
Copy after login

When m is equal to 0 (i.e. P is equal to 0), we will have R = S/2.

We have everything we need to convert all of this into gradients in CSS!

Create gradient

Our waves use circles, and when it comes to circles, we are talking about radial gradients. Since the two circles define our waves, we will use two radial gradients logically.

We will start with a special case where P is equal to 0. This is the first gradient illustration:

This gradient creates the first curvature while filling the entire bottom area – arguably the "water" of the waves.

<code>.wave {
  --size: 50px;

  mask: radial-gradient(var(--size) at 50% 0%, #0000 99%, red 101%) 
    50% var(--size)/calc(4 * var(--size)) 100% repeat-x;
}</code>
Copy after login
Copy after login

--size variables define the radius and size of the radial gradient. If we compare it with the S variable, it equals S/2.

Let's add the second gradient now:

The second gradient is just a circle to complete our waves:

<code>radial-gradient(var(--size) at 50% var(--size), blue 99%, #0000 101%) 
  calc(50% - 2*var(--size)) 0/calc(4 * var(--size)) 100%</code>
Copy after login
Copy after login

If you look at the previous post, you will find that I'm just repeating what I've done there.

I read two articles, but the gradient configuration is not the same.

This is because we can use different gradient configurations to achieve the same result. If you compare the two configurations, you will notice a slightly different alignment, but the trick is the same. If you are not familiar with gradients, this can be confusing, but don't worry. With some exercises, you will get used to them and you will find that different syntaxes can produce the same results.

This is the complete code for our first wave:

<code>.wave {
  --size: 50px;

  mask:
    radial-gradient(var(--size) at 50% var(--size),#000 99%, #0000 101%) 
      calc(50% - 2*var(--size)) 0/calc(4 * var(--size)) 100%,
    radial-gradient(var(--size) at 50% 0px, #0000 99%, #000 101%) 
      50% var(--size)/calc(4 * var(--size)) 100% repeat-x;
}</code>
Copy after login
Copy after login

Now let's take this code and adjust it so that we introduce a variable that can be used completely to create any wave we want. As we saw in the previous section, the main trick is to move the circles so that they are no longer aligned, so let's update the position of each circle. We move the first one up and the second one down.

Our code will look like this:

<code>.wave {
  --size: 50px;
  --p: 25px;

  mask:
    radial-gradient(var(--size) at 50% calc(var(--size) + var(--p)), #000 99%, #0000 101%) 
      calc(50% - 2*var(--size)) 0/calc(4 * var(--size)) 100%,
    radial-gradient(var(--size) at 50% calc(-1*var(--p)), #0000 99%, #000 101%) 
      50% var(--size) / calc(4 * var(--size)) 100% repeat-x;
}</code>
Copy after login
Copy after login

I introduced a new --p variable to define the center position of each circle. The first gradient uses 50% calc(-1*var(--p)), so its center moves upwards, while the second gradient uses calc(var(--size) var(--p)) to move it downwards.

The demonstration is better than a thousand words:

The circles are neither aligned nor touch each other. We separated them far without changing the radius, so we lost the waves. But we can fix these problems by calculating the new radius using the same mathematical method used earlier. Remember R = sqrt(P² S²)/2. In our case, --size is equal to S/2; so is --p because it is also equal to P/2 because we are moving two circles. Therefore, the distance between their center points is twice as high as --p:

<code>R = sqrt(P² + S²)/2
R = sqrt(m²*S² + S²)/2
R = S*sqrt(m² + 1)/2</code>
Copy after login
Copy after login

This gives us a result of 55.9px.

Our waves are back! Let's insert the equation into our CSS:

<code>.wave {
  --size: 50px;

  mask: radial-gradient(var(--size) at 50% 0%, #0000 99%, red 101%) 
    50% var(--size)/calc(4 * var(--size)) 100% repeat-x;
}</code>
Copy after login
Copy after login

The above CSS looks valid, but it won't work because we can't multiply two lengths, so we have to introduce an m variable to control the curvature, as described in the previous section.

<code>radial-gradient(var(--size) at 50% var(--size), blue 99%, #0000 101%) 
  calc(50% - 2*var(--size)) 0/calc(4 * var(--size)) 100%</code>
Copy after login
Copy after login

This is very cool: just two gradients are needed to get a cool wave that you can apply to any element using the mask attribute. No need to try and do it – you just need to update two variables!

Reverse wave

What if we want the waves to move in the other direction, we fill the "sky" instead of the "water"? Believe it or not, we only need to update two values:

<code>.wave {
  --size: 50px;

  mask:
    radial-gradient(var(--size) at 50% var(--size),#000 99%, #0000 101%) 
      calc(50% - 2*var(--size)) 0/calc(4 * var(--size)) 100%,
    radial-gradient(var(--size) at 50% 0px, #0000 99%, #000 101%) 
      50% var(--size)/calc(4 * var(--size)) 100% repeat-x;
}</code>
Copy after login
Copy after login

All I did was add an offset equal to 100%, as shown above. The results are as follows:

We might consider using a more keyword value-friendly syntax to make it easier:

<code>.wave {
  --size: 50px;
  --p: 25px;

  mask:
    radial-gradient(var(--size) at 50% calc(var(--size) + var(--p)), #000 99%, #0000 101%) 
      calc(50% - 2*var(--size)) 0/calc(4 * var(--size)) 100%,
    radial-gradient(var(--size) at 50% calc(-1*var(--p)), #0000 99%, #000 101%) 
      50% var(--size) / calc(4 * var(--size)) 100% repeat-x;
}</code>
Copy after login
Copy after login

We use the left and bottom keywords to specify edges and offsets. By default, browsers default to left and top - which is why we use 100% to move elements to the bottom. We actually moved it 100% from the top, so it's actually the same as saying the bottom. Easier to read than math!

Using this updated syntax, we simply replace bottom with top—and vice versa—to change the direction of the wave.

If you want to get both the top and bottom waves, we combine all the gradients in one statement:

<code>R = sqrt(var(--size) * var(--size) + var(--p) * var(--p))</code>
Copy after login

If you check the code, you will see that in addition to combining all the gradients, I also reduced its height from 100% to 51% so that they all cover half of the element. Yes, 51%. We need an extra little percentage to do small overlaps to avoid gaps.

What about the left and right sides?

This is your homework! Take advantage of what we did at the top and bottom and try to update the values ​​to get the values ​​on the right and left. Don't worry, it's easy, the only thing you need to do is swap values.

If you have problems, you can always use the online generator to check the code and visualize the results.

...(The remaining content is similar to the original text, except that the language and expression are adjusted, and the pictures and code blocks are retained)

The above is the detailed content of How to Create Wavy Shapes & Patterns in CSS. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template