skip to Main Content

I have designed front fascia of a car in CSS, and I would like to animate it from bottom to top, with charge filling in. How can I achieve that?
I am able to fill the bottom section of the car with it, but I want to do it for the whole car.
Any sort of suggestion/help will be highly appreciated. Please find the code for the same below,

.car-top {
    position: relative;
    border-bottom: 150px solid #555;
    border-left: 50px solid transparent;
    border-right: 50px solid transparent;
    border-top-left-radius: 100px;
    border-top-right-radius: 100px;
    height: 0;
    width: 350px;
}

.car-bottom {
    position: relative;
    width: 450px;
    height: 80px;
    background: #555;
}

.car-bottom:before {
    content: "";
    position: absolute;
    background: #04ACFF;
    width: 100%;
    bottom: 0;
    animation: wipe 2s cubic-bezier(.2,.6,.8,.4) forwards;
}

.tires:before, .tires:after {
    content: "";
    position: absolute;
    width: 60px;
    height: 50px;
    top: 80px;
    background: #555;
    border-bottom-left-radius: 20px;
    border-bottom-right-radius: 20px;   
}

.tires:before {
    left: 0;
}

.tires:after {
    right: 0;
}

@keyframes wipe {
  0% {
    height: 0;
  }
  100% {
    height: 100%;
  }
}
<div class="parent">
    <div class="car-top"></div>
    <div class="car-bottom">
        <div class="tires"></div>
    </div>
</div>

3

Answers


  1. have you tried using the same wipe animation to car top with an animation delay?

    Login or Signup to reply.
  2. SVG clip path works best for this. (I just borrowed the SVG from Font Awesome; you can change it as you like.)

    #svg {
      width: 0;
      height: 0;
    }
    
    .car {
      width: 200px;
      height: 200px;
      background: #555;
      clip-path: url(#car);
    }
    
    .car::before {
      content: '';
      display: block;
      width: 100%;
      height: 100%;
      background: #04ACFF;
      transform-origin: bottom;
      animation: wipe 2s cubic-bezier(.2, .6, .8, .4) forwards;
    }
    
    @keyframes wipe {
      0% {
        transform: scale(1, 0);
      }
      100% {
        transform: scale(1, 1);
      }
    }
    <svg id="svg" xmlns="http://www.w3.org/2000/svg">
      <!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.-->
      <clipPath id="car" clipPathUnits="objectBoundingBox" transform="scale(0.001953125, 0.001953125)">
        <path d="M135.2 117.4L109.1 192H402.9l-26.1-74.6C372.3 104.6 360.2 96 346.6 96H165.4c-13.6 0-25.7 8.6-30.2 21.4zM39.6 196.8L74.8 96.3C88.3 57.8 124.6 32 165.4 32H346.6c40.8 0 77.1 25.8 90.6 64.3l35.2 100.5c23.2 9.6 39.6 32.5 39.6 59.2V400v48c0 17.7-14.3 32-32 32H448c-17.7 0-32-14.3-32-32V400H96v48c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32V400 256c0-26.7 16.4-49.6 39.6-59.2zM128 288a32 32 0 1 0 -64 0 32 32 0 1 0 64 0zm288 32a32 32 0 1 0 0-64 32 32 0 1 0 0 64z"></path>
      </clipPath>
    </svg>
    
    <div class="car"></div>
    Login or Signup to reply.
  3. My own approach would be to avoid the artistry of HTML and CSS, and instead use an SVG along with the CSS image-mask property, as follows:

    /* defining the animation, with the @keyframes property: */
    @keyframes fill {
      /* the initial state is the current state of the element,
         so we only have to animate to that final state: */
      to {
        background-position: 50% 100%;
      }
    }
    
    html {
      block-size: 100%;
    }
    
    body {
      background: linear-gradient(0deg, hsl(120deg 40% 5% / 1), hsl(120deg 80% 5%));
      block-size: 100vb;
      padding: 1rem;
    }
    
    main {
      block-size: 100%;
      /* using grid layout for the ease of centering the content in
         the page: */
      display: grid;
      place-content: center;
    }
    
    /* 
      Attribution, this SVG is currently hosted on my own site but was originally sourced from:
        https://svgsilh.com/image/2736805.html
      and released under CC0 license (see: https://creativecommons.org/publicdomain/zero/1.0/deed.en)
    */
    .car {
      /* the color to show when the 'car' is filled: */
      --filled: hsl(240deg 100% 60% / 1);
      /* the color to show when the 'car' is not yet filled: */
      --unfilled: black;
      /* shorthand for:
        animation-name: fill;
        animation-duration: 10s;
        animation-timing-function: cubic-bezier(...);
        animation-fill-mode: forwards;
      */
      animation: fill 10s cubic-bezier(0.2, 0.6, 0.8, 0.4) forwards;
      /* sizing the element, so that its inline-axis is 1.6 times the (defined)
         block-size of the element: */
      aspect-ratio: 1.6;
      /*
        shorthand for:
          background-image: linear-gradient(...);
          background-position: 50% 0;
          background-size: 100% 200%;
          background-repeat: no-repeat;
        this allows us to position the linear-gradient 50% on the horizontal axis, and zero
        on the vertical axis (so far, I don't think that logical properties are available to
        background-position unfortunately), and specify the background-image to be 100% of
        the width of the element, and 200% of the vertical height of the parent element:
      */
      background: linear-gradient(180deg, var(--unfilled) 0 50%, var(--filled) 50%) 50% 0 / 100% 200% no-repeat;
      /* defining the block-size to be 60 viewport-block units, right-to-left/top-to-bottom languages,
         this is equivalent to height, but using logical properties to allow for sizing according to the
         user's language preferences: */
      block-size: 60vb;
      /* using the url() function to load the SVG: */
      mask-image: url(//davidrhysthomas.co.uk/linked/mask.svg);
      /* positioning the SVG in the center of the element: */
      mask-position: 50% 50%;
      /* setting the SVG to be sized as large as possible without overflowing the element: */
      mask-size: contain;
    }
    <main>
      <div class="car"></div>
    </main>

    JS Fiddle demo.

    References:

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search