skip to Main Content

I found a tutorial about creating a breath pacer using CSS:

The inhale and the exhale in the code are the same (4s). I want to control with the code the inhale, post-inhale hold, exhale, post exhale hold timing.

How can I do it?

Tutorial link – https://css-tricks.com/recreating-apple-watch-breathe-app-animation/
codepen – https://codepen.io/geoffgraham/pen/zKMEPE

body {
  background: #000;
  display: flex;
  align-items: center;
  height: 100vh;
  justify-content: center;
}

.watch-face {
  height: 125px;
  width: 125px;
  animation: pulse 4s cubic-bezier(0.5, 0, 0.5, 1) alternate infinite;
}

.circle {
  height: 125px;
  width: 125px;
  border-radius: 50%;
  position: absolute;
  mix-blend-mode: screen;
  transform: translate(0, 0);
  animation: center 6s infinite;
}

.circle:nth-child(odd) {
  background: #61bea2;
}

.circle:nth-child(even) {
  background: #529ca0;
}

.circle:nth-child(1) {
  animation: circle-1 4s ease alternate infinite;
}

.circle:nth-child(2) {
  animation: circle-2 4s ease alternate infinite;
}

.circle:nth-child(3) {
  animation: circle-3 4s ease alternate infinite;
}

.circle:nth-child(4) {
  animation: circle-4 4s ease alternate infinite;
}

.circle:nth-child(5) {
  animation: circle-5 4s ease alternate infinite;
}

.circle:nth-child(6) {
  animation: circle-6 4s ease alternate infinite;
}

@keyframes pulse {
  0% {
    transform: scale(.15) rotate(180deg);
  }
  100% {
    transform: scale(1);
  }
}

@keyframes circle-1 {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(-35px, -50px);
  }
}

@keyframes circle-2 {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(35px, 50px);
  }
}

@keyframes circle-3 {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(-60px, 0);
  }
}

@keyframes circle-4 {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(60px, 0);
  }
}

@keyframes circle-5 {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(-35px, 50px);
  }
}

@keyframes circle-6 {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(35px, -50px);
  }
}
<div class="watch-face">
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
</div>

3

Answers


  1. I want to control with the code the inhale, post-inhale hold, exhale, post exhale hold timing.

    The inhale, exhale are determined by the animation duration, is was 4s, I’ve introduced an CSS variable to easy change that: --duration. For example change it to 8s to double the duration.


    hold timing

    The hold timing is not that easy, since there is no CSS property to ‘hold’ between an ease alternate infinite animation.

    The easiest way to get your output is by adding a keyframe that does not apply any change, eg: it waits.

    100% keyframe means it’s back to the start, so if we copy/paste the keyframe and change the middel frame to 50%, the animation won’t do anything between 50 and 100 procent, so it’s ‘hangs’

    Please play around with the values, I’ve set it to 75% so it won’t animate between the 75% and 100% duration (--duration long)

    The same idea can be applied to the 0% frame so it ‘hangs’ before the growing phase.

    :root {
      --duration: 4s
    }
    
    body {
      background: #000;
      display: flex;
      align-items: center;
      height: 100vh;
      justify-content: center;
    }
    
    .watch-face {
      height: 125px;
      width: 125px;
      animation: pulse var(--duration) cubic-bezier(0.5, 0, 0.5, 1) alternate infinite;
    }
    
    .circle {
      height: 125px;
      width: 125px;
      border-radius: 50%;
      position: absolute;
      mix-blend-mode: screen;
      transform: translate(0, 0);
      animation: center 6s infinite;
    }
    
    .circle:nth-child(odd) {
      background: #61bea2;
    }
    
    .circle:nth-child(even) {
      background: #529ca0;
    }
    
    .circle:nth-child(1) {
      animation: circle-1 var(--duration) ease alternate infinite;
    }
    
    .circle:nth-child(2) {
      animation: circle-2 var(--duration) ease alternate infinite;
    }
    
    .circle:nth-child(3) {
      animation: circle-3 var(--duration) ease alternate infinite;
    }
    
    .circle:nth-child(4) {
      animation: circle-4 var(--duration) ease alternate infinite;
    }
    
    .circle:nth-child(5) {
      animation: circle-5 var(--duration) ease alternate infinite;
    }
    
    .circle:nth-child(6) {
      animation: circle-6 var(--duration) ease alternate infinite;
    }
    
    @keyframes pulse {
      0% {
        transform: scale(.15) rotate(180deg);
      }
      75% {
        transform: scale(1);
      }
      100% {
        transform: scale(1);
      }
    }
    
    @keyframes circle-1 {
      0% {
        transform: translate(0, 0);
      }
      75% {
        transform: translate(-35px, -50px);
      }
      100% {
        transform: translate(-35px, -50px);
      }
    }
    
    @keyframes circle-2 {
      0% {
        transform: translate(0, 0);
      }
      75% {
        transform: translate(35px, 50px);
      }
      100% {
        transform: translate(35px, 50px);
      }
    }
    
    @keyframes circle-3 {
      0% {
        transform: translate(0, 0);
      }
      75% {
        transform: translate(-60px, 0);
      }
      100% {
        transform: translate(-60px, 0);
      }
    }
    
    @keyframes circle-4 {
      0% {
        transform: translate(0, 0);
      }
      75% {
        transform: translate(60px, 0);
      }
      100% {
        transform: translate(60px, 0);
      }
    }
    
    @keyframes circle-5 {
      0% {
        transform: translate(0, 0);
      }
      75% {
        transform: translate(-35px, 50px);
      }
      100% {
        transform: translate(-35px, 50px);
      }
    }
    
    @keyframes circle-6 {
      0% {
        transform: translate(0, 0);
      }
      75% {
        transform: translate(35px, -50px);
      }
      100% {
        transform: translate(35px, -50px);
      }
    }
    <div class="watch-face">
      <div class="circle"></div>
      <div class="circle"></div>
      <div class="circle"></div>
      <div class="circle"></div>
      <div class="circle"></div>
      <div class="circle"></div>
    </div>
    Login or Signup to reply.
  2. This can be controlled by changing the animation pulse. For example, now I reduced the inhalation and increased the delay before exhalation:

    body {
      background: #000;
      display: flex;
      align-items: center;
      height: 100vh;
      justify-content: center;
    }
    
    .watch-face {
      height: 125px;
      width: 125px;
      animation: pulse 4s cubic-bezier(0.5, 0, 0.5, 1) alternate infinite;
    }
    
    .circle {
      height: 125px;
      width: 125px;
      border-radius: 50%;
      position: absolute;
      mix-blend-mode: screen;
      transform: translate(0, 0);
      animation: center 6s infinite;
    }
    
    .circle:nth-child(odd) {
      background: #61bea2;
    }
    
    .circle:nth-child(even) {
      background: #529ca0;
    }
    
    .circle:nth-child(1) {
      animation: circle-1 4s ease alternate infinite;
    }
    
    .circle:nth-child(2) {
      animation: circle-2 4s ease alternate infinite;
    }
    
    .circle:nth-child(3) {
      animation: circle-3 4s ease alternate infinite;
    }
    
    .circle:nth-child(4) {
      animation: circle-4 4s ease alternate infinite;
    }
    
    .circle:nth-child(5) {
      animation: circle-5 4s ease alternate infinite;
    }
    
    .circle:nth-child(6) {
      animation: circle-6 4s ease alternate infinite;
    }
    
    @keyframes pulse {
      0% {
        transform: scale(.15) rotate(180deg);
      }
      /* 👇 */
      60% {
        transform: scale(1);
      }
      /* ☝️ */
      100% {
        transform: scale(1);
      }
    }
    
    @keyframes circle-1 {
      0% {
        transform: translate(0, 0);
      }
      100% {
        transform: translate(-35px, -50px);
      }
    }
    
    @keyframes circle-2 {
      0% {
        transform: translate(0, 0);
      }
      100% {
        transform: translate(35px, 50px);
      }
    }
    
    @keyframes circle-3 {
      0% {
        transform: translate(0, 0);
      }
      100% {
        transform: translate(-60px, 0);
      }
    }
    
    @keyframes circle-4 {
      0% {
        transform: translate(0, 0);
      }
      100% {
        transform: translate(60px, 0);
      }
    }
    
    @keyframes circle-5 {
      0% {
        transform: translate(0, 0);
      }
      100% {
        transform: translate(-35px, 50px);
      }
    }
    
    @keyframes circle-6 {
      0% {
        transform: translate(0, 0);
      }
      100% {
        transform: translate(35px, -50px);
      }
    }
    <div class="watch-face">
      <div class="circle"></div>
      <div class="circle"></div>
      <div class="circle"></div>
      <div class="circle"></div>
      <div class="circle"></div>
      <div class="circle"></div>
    </div>
    Login or Signup to reply.
  3. I have added another animation percentage to overcome the alternate sequence. I hope this helps.

    :root{
      /* 👇 you can set desired time as you want */
      --duration: 6s;
      --anim-circle: ease-out infinite;
    } 
    
    body {
      background: #000;
      display: flex;
      align-items: center;
      height: 100vh;
      justify-content: center;
    }
    
    .watch-face {
      height: 125px;
      width: 125px;
      animation: pulse  var(--duration) cubic-bezier(0.65, 0.05, 0.36, 1) infinite;
    }
    
    .circle {
      height: 122px;
      width: 122px;
      border-radius: 50%;
      position: absolute;
      mix-blend-mode: screen;
      transform: translate(0, 0);
    }
    
    .circle:nth-child(odd) {
      background: #61bea2;
    }
    
    .circle:nth-child(even) {
      background: #529ca0;
    }
    
    .circle:nth-child(1) {
      animation: circle-1 var(--duration) var(--anim-circle);
    }
    
    .circle:nth-child(2) {
      animation: circle-2 var(--duration) var(--anim-circle);
    }
    
    .circle:nth-child(3) {
      animation: circle-3 var(--duration) var(--anim-circle);
    }
    
    .circle:nth-child(4) {
      animation: circle-4 var(--duration) var(--anim-circle);
    }
    
    .circle:nth-child(5) {
      animation: circle-5 var(--duration) var(--anim-circle);
    }
    
    .circle:nth-child(6) {
      animation: circle-6 var(--duration) var(--anim-circle);
    }
    
    @keyframes pulse {
      0%, 100% {
        transform: scale(.15) rotate(-135deg);
      }
      80% {
        transform: scale(1);
      }
    }
    
    @keyframes circle-1 {
      0%, 100% {
        transform: translate(0, 0);
      }
      80%, 90% {
        transform: translate(-35px, -50px);
      }
    }
    
    @keyframes circle-2 {
      0%, 100% {
        transform: translate(0, 0);
      }
      80%, 90%  {
        transform: translate(35px, 50px);
      }
    }
    
    @keyframes circle-3 {
      0%, 100% {
        transform: translate(0, 0);
      }
      80%, 90%  {
        transform: translate(-60px, 0);
      }
    }
    
    @keyframes circle-4 {
      0%, 100% {
        transform: translate(0, 0);
      }
      80%, 90%  {
        transform: translate(60px, 0);
      }
    }
    
    @keyframes circle-5 {
      0%, 100% {
        transform: translate(0, 0);
      }
      80%, 90% {
        transform: translate(-35px, 50px);
      }
    }
    
    @keyframes circle-6 {
      0%, 100% {
        transform: translate(0, 0);
      }
      80%, 90%  {
        transform: translate(35px, -50px);
      }
    }
    <div class="watch-face">
      <div class="circle"></div>
      <div class="circle"></div>
      <div class="circle"></div>
      <div class="circle"></div>
      <div class="circle"></div>
      <div class="circle"></div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search