Search code examples
csssvgcss-animationssvg-animate

How to animate concave rectangle to convex


I have created a rectangle of the following shape using sketch.

enter image description here

When I hover it I need to animate and rest as the below shape.

enter image description here

Is there a way I can animate it using css only from concave to convex.

Any help would be appreciated. I am fine with svg solution as well.

Here is the link to the fiddle for svg.

    <svg width="641px" height="313px" viewBox="0 0 641 313" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <!-- Generator: Sketch 52.5 (67469) - http://www.bohemiancoding.com/sketch -->
    <title>Concave</title>
    <desc>Created with Sketch.</desc>
    <defs>
        <path d="M0,252.683363 C104.477953,274.894454 210.133596,286 316.966929,286 C423.800262,286 531.811286,274.894454 641,252.683363 L641,565 L0,565 L0,252.683363 Z" id="path-1"></path>
    </defs>
    <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
        <g id="iteration-3" transform="translate(-752.000000, -3299.000000)">
            <g id="case--study" transform="translate(0.000000, 2766.000000)">
                <g transform="translate(50.000000, 100.000000)" id="case--study--1-copy">
                    <g transform="translate(702.000000, 181.000000)">
                        <use id="bottom" fill="#000000" fill-rule="nonzero" xlink:href="#path-1"></use>
                    </g>
                </g>
            </g>
        </g>
    </g>
</svg>


Solution

  • For a CSS only solution I would consider a radial-gradient and some background animation:

    .box {
      height:50px;
      width:600px;
      padding-top:50px;
      background:
        /*concave*/
        radial-gradient(410px 50px at 50% 0,transparent, 80%, #000 80.5%) center,
        /*convexe*/
        radial-gradient(410px 50px at 50% 50px,#000, 80%, transparent 80.5%)center,
        linear-gradient(#000,#000) content-box;
      background-size:100% 100%,100% 0px,auto;  
      background-repeat:no-repeat;
      transition:1s all;
    }
    .box:hover {
      background-size:100% 0,100% 100%,auto;
    }
    <div class="box"></div>

    You can also have it for a full width rectangle:

    .box {
      height:50px;
      padding-top:50px;
      background:
        /*concave*/
        radial-gradient(70% 50px at 50% 0,transparent, 80%, #000 80.5%) center,
        /*convexe*/
        radial-gradient(70% 50px at 50% 50px,#000, 80%, transparent 80.5%)center,
        linear-gradient(#000,#000) content-box;
      background-size:100% 100%,100% 0px,auto;  
      background-repeat:no-repeat;
      transition:1s all;
    }
    .box:hover {
      background-size:100% 0,100% 100%,auto;
    }
    <div class="box"></div>

    In case you will have a bigger height or dynamic height better consider a pseudo element so the effect won't get affected by height changing:

    .box {
      height: 80vh;
      position: relative;
      padding-top: 50px;
      background: #000 content-box;
    }
    
    .box::before {
      content: "";
      position: absolute;
      top: 1px;
      left: 0;
      right: 0;
      padding: inherit;
      background: 
       /*concave*/
       radial-gradient(70% 50px at 50% 0, transparent, 80%, #000 80.5%) bottom,      
       /*convexe*/
       radial-gradient(70% 50px at 50% 50px, #000, 80%, transparent 80.5%)bottom;
      background-size: 100% 100%, 100% 0px;
      background-repeat: no-repeat;
      transition: 1s all;
    }
    
    .box:hover::before {
      background-size: 100% 0, 100% 100%;
    }
    <div class="box"></div>

    Update

    You can also adjust the effect like below:

    .box {
      height: 80vh;
      position: relative;
      padding-top: 100px;
      background: #000 content-box;
    }
    
    
    /*concave*/
    .box::before {
      content: "";
      position: absolute;
      top: 50px;
      left: 0;
      right: 0;
      height: 51px;
      background: 
       radial-gradient(70% 50px at 50% 0, transparent, 80%, #000 80.5%) top center;
      background-size: 100% 200%;
      background-repeat: no-repeat;
      transition: 0.5s all 0.4s ease-out;
    }
    
    /*convexe*/
    .box::after {
      content: "";
      position: absolute;
      top: 1px;
      left: 0;
      right: 0;
      height: 51px;
      background:
       radial-gradient(70% 50px at 50% 50px, #000, 80%, transparent 80.5%)bottom center;
      background-size: 200% 0%;
      background-repeat: no-repeat;
      transition: 0.5s all ease-in;
    }
    
    .box:hover::before {
      background-position: bottom center;
      background-size: 200% 200%;
      transition: 0.5s all ease-in;
    }
    
    .box:hover::after {
      background-size: 100% 100%;
      transition: 0.5s all 0.4s ease-out;
    }
    <div class="box"></div>