Guide to utilizing SVG animations for line drawing rather than just outlines

I've been experimenting with animating an SVG file to resemble the gif below, and I'm getting pretty close, but I seem to be encountering an issue where the outlines are drawn before being filled. I want the entire lines to be animated as shown in the gif.

Can anyone suggest modifications to my CSS or adjustments needed in the SVG itself to achieve this effect? I have limited experience when it comes to animating SVGs.

Current Animation

<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1244.41 201.57">
        <defs>
          <style>
          .cls-1 {
            fill:#f59e00;
          }
          .cls-2 {
            fill:#7a1331;
          }
          #Dots circle {
            fill:#1e9a64;
          }
          #Lines path {
            animation: draw 3s linear forwards;
            animation-delay: 1.2s;
          }

          #Years_Text {
            animation: 1s ease-out 0s 1 slideInFromRight;
          }

          .line-1 {
            stroke-dasharray: 2150;
            stroke-dashoffset: 2150;
          }
          .
          .
          .
          
         </svg>
     

Wanted Animation

https://i.stack.imgur.com/FIYjT.gif

Answer №1

The main issue at hand is:

@keyframes draw {
  to {
    stroke-dashoffset: 0;
    fill: #1e9a64; <=== this
  }
}

You are unable to apply the fill property while the path is being drawn, as the path needs to be completed first.

I recommend adjusting the paths so that the space between the sides of the path is roughly half the stroke width.

Alternatively, you can modify the stroke width (for example, stroke-width="7.5") and increase the size of the circles slightly (for instance, r="9.98)...

An approximation could look something like this:

svg {
  margin: 5vh
}
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1244.41 201.57">
    <defs>
      <style>
      .cls-1 {
        fill:#f59e00;
      }
      .cls-2 {
        fill:#7a1331;
      }
      #Dots circle {
        fill:#1e9a64;
      }
      #Lines path {
        animation: draw 3s linear forwards;
        animation-delay: 1.2s;
      }

      #Years_Text {
        animation: 1s ease-out 0s 1 slideInFromRight;
      }

      .line-1 {
        stroke-dasharray: 2150;
        stroke-dashoffset: 2150;
      }
      .line-2 {
        stroke-dasharray: 1600;
        stroke-dashoffset: 1600;
      }
      .line-3 {
        stroke-dasharray: 1000;
        stroke-dashoffset: 1000;
      }
      .line-4 {
        stroke-dasharray: 650;
        stroke-dashoffset: 650;
      }
      .line-5 {
        stroke-dasharray: 1600;
        stroke-dashoffset: 1600;
      }
      .line-6 {
        stroke-dasharray: 1300;
        stroke-dashoffset: 1300;
      }

        @keyframes draw {
          to {
            stroke-dashoffset: 0;
          }
        }


        .dot-1 {
          animation: 1s ease-out 0s 1 slideInFromLeft;
        }
        .dot-2 {
          animation: 1s ease-out 0s 1 slideInFromCenterToLeft;
        }
        .dot-3 {
          animation: 1s ease-out 0s 1 slideInFromCenterToLeft;
        }
        .dot-4 {
          animation: 1s ease-out 0s 1 slideInFromCenterToLeft;
        }
        .dot-5 {
          animation: 1s ease-out 0s 1 slideInFromLeft;
        }
        .dot-6 {
          animation: 1s ease-out 0s 1 slideInFromLeft;
        }
        .dot-7 {
          animation: 1s ease-out 0s 1 slideInFromCenterToRight;
        }
        .dot-8 {
          animation: 1s ease-out 0s 1 slideInFromCenterToRight;
        }
        .dot-9 {
          animation: 1s ease-out 0s 1 slideInFromTop;
        }
        .dot-10 {
          animation: 1s ease-out 0s 1 slideInFromLeft;
        }
        .dot-11 {
          animation: 1s ease-out 0s 1 slideInFromRight;
        }
        .dot-12 {
          animation: 1s ease-out 0s 1 slideInFromRight;
        }

        @keyframes slideInFromLeft {
          0% {
            transform: translate(-20%, -20%);
          }
          100% {
            transform: translate(0, 0);

          }
        }
        @keyframes slideInFromRight {
          0% {
            transform: translate(+20%, +20%);
          }
          100% {
            transform: translate(0, 0);

          }
        }
        @keyframes slideInFromCenterToRight {
          0% {
            transform: translate(-5%, +50%);
          }
          100% {
            transform: translate(0, 0);

          }
        }
        @keyframes slideInFromCenterToLeft {
          0% {
            transform: translate(+15%, +30%);
          }
          100% {
            transform: translate(0, 0);

          }
        }
        @keyframes slideInFromTop {
          0% {
            transform: translate(-5%, -5%);
          }
          100% {
            transform: translate(0, 0);

          }
        }

        </style>
    </defs>

<g id="Lines">
        <path class="line-1" fill="none" stroke="#1e9a64" stroke-width="7.5" d="M1155.49,188.09h-69.85A3.74,3.74,0,0,1,1083,187l-20.2-20.19a3.73,3.73,0,0,1-1.09-2.64v-137a3.73,3.73,0,0,1,1.09-2.64L1083,4.35a3.74,3.74,0,0,1,2.64-1.1h24.21a3.74,3.74,0,0,1,0,7.47h-22.67l-18,18V162.61l18,18h66.76l18-18V28.73l-18-18h-23.45a3.74,3.74,0,1,1,0-7.47h25a3.74,3.74,0,0,1,2.64,1.1l20.2,20.19a3.73,3.73,0,0,1,1.09,2.64v137a3.73,3.73,0,0,1-1.09,2.64L1158.13,187A3.74,3.74,0,0,1,1155.49,188.09Z" />
        <path class="line-2" fill="none" stroke="#1e9a64" stroke-width="7.5" d="M1145.2,169.43h-14.71a3.74,3.74,0,1,1,0-7.47h13.11l9.7-10.21V39.25l-9.67-9.87H1098.2l-10.37,9.93V151.68l10.4,10.28h11.62a3.74,3.74,0,0,1,0,7.47H1096.7a3.73,3.73,0,0,1-2.62-1.08l-12.6-12.46a3.71,3.71,0,0,1-1.11-2.65V37.72a3.69,3.69,0,0,1,1.15-2.69L1094.12,23a3.71,3.71,0,0,1,2.58-1h48.5a3.79,3.79,0,0,1,2.67,1.12l11.82,12.08a3.72,3.72,0,0,1,1.07,2.61V153.24a3.72,3.72,0,0,1-1,2.57l-11.82,12.45A3.73,3.73,0,0,1,1145.2,169.43Z" />
        <path class="line-3" fill="none" stroke="#1e9a64" stroke-width="7.5" d="M1131.61,150.77h-23.15a3.76,3.76,0,0,1-2.6-1.05l-5.69-5.51a3.71,3.71,0,0,1-1.14-2.68V106a3.73,3.73,0,1,1,7.46,0v34l3.48,3.36h20.31l4.36-3.55V52.26L1130.13,48h-20l-3.63,4V85.35a3.73,3.73,0,0,1-7.46,0V50.64a3.73,3.73,0,0,1,1-2.49l5.7-6.34a3.74,3.74,0,0,1,2.78-1.24h23.15a3.73,3.73,0,0,1,2.55,1l6.76,6.34a3.75,3.75,0,0,1,1.18,2.72v90.89a3.74,3.74,0,0,1-1.38,2.89l-6.76,5.51A3.73,3.73,0,0,1,1131.61,150.77Z" />
        <path class="line-4" fill="none" stroke="#1e9a64" stroke-width="7.5" d="M974.43,150.77H938a3.74,3.74,0,0,1,0-7.47H970.7v-84l-11.33,5.72A3.73,3.73,0,0,1,956,58.41L972.75,50a3.72,3.72,0,0,1,5.41,3.33V147A3.73,3.73,0,0,1,974.43,150.77Z" />
        <path class="line-5" fill="none" stroke="#1e9a64" stroke-width="7.5" d="M1048.22,188.09H938a3.73,3.73,0,0,1-3.73-3.74V165.69A3.73,3.73,0,0,1,938,162h51.39V29.38h-6.5L949.75,46.73a3.73,3.73,0,1,1-3.46-6.61l33.92-17.78a3.72,3.72,0,0,1,1.73-.43h11.15a3.73,3.73,0,0,1,3.73,3.73V165.69a3.73,3.73,0,0,1-3.73,3.74H941.7v11.19h106.52a3.74,3.74,0,0,1,0,7.47Z" />
        <path class="line-6" fill="none" stroke="#1e9a64" stroke-width="7.5" d="M1048.22,169.43h-36.47a3.74,3.74,0,0,1,0-7.47h32.73V150.77h-32.73A3.73,3.73,0,0,1,1008,147V10.72H975.33L940.84,28.36a3.73,3.73,0,1,1-3.4-6.64L972.73,3.66a3.74,3.74,0,0,1,1.7-.41h37.32A3.73,3.73,0,0,1,1015.48,7V143.3h32.74A3.73,3.73,0,0,1,1052,147v18.66A3.73,3.73,0,0,1,1048.22,169.43Z" />
    </g>


    <g id="Dots">
        <circle class="dot-1" cx="941.03" cy="147.03" r="9.98" />
        <circle class="dot-2" cx="941.23" cy="23.59" r="9.98" />
        <circle class="dot-3" cx="958.83" cy="61.32" r="9.98" />
        <circle class="dot-4" cx="949.22" cy="42.96" r="9.98" />
        <circle class="dot-5" cx="1014.77" cy="165.69" r="9.98" />
        <circle class="dot-6" cx="1045.08" cy="184.35" r="9.98" />
        <circle class="dot-7" cx="1109.85" cy="6.98" r="9.98" />
        <circle class="dot-8" cx="1130.49" cy="6.98" r="9.98" />
        <circle class="dot-9" cx="1109.85" cy="165.69" r="9.98" />
        <circle class="dot-10" cx="1130.49" cy="165.69" r="9.98" />
        <circle class="dot-11" cx="1102.87" cy="105.99" r="9.98" />
        <circle class="dot-12" cx="1102.87" cy="85.35" r="9.98" />
    </g>
</svg>

By the way, there exists an attribute in SVG known as pathLength which can be manually set, for example, pathLength="`"`.

Referencing information from CSS-Tricks

This attribute does not have any direct impact on its own (to my knowledge). It doesn't draw only a portion of the path — it still draws the entire path as if no modification was made, just with the path length value set to 1.

Now, you can set the stroke-dasharray to 1 and animate the offset using CSS!

For instance,

@keyframes dash {
  from {
    stroke-dashoffset: 1;
  }
  to {
    stroke-dashoffset: 0;
  }
}

This method helps reduce repetition within your CSS code significantly.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue with Bootstrap's pull-right class causing elements to overlap

I need help positioning a single button above a list, with the button to the right. Whenever I try using the pull-right class on the button (or its containing div), the button ends up being covered by the list. <div> <div class="pull-right"& ...

Difficulty Aligning Header Elements - Combining Navigation and Logo on the Same Line

I am currently facing an issue with positioning a logo and navigation links within a <header> element. When I apply the CSS property text-align:center;, the logo aligns to the center on one line while the navigation links appear on another line direc ...

IE and Chrome are experiencing issues where the radio buttons are disappearing

Here is the style sheet code: select,input ,td a {border:1px solid green; width:25%;height:25px;font-size:20px;margin- left:.1em;} input.myradio {border:none;width:0%;height:0%;font-size:0%;} And here is the corresponding HTML code: <td><inpu ...

Implement a feature in JS/HTML where clicking on a button shifts a specific section of a row from one table to another while simultaneously deleting the remaining

I am facing an issue with two tables - addFriends and existingFriends. The addFriends table contains a button in the fourth column, which, upon clicking, should delete the corresponding row from that table and add it to the existingFriends table. Currentl ...

What is the best way to set unique heights for various ion-grid components?

Situation: I am facing an issue with my Ionic/Angular app. The screen layout, as shown in the image provided and on Stackblitz, includes two ion-grids with different background colors - green and red. Goal: My goal is to assign a percentage height to each ...

Is it possible to arrange the final divs on top of the initial ones without any overlap between them?

I have a script for uploading files that displays all previously uploaded images in divs with the class "download". When I use a jQuery script to add more pictures, it puts them in divs with the class "upload". I want these new uploads to be displayed ab ...

Why does my HTML file consistently prioritize the final instance of my two external style sheets when loading?

I am looking to implement Media Queries for Responsive Web Design. My goal is to have two distinct CSS files based on the browser width being either higher or lower than 900px. Here is how I included the external stylesheets: <link id="Min900" rel="st ...

Revisiting the Issue: Jquery Hover Effect Fails to Function in Internet Explorer

Can anyone provide assistance with this issue? The code snippet works perfectly in all browsers except for IE, where the menu does not fade in and looks unattractive. html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.o ...

Whenever I insert an http link for FontAwesome, the icons work perfectly fine. However, when I try to host it locally,

After providing the CDN link: <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css" rel="stylesheet"> The icons are displaying correctly and everything is working fine. You can view the code on ...

Aligning an image within the layout of a Ghost theme

I'm currently using Ghost's free Starter theme and I'm attempting to center an image that is wider than the paragraph and main element (60rem). These are the key CSS elements that control the positioning of the image. I can achieve full wid ...

Is there a way to convert inline styling to CSS using Material-ui within a React component?

In my development work with React, I initially utilized inline styling to customize the appearance of material-UI components. However, I have come to realize that utilizing CSS provides a more structured and efficient approach to styling components. Despit ...

Creating a notification for specific choices in a dropdown menu

I am working on a form that includes a select element with multiple options. Depending on the option selected, a different form will be displayed. My concern is if a user starts filling out one form and then decides to select another option, I want to add ...

Bizarre actions with jQuery append in Internet Explorer 8

Issue with adding elements to a div in IE8: The element is not added until the button is clicked twice, resulting in two new elements being added at once. Here's the code snippet in question: $(options.addButton).click(function(event) { var proto ...

"Utilizing Bootstrap 4: Wide text causes columns to stack on top of

My website has a layout with three columns: col-auto on the left, col in the middle, and col-auto on the right. The col-auto columns display skyscraper ads (600x160) while the col column contains text. However, when the text inside the col column is wide, ...

Discovering hidden elements using Overflow:hidden

I need help figuring out how to display the cropped part of my text without using scroll bars in css. For example: td { overflow: hidden; } The hidden content is important, but the table property is fixed. table { table-layout: fixed; } I want the ...

row-1 css classes on the top in a project built with Blazor

I'm currently working on customizing the standard layout provided in Blazor projects like WASM or server, but I'm a bit perplexed by the top-row px-4 css classes. Within the HTML code that appears to define the top row/header section is this sni ...

Create a row in React JS that includes both a selection option and a button without using any CSS

My dilemma involves a basic form consisting of a select element and a button. What I want to accomplish is shifting the position of the form to the right directly after the select element Below is the code snippet that I have: return ( <> <div ...

Is it permissible to employ both CSS pseudo-elements, namely before and after, on a single selector in this instance?

Seeking to create a visually appealing horizontal menu navigation resembling: {image1} ITEM1 [separator1] {image2} ITEM2 [separator2] etc. However, a constraint exists - the HTML structure must remain unchanged. Can this be achieved solely with CSS us ...

How to Implement Loading Image with CSS

I have customized the CSS code below to style a div element that showcases a responsive image. .my-img-container { position: relative; &:before { display: block; content: " "; background: url("https://lorempixel.com/300/160/") ...

the background image shivering with movement

While experimenting with some animations, I encountered a small issue: When trying to animate a div that has an image as its background, the image appears to shake, especially when expanding and shrinking the div from the center. Is there a way to prevent ...