Archives

Recreating the Apple Watch Breathe App Animation

The Apple Watch comes with a stock app called Breathe that reminds you to, um, breathe. There’s actually more to it than that, but the thought of needing a reminder to breathe makes me giggle. The point is, the app has this kinda awesome interface with a nice animation.

Photo courtesy of Apple Support

I thought it would be fun to recreate the design in vanilla CSS. Here’s how far I got, which feels pretty close.

Making the circles

First things first, we need a set of circles that make up that flower looking design. The app itself adds a circle to the layout for each minute that is added to the timer, but we’re going to stick with a static set of six for this demo. It feels like we could get tricky by using ::before and ::after to reduce the HTML markup, but we can keep it simple.

We’re going to make the full size of each circle 125px which is an arbitrary number. The important thing is that the default state of the circles should be all of them stacked on top of one another. We can use absolute positioning to do that.

Note that we’re using the translate function of the transform property to center everything. I had originally tried using basic top, right, bottom, left properties but found later that animating translate is much smoother. I also originally thought that positioning the circles in the full expanded state would be the best place to start, but also found that the animations were cumbersome to create that way because it required resetting each one to center. Lessons learned!

If we were to stop here, there would be nothing on the screen and that’s because we have not set a background color. We’ll get to the nice fancy colors used in the app in a bit, but it might be helpful to add a white background for now with a hint of opacity to help see what’s happening as we work.

We need a container!

You may have noticed that our circles are nicely stacked, but nowhere near the actual center of the viewport. We’re going to need to wrap these bad boys in a parent element that we can use to position the entire bunch. Plus, that container will serve as the element that pulses and rotates the entire set later. That was another lesson I had to learn the hard way because I stubbornly did not want the extra markup of a container and thought I could work around it.

We’re calling the container .watch-face here and setting it to the same width and height as a single circle.

Next up, animate the circles

At this point, I was eager to see the circles positioned in that neat floral, overlapping arrangement. I knew that it would be difficult to animate the exact position of each circle without seeing them positioned first, so I overrode the transform property in each circle to see where they’d land.

We could set up a class for each circle, but using :nth-child seems easier.

I have to admit that the way I went about it feels super clunky because each circle has it’s own animation. It would be slicker to have one animation that can rule them all to push and re-center the circles, but maybe someone else reading has an idea and can share it in the comments.

Now we can apply those animations to each :nth-child in place of transform:

Note that we set the animation-timing-function to ease because that feels smooth…at least to me! We also set the animation-direction to alternate so it plays back and forth and set the animation-iteration-count to inifinite so it stays running.

Like the circles, we want the animation to run both ways and repeat infinitely. In this case, the scale drops to a super small size as the circles stack on top of each other and the whole thing rotates halfway on the way out before returning back on the way in.

I’ll admit that I am not a buff when it comes to finding the right animation-timing-function for the smoothest or exact animations. I played with cubic-bezier and found something I think feels pretty good, but it’s possible that a stock value like ease-in would work just as well.