skip to Main Content

I am trying to make a kind of green wave effect behind a image.
I did this by making a div for the image and another div for the wave element as shown below in my HTML code.
Then I used css to rotate it 45 degrees and animate it so that it goes from the left upper corner to the right lower corner.

Now, the problem is because I rotated the wave div 45 degrees the actual width is shorter if you understand what I mean.
So when the wave gets close to for example the left lower corner you can see that it is not long enough and doesn’t cover the whole screen, this problem gets even worse when the screen ratio is vertical like a phone because the width is even smaller.

body {
  margin: 0;
  height: 100%;
}

#background-image {
  background-image: url("https://www.transparenttextures.com/patterns/black-felt.png");
  height: 100vh;
  background-size: 50vh;
  position: absolute;
  z-index: 2;
  filter: grayscale(100%) brightness(20%);
  right: 0;
  left: 0;
}

#background-neon {
  width: 100%;
  height: 10%;
  overflow: hidden;
  position: absolute;
  z-index: 1;
  transform: rotate(-45deg);
  background-position: bottom left;
  background-color: rgb(0, 150, 0);
  animation: move 4s linear infinite;
}

@keyframes move {
  0% {
    top: -50%;
    left: -50%;
  }
  100% {
    top: 100%;
    left: 25%;
  }
}
<div id="background-neon"></div>
<div id="background-image"></div>

Here’s an example of the code in JSFiddle

I think I will need to use JavaScript or a simple formula in CSS using calc(), but I haven’t found a solution yet.

2

Answers


  1. You can accomplish this effect by using a clip-path and animating that. You’d have to work carefully on your polygon definitions and the transition points but here is a quick example I threw together to illustrate how that would look.

    body, html {
      margin: 0;
      padding: 0;
      height: 100%;
      width: 100%;
    }
    
    .container {
      position: relative;
      height: 100%;
      width: 100%;
    }
    
    .image {
      background-image: url("https://www.transparenttextures.com/patterns/black-felt.png");
      filter: grayscale(100%) brightness(20%);
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
    }
    
    .wave {
      width: 100%;
      height: 100%;
      overflow: hidden;
      background-position: bottom left;
      background-color: rgb(0, 150, 0);
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      
      animation: move 4s linear infinite;
    }
    
    @keyframes move {
      0% {
        clip-path: polygon(10% 0, 17% 0, 0 24%, 0 15%);
      }
    
      49% {
        clip-path: polygon(93% 0, 100% 0, 0 100%, 0 93%);
      }
    
      50% {
        clip-path: polygon(100% 0, 100% 8%, 9% 100%, 0 100%);
      }
    
      100% {
        clip-path: polygon(100% 82%, 100% 90%, 94% 100%, 88% 100%);
      }
    }
    <p>
      Paragraph before 
    </p>
    <div class="container">
      <div class="image"></div>
      <div class="wave"></div>  
    </div>
    <p>
      Paragraph after
    </p>
    Login or Signup to reply.
  2. Answer 1

    Here is a solution that should work for most screen sizes. However, it still needs to be refined for edge cases with the help of media queries.

    body {
      margin: 0;
    }
    
    #effect {
      position: relative;
      background-image: url("https://www.transparenttextures.com/patterns/black-felt.png");
      height: 100vh;
      overflow: hidden;
    }
    
    #effect::before {
      position: absolute;
      content: "";
      width: calc(100vw + 100vh + 10%);
      top: 45%;
      height: 10%;
      z-index: -1;
      background-color: rgb(0, 150, 0);
      rotate: -45deg;
      animation: move 4s linear infinite;
    }
    
    @keyframes move {
      0% {
        left: -200%;
      }
      100% {
        left: 100%;
      }
    }
     <div id="effect"></div>

    Answer 2

    Probably an even better solution which will only break on very large screensizes (fixable with media queries). Here we use a linear gradient instead and set the background-size to 400% 400%. This means that the duration has to be set to 4 * 4s, otherwise the animation would be too fast.

    body {
      margin: 0;
    }
    
    #effect {
      position: relative;
      background-image: url("https://www.transparenttextures.com/patterns/black-felt.png");
      height: 100vh;
    }
    
    #effect::before {
      position: absolute;
      content: "";
      inset: 0;
      z-index: -1;
    
      background: linear-gradient(
        135deg,
        transparent 0%,
        transparent 48%,
        green 48%,
        green 52%,
        transparent 52%
      );
      background-size: 400% 400%;
    
      animation: move 16s linear infinite;
    }
    
    @keyframes move {
      0% {
        background-position: 50% 400%;
      }
      100% {
        background-position: 50% 0%;
      }
    }
    <div id="effect"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search