Using CSS Animations to Visualize Breathing Techniques

Vanessa Martinez
4 min readSep 15, 2020

One of my favorite things to do with CSS is create animations. It’s a fun way to manipulate shapes, create transitions, and bring your app to life. I’ve been working on a new React app that teaches you different types of breathing techniques to relax. So, when brainstorming how I would visually represent each one, I decided to use custom CSS animations.

To start, I chose the breathing technique that I thought would be easiest to animate: diaphragmatic breathing. It’s simple because it involves inhaling deeply through the nose, allowing the diaphragm to expand, and exhaling through pursed lips, letting the stomach fall. The simplest way to visualize that is with circles that expand and contract.

So, I began by creating the core of the circle using a <p> tag containing the name of the animation, and I gave it a class name.

<p className='anim-circle'>diaphragmatic animation</p>

Then, in my App.css file, I made the text transparent and gave the <p> tag a background color. But that rendered as a rectangle, so I adjusted the border radius to make it into a circle. I also gave it an exact width and height because I wanted it to be small enough to create room for the expanding circle animations. Then, I adjusted the positioning on the page until I got it just right.

.anim-circle {  color: transparent;  position: absolute;  top: -28%;  left: 50%;  width: 70px;  height: 70px;  border-radius: 50%;  background: rgba(188, 237, 243, 0.889);}

That resulted in this:

So, the next step is to give it the first layer of box shadow animation. I added a property of transform, which made the box shadow move, and an animation property with a name (breathe), the animation duration (7s), the animation-direction (linear), and animation-iteration-count (infinite). Then I added the corresponding keyframe with the same animation name (breathe) and gave the box shadow a size and color.

.anim-circle {  color: transparent;  position: absolute;  top: -28%;  left: 50%;  transform: translate(-50%, -50%);  width: 70px;  height: 70px;  border-radius: 50%;  background: rgba(188, 237, 243, 0.889);  animation: breathe 7s linear infinite;}@keyframes breathe { 0% {  box-shadow: 0 0 0 15px rgba(188, 237, 243, 0.3) }
}

That resulted in:

I then decided to add more layers of box shadow, separating each with a comma and making them increasingly larger. All had the same color.

@keyframes breathe { 0% {  box-shadow: 0 0 0 15px rgba(188, 237, 243, 0.3), 0 0 0 30px       rgba(188, 237, 243, 0.3), 0 0 0 45px rgba(188, 237, 243, 0.3), 0 0 0 60px rgba(188, 237, 243, 0.3), 0 0 0 75px rgba(188, 237, 243, 0.3); }
}

That gave me:

But since I wanted users to follow the animation as a visual guide for diaphragmatic breathing, I needed to adjust for a smoother transition. So, I added two more keyframes: 50% and 100%. For the 50% keyframe, I made the box shadows grow as large as I wanted, and then I reduced the size for the 100% keyframe (so it matched 0%).

@keyframes breathe { 0% {box-shadow: 0 0 0 15px rgba(188, 237, 243, 0.3), 0 0 0 30px rgba(188, 237, 243, 0.3), 0 0 0 45px rgba(188, 237, 243, 0.3), 0 0 0 60px rgba(188, 237, 243, 0.3), 0 0 0 75px rgba(188, 237, 243, 0.3); } 50% {box-shadow: 0 0 0 25px rgba(188, 237, 243, 0.3), 0 0 0 50px rgba(188, 237, 243, 0.3), 0 0 0 75px rgba(188, 237, 243, 0.3), 0 0 0 100px rgba(188, 237, 243, 0.3), 0 0 0 125px rgba(188, 237, 243, 0.3); } 100% {box-shadow: 0 0 0 15px rgba(188, 237, 243, 0.3), 0 0 0 30px rgba(188, 237, 243, 0.3), 0 0 0 45px rgba(188, 237, 243, 0.3), 0 0 0 60px rgba(188, 237, 243, 0.3), 0 0 0 75px rgba(188, 237, 243, 0.3); }}

That gave me the desired pulsating effect:

Note: The GIF above may lag slightly, but the animation runs smoothly in my React app.

Here’s a sneak peek at one of the other breathing techniques I’m working on animating. The challenge will be to split the animation timing, so one side expands and contracts while the other does not. Wish me luck!

References:

--

--

Vanessa Martinez

Freelance Software Engineer. Experience in JavaScript, React.js, and Ruby on Rails.