Search code examples
htmlcsssvgcss-animationscss-mask

Masking a div with an image and animating gradient background


I am currently designing a logo that has an animated gradient background.

Requirements:

  • The mask image must be either jpg or png
  • The element being masked should preferably be a <div>
  • The gradient should be CSS and preferably come from the <div> background

The mask should look something like this:

enter image description here

i have the CSS animations down, but when it comes to cutting a shape out of a <div> with an jpg or png image i seem to be stuck.

What i came up with:

I do not like my current solutions because it relies on SVG animations and im masking a SVG <rect> element not a <div>. It is much less flexible then if it was achieved mainly using CSS. But, it gets the job done.

<!-- image masked gradient -->
<svg  height="200px" width="200px">  
    <defs>  
        <!-- the gradient for the rectangle element-->
        <linearGradient id='gradient1'>
            <stop stop-color='#020024'/>
            <stop offset='.35' stop-color='#090979'/>
            <stop offset='1' stop-color='#6699ff'/>
            </linearGradient>

        <!-- the mask shape of a thunder bolt -->
        <mask id="image-mask" x="0" y="0" width="100" height="100" >  
            <image href="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcRU8cEP-xBjtmZ2ZhpNKMc0dwE7I5a-PB8RBA&usqp=CAU" height="200" width="200"/>
        </mask>  
    </defs>

    <!-- this is the gradient rectangle element to be masked -->
    <g mask="url(#image-mask)">  
        <rect class="posr " x="10" y="0"  width="500%" height="400%" fill="url(#gradient1)">
           <animate attributeName="x" values='0px;-450px;0px' dur="5s"  repeatCount="indefinite" />
        </rect>
    </g>  
</svg>

So i basically want the effect showed in the snippet but mainly with CSS animations and the image mask!


Solution

  • You can use CSS mask but you need to fîrst create a PNG image like below:

    enter image description here

    Then use it like below:

    .box {
      display:inline-block;
      width:300px;
      -webkit-mask:url(https://i.ibb.co/m9fR6H1/aLOO0.png) center/cover;
              mask:url(https://i.ibb.co/m9fR6H1/aLOO0.png) center/cover;
      background:linear-gradient(to right,red,blue,green) left/300% 100% no-repeat;
      animation:change 2s linear infinite alternate;
    }
    
    /* maintain the square ratio */
    .box::before {
      content:"";
      display:block;
      padding-top:100%;
    }
    /**/
    
    
    @keyframes change {
      to {
        background-position:right;
      }
    }
    
    body {
      background:#f2f2f2;
    }
    <div class="box"></div>
    <div class="box" style="width:150px;"></div>

    The quality of the image I am using is very bad. I only focusing on the trick rather than the quality.