CSS Animated snake ๐Ÿ

โœ๏ธ

Learn how to animate a snake just using CSS

18 Apr, 2020 ยท 6 min read

Sometimes I want to experiment and feel how powerful CSS these days is.

So let's create something reasonably straightforward, but cool! A animated moving snake in CSS only.

Setting up the HTML

To create our snake we are going to create one main snake div and add some dots in this, each dot will have it's own id so we can animate it better.

<div class="container">
  <div class="snake">
    <div class="dot dot-1"></div>
    <div class="dot dot-2"></div>
    <div class="dot dot-3"></div>
    <div class="dot dot-4"></div>
    <div class="dot dot-5"></div>
    <div class="dot dot-6"></div>
    <div class="dot dot-7"></div>
    <div class="dot dot-8"></div>
    <div class="dot dot-9"></div>
    <div class="dot dot-10"></div>
    <div class="dot dot-11"></div>
    <div class="dot dot-12"></div>
    <div class="dot dot-13"></div>
    <div class="dot dot-14"></div>
    <div class="dot dot-15"></div>
    <div class="dot dot-16"></div>
    <div class="dot dot-17"></div>
    <div class="dot dot-18"></div>
    <div class="dot dot-19"></div>
    <div class="dot dot-20"></div>
  </div>
</div>

CSS for a animated snake

$numberOfDots: 20;
* {
  margin: 0;
  padding: 0;
}
.container {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100vw;
  height: 100vh;
  background: #55d6be;
}
.snake {
  .dot {
    width: 12px;
    height: 12px;
    background: #fc6471;
    border-radius: 50%;
    margin: 5px 0;
    &:nth-child(1) {
      width: 10px;
      height: 10px;
      background: #fff !important;
    }
    &:nth-child(odd) {
      background: #090909;
    }
  }
}
@for $i from 1 through $numberOfDots {
  $delay: 0.1 * $i;
  .dot-#{$i} {
    animation: dot 1.5s infinite;
    animation-delay: $delay + s;
  }
}
@keyframes dot {
  0%,
  100% {
    transform: translateX(0);
  }
  50% {
    transform: translateX(-15px);
  }
}

This code is build in scss, we can compile this to plain css, but it will become very long, so for the sake of explaining what this does we will keep the scss stylesheet and explain what happens.

$numberOfDots: 20;

We define the number of dots (body parts) of our snake ๐Ÿwe can use this variable later on to loop each div, a handy feature of scss.

* {
  margin: 0;
  padding: 0;
}

The * selector is a global selector, it will select every element and in this case remove margin and padding from it.

.container {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100vw;
  height: 100vh;
  background: #55d6be;
}

As seen in many of my example we want to center our snake and I choose to center is with flexbox and use the 100vw and 100vh attributes.

.snake {
  .dot {
    width: 12px;
    height: 12px;
    background: #fc6471;
    border-radius: 50%;
    margin: 5px 0;
    &:nth-child(1) {
      width: 10px;
      height: 10px;
      background: #fff !important;
    }
    &:nth-child(odd) {
      background: #090909;
    }
  }
}

Our snake self has no styling, but each dot (body part) inside it consist of a basic width and height. We give it a pink color, and a border-radius: 50% which will make the div round! Then we add some margin so it's not stacked.

&:nth-child(1) { This is a pseudo-selector in this case we want the first child and make it slightly stronger and white, this will be the snakes head.

&:nth-child(odd) { again a pseudo-selector but this time we get every odd dot element and make it black, so 1,3,5... will be be black and 2,4,6... will be pink (the default).

@for $i from 1 through $numberOfDots {
  $delay: 0.1 * $i;
  .dot-#{$i} {
    animation: dot 1.5s infinite;
    animation-delay: $delay + s;
  }
}

So as mentioned we are using the variable here, we are going to loop through 1 to 20 and calculate a custom delay for each dot.

Then we say each dot should have the dot animation which will play for 1.5seconds infinite (never stops)

Uncompiled it will look like this:

.dot-1 {
  animation: dot 1.5s infinite;
  animation-delay: 0.1s;
}
.dot-2 {
  animation: dot 1.5s infinite;
  animation-delay: 0.2s;
}
.dot-3 {
  animation: dot 1.5s infinite;
  animation-delay: 0.3s;
}
...

And then we add a unique animation-delay to each dot this will increase for each dot.

@keyframes dot {
  0%,
  100% {
    transform: translateX(0);
  }
  50% {
    transform: translateX(-15px);
  }
}

This is the part that makes the snake move.

We make our own @keyframe animation called dot and say at position 0 and 100% it should do transform: translateX(0); on position 50% it should transform: translateX(-15px);. The translateX will move the dot -15px to the left at 50% and fill the gaps in between 0-50 and 50-100% so it will look smooth.

See a working example in this Codepen:

See the Pen CSS Animated snake ๐Ÿ by Chris Bongers (@rebelchris) on CodePen.

Thank you for reading, and let's connect!

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter

Spread the knowledge with fellow developers on Twitter
Tweet this tip
Powered by Webmentions - Learn more

Read next ๐Ÿ“–

Bringing perspective to CSS

7 Aug, 2022 ยท 2 min read

Bringing perspective to CSS

Creating a 3D Cylinder shape in CSS

29 Jul, 2022 ยท 3 min read

Creating a 3D Cylinder shape in CSS