For a long time, everybody has been talking about CSS and JS animation or animation libraries. I am wondering why no one is talking about HTML
I wish some big names around would have pushed this
animate element of SVG to promote more development over it. Anyways, it is never too late to start something good. I am taking this initiative to start spreading awareness around the front-end community regarding
animate element of SVG.
Let's understand SVG first in short.
first thing first - W3schools is always a great start.
- SVG stands for Scalable Vector Graphics
- SVG is used to define vector-based graphics for the Web
- SVG defines the graphics in XML format
- Every element and every attribute in SVG files can be animated
- SVG is a W3C recommendation
- SVG integrates with other W3C standards such as the DOM and XSL
- It's a Vector.
- Being vector it is scalable.
- Smaller file-size. (Average 5X smaller than png file.)
- Easy to modify using CSS and JS.
- Easily Animatable :) in less time. Also, no need for any animation software or image processors.
If you are a first timer to SVG, please get yourself some helpful information about SVG and it's relatives from Sara Soueidan's Blog on understanding SVG Coordinate Systems and Transformations.
We will go step by step.
If you are familiar with Emmet. Just type
html:5 in your emmet enabled editor and execute it for sublime text execution key is Tab Key.
Copy the code from below.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>SVG wave animation</title> <link rel="stylesheet" href="style.css"> </head> <body> <!-- Wave SVG Animation --> <div class="waves"></div> </body> </html>
I am not good at drawing but, I can tell you that cubic bezier is something we can consider as a wave. So, we will draw a cubic Bezier curve.
<div class="waves"> <svg width="100%" height="200px" fill="none"> <path fill="#454599" d=" M 0 67 C 273,183 822,-40 1920,106 V 359 H 0 V 67 Z"> </path> </svg> </div>
Result should something like this:
Here, I have styled background and positioned div using CSS. You can get the CSS from the codepen link of this project at the bottom.
Let me explain you first what's going on with those numbers and letters.
Welcome to the Matrix!
You need to know those green rainfall of numbers from the matrix. (Ignore it)
Okay So, there are three attributes attached to
<svg width="100%" height="200px" fill="none"> and they explain themselves pretty well.
Also, inside the
<svg> element there is the element
<path> and attached with two attributes
d. You still can understand that we are starting to draw a path with
<path> element and filling it with color with
fill attribute inside. But, hey! What's that
d ="1230948713294" about? That's what your question is right? And that's what I want you to understand the most as it is the thing we are going to play within this tutorial.
There are three variants of smooth curves available to draw with SVG.
- Quadratic Bezier curve
- Cubic Bezier curve
We will work with cubic bezier curve in this tutorial. So, let's understand how it works.
If you have any experience with Illustrator or Sketch like softwares, or something like the pen tool you will understand it easily. But, if you do not have any experience with the pen tool, nothing to worry about it. I will explain how bezier curve works at my best.
Bezier curve has two main points and we will call it a start point and end point, and each main point has their handles which we will call control points.
In the figure above:
M x,y is Start Point
C dx1,dy1 is Control Point for Start Point
C x2,y2 is End Point
C dx2,dy2 is Control Point for End Point
M 0 67 M x,y C 273,183 C dX1,dy1 822,-40 --> dx2,dy2 1920,106 x2,y2
Important: we are using absolute Bezier curve in this example by using
C 273 .... If you want to use a relative Bezier curve you can change the **UPPERCASE*
C 273 ... to LOWERCASE
c 273... however it will need modification in defining points.*
Mozilla developer community has a great explanation guide for absolute and relative curves please visit Mozilla Documentation for Cubic Bezier Curves
We will do it with
<animate> element of SVG. In addition, we will use some attributes of
<animate> element. Firstly as we want the wave to keep waving itself, we will use
repeatCount="indefinite". Secondly, we will fill our wave with some color by adding
fill="#454599" attribute. After that, we will target the
d attribute from
<svg> element with
attributeName="d" and we will define the duration for the animation by adding
dur="12s" attribute. Coming up next, we will talk about the
<animate repeatCount="indefinite" fill="#454599" attributeName="d" dur="12s" values="" ></animate>
values="" attribute can be written in several ways depending upon the context where it is being used. On the other hand, if interpreter finds the specification of the list of
values, the interpreter will ignore the values of the attributes
by. Recommended article for more details.
In our case, we are targeting
d attribute of
<svg> element to modify the curve. We also have defined the duration of 12s, that means we can break the iterations in 4 phases of 3 seconds each. Let's start now...
values=" M0 77 C 473,283 822,-40 1920,116 V 359 H 0 V 67 Z; *second and third iteration will go here* M0 77 C 473,283 822,-40 1920,116 V 359 H 0 V 67 Z; "
You might be wondering why I am using the same value for two times?
It is because we will come back to where we started by the end of the fourth iteration of our animation cycle, and we will make some movements in the shape during the second and the third iteration.
Let's make the second and the third animation iteration now.
M0 77 C 473,-40 1222,283 1920,136 V 359 H 0 V 67 Z;
M0 77 C 973,260 1722,-53 1920,120 V 359 H 0 V 67 Z;
Basically, we are modifying values of points and handles between iterations and
<animate> element will smoothen the transformation of points according to the duration of the animation defined with
So, the final code should be something like this:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>SVG wave animation</title> <link rel="stylesheet" href="style.css"> </head> <body> <!-- Wave SVG Animation --> <div class="waves"> <svg width="100%" height="200px" fill="none"> <path fill="#454599" d=" M0 67 C 273,183 822,-40 1920.00,106 V 359 H 0 V 67 Z"> <animate repeatCount="indefinite" fill="#454599" attributeName="d" dur="15s" values=" M0 77 C 473,283 822,-40 1920,116 V 359 H 0 V 67 Z; M0 77 C 473,-40 1222,283 1920,136 V 359 H 0 V 67 Z; M0 77 C 973,260 1722,-53 1920,120 V 359 H 0 V 67 Z; M0 77 C 473,283 822,-40 1920,116 V 359 H 0 V 67 Z "> </animate> </path> </svg> </div> </body> </html>
Ohh, wait... Since this is my first article ever. I have a bonus for you.
Let me tell you how you can add the gradient to the wave.
To add gradient, we will add
<linearGradient> element right before
<path> element. Also, we will provide some attributes to
<linearGradient> such as
id and positions of gradient start and end, something like this
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">.
<linearGradient> element we will define the
stop points of colors we want to use in our gradient. for more details over working with gradients in SVG please read this article on Mozilla developer network : Grdients in SVG.
linearGradient can be used in
check the code below.
<svg width="100%" height="200px" fill="none"> <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%"> <stop offset="0%" stop-color="#00B4DB" /> <stop offset="50%" stop-color="#224488" /> <stop offset="100%" stop-color="#0083B0" /> </linearGradient> <path fill="url(#grad1)" d=" M0 67 C 273,183 822,-40 1920.00,106 V 359 H 0 V 67 Z"> </path> ...
Final output: Check out the pen