Search code examples
cssbordercss-shapes

Wave border in CSS


I know what you're thinking, there's at least a million questions like this, asking about waves in borders, or waves at the edges of elements. However, I have a different question. What I need is a combination between a zigzag-edge (I have no idea how to call it, I'm not English) and a wave-edge.

More specific: I need to create this:

enter image description here

The top part of the blue element has to be a wavy kind of border, where the top part is transparent so the underlying image shows 'through the element', so to say.

Is this do-able with CSS? I'd rather not use images, simply because there will be multiple elements like these, with different colours (that means different edge colours per element).


Solution

  • It's relatively easy to draw a border like that with a couple of pseudo-elements.

    First we draw the bottom of the wave:

    .wave{
      background:
        linear-gradient(to right, sandybrown, chocolate);
      height: 50px;
      position: relative;
    }
    .wave::before{
      content: "";
      position: absolute;
      left: 0;
      bottom: 0;
      right: 0;
      background-repeat: repeat;
      height: 10px;
      background-size: 20px 20px;
      background-image:
        radial-gradient(circle at 10px -5px, transparent 12px, maroon 13px);
    }
    <div class='wave'></div>

    We then fill every other ditch with the background of another pseudo-element. This background is twice as wide so we only fill the odd ditches.

    .wave{
      background:
        linear-gradient(to right, sandybrown, chocolate);
      height: 50px;
      position: relative;
    }
    .wave::after{
      content: "";
      position: absolute;
      left: 0;
      bottom: 0;
      right: 0;
      background-repeat: repeat;
      height: 15px;
      background-size: 40px 20px;
      background-image:
        radial-gradient(circle at 10px 15px, crimson 12px, transparent 13px);
    }
    <div class='wave'></div>

    Combining the two gives us the desired effect:

    .wave{
      background:
        linear-gradient(to right, sandybrown, chocolate);
      height: 50px;
      position: relative;
    }
    .wave::before{
      content: "";
      position: absolute;
      left: 0;
      bottom: 0;
      right: 0;
      background-repeat: repeat;
      height: 10px;
      background-size: 20px 20px;
      background-image:
        radial-gradient(circle at 10px -5px, transparent 12px, aquamarine 13px);
    }
    .wave::after{
      content: "";
      position: absolute;
      left: 0;
      bottom: 0;
      right: 0;
      background-repeat: repeat;
      height: 15px;
      background-size: 40px 20px;
      background-image:
        radial-gradient(circle at 10px 15px, aquamarine 12px, transparent 13px);
    }
    <div class='wave'></div>


    Updated with a flatter wave.

    .wave{
      background:
        linear-gradient(to right, sandybrown, chocolate);
      height: 50px;
      position: relative;  
    }
    .wave::before, .wave::after{
      border-bottom: 5px solid yellow;
    }
    .wave::before{
      content: "";
      position: absolute;
      left: 0;
      right: 0;
      bottom: 0;
      height: 10px;
      background-size: 20px 40px;
      background-image:
        radial-gradient(circle at 10px -15px, transparent 20px, yellow 21px);
    }
    .wave::after{
      content: "";
      position: absolute;
      left: 0;
      right: 0;
      bottom: 0;
      height: 15px;
      background-size: 40px 40px;
      background-image:
        radial-gradient(circle at 10px 26px, yellow 20px, transparent 21px);
    }
    <div class='wave'></div>