DEV Community

Cover image for Animated play button - Pure css
Mostafa Alvandi Setvat
Mostafa Alvandi Setvat

Posted on

Animated play button - Pure css

Hi! I am Mostafa, and this is my first post on DEV.
Here I want to explain how I built this:

First of all, we use checkbox hack, so our body should contain a checbox and a label:

<input type="checkbox" name="play-checkbox" id="play-checkbox">
<label for="play-checkbox">
  <div class="play">
  </div>
</label>
Enter fullscreen mode Exit fullscreen mode

Then some basic styling:

*,
*:after,
*::before {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}
:root {
  --primary-color: #242424;
  --background-color: #01af5b;
}
body {
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--background-color);
}
#play-checkbox {
  display: none;
}
Enter fullscreen mode Exit fullscreen mode

Our goal is to create two triangles, use them to make another triangle, and finally turn these triangles into two vertical bars.

elements before transition

elements after transition

.play {
  height: 22rem;
  width: 22rem;
  border: 1rem var(--primary-color) solid;
  border-radius: 40rem;
  overflow: hidden;
  position: relative;
}
.play::before,
.play::after {
  content: "";
  position: absolute;
  width: 10rem;
  height: 5.8rem;
  transition: all 400ms ease-out;
  left: 6.7rem;
}
Enter fullscreen mode Exit fullscreen mode

The whole element has a 20rem width(2rem for border), and The play triangle has a 10rem height (in trigonometry concept). Here it means it has a 10rem width.
For the height, we use math:

height=10remtan30°5.8rem height = 10 rem *\tan 30\degree \simeq 5.8 rem



And the left:6.7rem centers it horizontally (using trigonometry again :The centers of the big triangle and circle should be the same.).

The big triangle now has 10rem width and 11.6 rem height. So we need 4.2rem on top and bottom to center it.

Now we use linear-gradient to make two triangles.

.play::before {
  top: 4.2rem;
  background-image: linear-gradient(
    30deg,
    var(--primary-color) 49%,
    transparent 50%
  );
}
.play::after {
  top: 10rem;
  background-image: linear-gradient(
    -30deg,
    transparent 49%,
    var(--primary-color) 50%
  );
}
Enter fullscreen mode Exit fullscreen mode

First part is over. Just keep in mind: ::before's center:(top:7.1rem,left:11.7rem) and ::after's center:(top:12.9rem,left:11.7rem).

For the next part, we should do 3 things:

  • Getting rid of background gradient
  • Decreasing width
  • Rotating and moving pseudo-elements to final positions.

Let's add our checkbox hack code:

#play-checkbox:checked + label .play::before {
 /*
increase background size
transform:some rotation,translate and scale
*/ 
}
#play-checkbox:checked + label .play::after {
 /*
increase background size
transform:some rotation,translate and scale
*/ 
}
Enter fullscreen mode Exit fullscreen mode

For background, we just increase the background size from 100% to 400% (actually 300% is enough.)

And transform:
Imagine the final pause button shape, two bars with 2.5rem width and 5rem space between them.
2.5/5.8=0.43 2.5/5.8 = 0.43 , so Y scale factor will be 0.43 and height doesn't change.
In the final state we have :::before's center:(top:10rem,left:6.25rem) and ::after's center:(top:10rem,left:13.75rem).
So we should move ::before 5.45rem left and 2.9rem down and ::after 2.05rem right and 2.9rem up.
In CSS it means:

{
transform: translate(-5.45rem, 2.9rem)
}
/* and */
{
transform: translate(2.05rem, -2.9rem)
}
Enter fullscreen mode Exit fullscreen mode

Now we can complete our work:
Note that when we use multiple transform functions, the order is important.

.play::before,
.play::after {
  /* Don't forget this */
  background-size: 100%;
}
#play-checkbox:checked + label .play::before {
  background-size: 400%;
  transform: translate(-5.45rem, 2.9rem) rotate(90deg) scaleY(0.43);
}
#play-checkbox:checked + label .play::after {
  background-size: 400%;
  transform: translate(2.05rem, -2.9rem) rotate(90deg) scaleY(0.43);
}
Enter fullscreen mode Exit fullscreen mode

And Now our button is working! Try to increase transition duration to see exactly what's happening.
Thank you!

Top comments (0)