Hello Frontend developers, today i will show you how to create a smooth worm or snake animation, whatever name you like, with html and css only. We are going to SASS just for writing less css. You can get the css code from sass in the codepen below. Just click the dropdown in the CSS tab and select "view compiled css".
Let's get started...
What we are going to build?
HTML
<div class="parent">
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
</div>
- So we have just created a container with class name "parent" with 12 child elements with a class name "circle"
CSS
Basic stylings
html {
color-scheme: dark light;
}
body {
min-height: 100vh;
display: grid;
place-items: center;
}
.parent {
margin-top: 50px;
width: 200px;
aspect-ratio: 1;
position: relative;
}
- The color-scheme property specifies that the web page should adapt to both dark and light color schemes.
- The body style ensures that the body of the web page is centered both horizontally and vertically on the screen.
- The parent class defines a container with a square aspect ratio (width equals height) and relative positioning.
Child elements stylings
.circle {
--size: 25px;
width: var(--size);
aspect-ratio: 1;
border-radius: 50%;
position: absolute;
top: 0;
@media screen and (max-width: 580px) {
--size: 15px;
}
}
- We have 1 variables size for width of the circles
- aspect ration ensures the circles will always have a equal width and height and border radius makes the circles circular.
- top property initial value is set to 0 and will be used in the animation part.
Colors
$colors: (
#ff5733,
#ffbd33,
#33ff57,
#33a1ff,
#b933ff,
#ff33a1,
#33ffbd,
#338aff,
#ff3333,
#33ffa1,
#a1ff33,
#ff33bd
);
- As we have 12 child elements, we are defining 12 different colors for each cirlce
Logic for the circles
@for $i from 1 through length($colors) {
.circle:nth-of-type(#{$i}) {
background-color: nth($colors, $i);
animation: rotate ease-in-out infinite alternate;
animation-delay: #{$i *
0.1}s; // Adjust the delay to control the spacing between animations
animation-duration: 2s; // Adjust the duration as needed for the speed of rotation
transform-origin: center; // Rotate from the center of each circle
left: #{$i * 20}px;
}
}
- Using SASS, we are looping through the colors array from 1-12.
- Then passing the value of i to the nth-child, it will applied like this (nth-child(1), nth-child(2), ... and so on)
- Then we have passed the animation name, transition value, iteration as infinite and alternate so it will be in flow not start the animation from scratch again and again.
- Animation delay is different for each item as we are using i times .1s, which will be like this(animation-delay:.1s, animation-delay:.2s, animation-delay:.3s,... and so on).Making the left side circles move fast and right side ones slow. Animation delay makes the animation looks like worm
- Then animation duration set to 2s to make the animation little bit slow.
- Then left property with a value i multiplied by 20(20,40,60), to provide a gap between the circles.
Animation
@keyframes rotate {
0% {
top: 0;
}
50% {
top: 100%;
}
100% {
top: -100%;
}
}
- So the initial position of the circles are center as i have made the body as grid and place items as center. you can use some other container or div to wrap around the parent container and make the outer container as grid and place the items at center with height 100vh.
- Animation will start the top 0, which is center, the at 50 % go downwards and at 100% go upwards and then keep this flow runnning.
Feel free to give suggestions in comments to improve the component and make it more reusable and efficient.
THANK YOU FOR CHECKING THIS POST
You can contact me on -
Instagram - https://www.instagram.com/supremacism__shubh/
LinkedIn - https://www.linkedin.com/in/shubham-tiwari-b7544b193/
Email - shubhmtiwri00@gmail.com
You can help me with some donation at the link below Thank you👇👇
☕ --> https://www.buymeacoffee.com/waaduheck <--
Also check these posts as well
Top comments (8)
Check out this beautiful Jellyfish-menue I created for this page. This is reacting to mouse movement and is super easy to use (see example lower on this page). Do you think, this could be achieved using CSS only? And can we build a code module somehow to reuse it in any other project?
Like we can create that circular layout alone with CSS but for that mouse movement, we need javascript, or if the movement is automatic then we can do that with CSS only as well
So, is there any advantage of using CSS instead of using JS directly? I found that even modifying CSS through Javascript works amazingly well on most browsers.
No just less javascript means less compilation for the code, better website performance, As the browser don't have to rely on javascript to function, as soon as the page loads on slow network even than the layout will be functional
Oh, this is just a fairy tale.
The thing is: all this happens, after your initial page was loaded.
Browsers are increadibly fast on decoding HTML, so decoding the page only takes just microseconds. Javascript is executed as soon as it is found in the source, so your scripts start running long before your page gets visible. Often you need to take care that a script does not acces the page before the DOM is fully established.
There is a difference between "building the DOM" and "displaing the page on screen" (-> rendering). The browser cannot start rendering the page, until all CSS is loaded. But is can run your scripts before your page is displayed.
How about slow networks?
Their the download and execution time increases, that's why it is preferred to use CSS as much as possible for stylings and animation
Slow performance affects all ressources in the same way, regardless if it´s a CSS file or an ES6-module. See mozilla -> how browsers work
HTML files are read from top to bottom. Scripts located in the main HTML file are executed when they appear. So, they are usually running before CSS is loaded completely. Just the browser does not show the action, because he cannot show anything before CSS is ready.
Even on a slow network, you do not need to wait for Javascript. Thanks to the preload scanner, all external files, including CSS, are requested in parallel. What returns first is executed first. Even if the broswer needs to wait for the the React core to be loaded, a smaller script file can already be executed long before React is ready.
Bulky ressources may in fact slow down the page start. But if you include a bulky CSS file, just to save some bytes of Javascript, this might be a bad advice: If the script is loaded slowly, your animation will start a bit delayed. But if your CSS loads slowly, the user will see an empty or wrong formatted page.
Actually in one of my task I have worked on, there is a book section with book imaged and details, we have created a logic with JS to randomly change the book details from 5 available books, On slow network, the section is empty for a second or two, so I created a default book section with static html and css to load it on slow network as well, then when the JS execution completes, randomly change the book, Sometimes JS stops interactivity for the elements, As my senior taught me to look after for all the edge cases, I try to minimise the code wherever possible