CSS Beating Heart Tutorial.

CSS Beating Heart Tutorial.

DOWNLOAD THE FILES

Hearts might be complicated in the real world, but at least with CSS they’re quite easy to figure out.
In order to make a more complicated shapes in CSS we have to break them down into more basic shapes.
In this case, we’re going to break the heart apart into two circles and a square.
HTML elements are essentially squares or rectangles, so the bottom bit of the heart is easy enough!
In order to make the circles, we’re going to utilise the CSS3 border radius property. This property allows us to add rounded corners to an element.

MORE INFO ABOUT BORDER RADIUS

Start by adding a <div> element with a class of “heart-shape”

<body>
 <div class="heart-shape"></div> 
</body>

Then we want to make it a square by specifying the width and height.
Make it whatever colour you damn well please.
Who needs red? Break those conventions!

.heart-shape{
  position: relative;
  width: 200px;
  height: 200px;
  background-color: #008080;
}

We’re giving it relative positioning so that later on we have the control to absolutely position the circles in relation to it.
Here’s a reminder of relative and absolute positioning in case you need a refresher.

 

Screen-Shot-2017-02-11-at-17.17.13

Lastly, set the top margin to 40% of the viewport height and the left and right margins to auto to position it in the centre of the browser.

.heart-shape{
  position: relative;
  width: 200px;
  height: 200px;
  background-color: #008080;
  margin: 40vh auto;
}

Now for the circles.
Instead of messing about with new elements we’re going to use the pseudo elements :before and :after

 

PSEUDO ELEMENTS

 

The :before pseudo-element is going to become our first circle.
We’ll make it a square, the same size as the heart-shape div and then transform it into a circle by giving it a border radius of 50%
In order to position it where we want it, halfway to the left of the heart-shape div we’re going to give it absolute positioning.
The bottom edge is going to be set to align with the bottom edge of the heart-shape div and the left edge is going to be set to 200px to the left so that the middle aligns with the left side of the heart-shape div

.heart-shape:before{
  position: absolute;
  bottom: 0px;
  left: -100px;
  width: 200px;
  height: 200px;
  content: '';
  -webkit-border-radius: 50%;
  -moz-border-radius: 50%;
  -o-border-radius: 50%;
  border-radius: 50%;
  background-color: #006060;
}

Give it a different colour too for now, so you can see what we’re working with.
Now for the second circle!
For this one we’re going to use the :after psuedo-element.
Exactly the same styles as the first circle we created but with different positioning.
This time we want it to be on top of the square so set the right and top properties accordingly.

.heart-shape:after{
  position: absolute;
  top: -100px;
  right: 0px;
  width: 200px;
  height: 200px;
  content: '';
  -webkit-border-radius: 50%;
  -moz-border-radius: 50%;
  -o-border-radius: 50%;
  border-radius: 50%;
  background-color: #006060;
}

Hooray! A heart shape!
It’s a bit wonky though…
Lets sort that out.

CSS3 Transformation time!

Because the circles are pseudo-elements, absolutely positioned in relation to the main element, when we transform the heart-shape div, the circles will automatically follow.

We want to transform the heart-shape 45 degrees clockwise.
So add the following transforms to your heart-shape styling.

-webkit-transform: rotate(45deg);
  -moz-transform: rotate(45deg);
  -ms-transform: rotate(45deg);
  -o-transform: rotate(45deg);
  transform: rotate(45deg);

Now that we’ve got all the elements positioned correctly, change the colour of the circles so that they’re all uniform.

And there you have it! A CSS heart!
It’s a bit boring like this though. Why don’t we animate it too?

 

CSS3 ANIMATIONS

CSS3 animations allow you to change CSS properties.
To get the animation to work, we have to bind the animation to an element and specify @keyframes for the animation.
The keyframes hold what styles the element will have at different stages of the animation.

We’ve already used transform:rotate on the heart-shape div in, and we want to use transform:scale to make it beat.
We don’t want to override all our hard work, so we’re going to wrap the heart-shape div in another div named heart-animation and apply the animation to that.

<div class="heart-animation"> <div class="heart-shape"></div> </div>

Apply margin:auto to the heart-animation div to centre it
and add the animation name, I’m going to call it beating.

.heart-animation{
  margin:0 auto;
  animation-name: beating;
}

if you don’t specify a duration for the animation it won’t run as the default is 0.
Lets make our animation last 1 second. We want our animation to play infinitely too, so add that in with the animation-iteration count

  animation-duration: 1s;
  animation-iteration-count: infinite;

Now for the keyframes!
We want the heart to scale up in size slightly and then go back to normal.
To do this we’ll have to change the size with transform:scale

TRANSFORMS

we’re going to add two keyframes, one at the beginning of the transformation (0%) and one at the end of the transformation (100%)
the first keyframe will be 20% bigger than the original and the second keyframe will remain the same.

@keyframes beating{
  0%{ transform: scale(1.2); }
  100%{ transform: scale(1); }
}

Have a look and see what you think!
Right now it’s playing the animation, and then restarting it. Which gives it a bit of a stilted, jerky effect.
I’m going to add in another property that controls the direction of the animation.
If we tell it to alternate directions, the animation will reverse direction every other time it plays, making it a bit smoother.

animation-direction: alternate;

And there you have it, a beating CSS heart. Good job!

If you got this far I’ve added in a…….

BONUS DISCO ROUND!
(epilepsy warning!)

Create an infinite animation bound to the body. Call it disco and give it a duration of 0.1s. Make it alternate in direction.

Set the 0% keyframe to a bright colour using the background-color property
and set the 100% keyframe to white.