Animated play button - Pure css
Tags: animation, tutorial, css, design
Published: 2022-08-12 08:42:00

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

{% codepen https://codepen.io/alvandisetvat/pen/abYavpJ %}

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

```HTML
<input type="checkbox" name="play-checkbox" id="play-checkbox">
<label for="play-checkbox">
  <div class="play">
  </div>
</label>
```
Then some basic styling:

```css
*,
*: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;
}
```
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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ga6k572l287i5rs7xnej.png)

![elements after transition](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ztsg8s3sb5e04rut30kt.png)

```css
.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;
}
```
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:
{% katex %}
 height = 10 rem *\tan 30\degree \simeq 5.8 rem
{% endkatex %}
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.

```css
.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%
  );
}
```
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:

```css
#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
*/ 
}
```
 
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.
 {% katex inline %}
 2.5/5.8 = 0.43
{% endkatex %} , 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:

```css
{
transform: translate(-5.45rem, 2.9rem)
}
/* and */
{
transform: translate(2.05rem, -2.9rem)
}
```
Now we can complete our work:
Note that when we use multiple transform functions, **the order is important**.
```css
.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);
}
```
And Now our button is working! Try to increase transition duration to see exactly what's happening.
Thank you!