webdevpuneet.com

Breathing Animation — Free HTML CSS JS Snippet

Breathing / Focus Ring · Loaders · Plain HTML, CSS & JS · Live preview

CategoryLoaders

Copy & paste

Source Code

<div class="scene">
  <div class="breathing-wrap" id="wrap">
    <div class="ring r4"></div>
    <div class="ring r3"></div>
    <div class="ring r2"></div>
    <div class="ring r1"></div>
    <div class="core">
      <div class="label" id="label">Breathe in</div>
      <div class="timer" id="timer">4</div>
    </div>
  </div>
  <div class="controls">
    <button class="btn active" id="start-btn" onclick="toggle()">Pause</button>
    <select class="sel" onchange="setPattern(this.value)">
      <option value="4-4">4-4 Box</option>
      <option value="4-7-8">4-7-8</option>
      <option value="5-5">5-5 Equal</option>
    </select>
  </div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Breathing patterns as data: { label, dur } phase arrays
CSS scale animation: inhale scales to 1.4, hold maintains, exhale returns to 1
Animation duration set dynamically via style.animationDuration = dur + "s"
setInterval countdown updates displayed number each second within a phase
Phases iterate via recursive setTimeout after each countdown completes
Pattern buttons switch between 4-4, 4-7-8, and 5-5 techniques
Ambient circle with blur and opacity layers for visual depth
Export as HTML, JSX, or Tailwind CSS
Mobile/Tablet/Desktop preview
Live editor — preview updates as you type

About this UI Snippet

Breathing Animation — Guided Patterns, CSS scale Pulse & Phase Timer Countdown

Screenshot of the Breathing / Focus Ring snippet rendered live

A guided breathing animation is a visual tool for practicing breathing techniques that reduce anxiety, improve focus, and aid in sleep. The visual expanding and contracting circle guides the user through each phase — inhale, hold, exhale — in sync with a countdown timer, so the user can follow along without counting mentally. This snippet implements three clinically recognised breathing patterns using data-driven animation: box breathing (4-4), the 4-7-8 technique, and equal breathing (5-5).

How the breathing pattern data structure works

Each breathing pattern is stored as an array of { label, dur } phase objects in the patterns object. The 4-4 pattern has two phases: [{label:'Breathe in', dur:4}, {label:'Breathe out', dur:4}]. The 4-7-8 pattern adds a hold phase: inhale 4s, hold 7s, exhale 8s. The 5-5 pattern is simple equal breathing: in 5s, out 5s. The setPattern(key) function resets to the first phase and duration when the user switches patterns.

The CSS animation tied to breathing phases

Four .ring divs of increasing size and decreasing opacity create the layered glow rings around the central core. All rings share the same @keyframes breathe animation: 0%,100% { transform: scale(0.8); opacity: 0.7 } to 50% { transform: scale(1.1); opacity: 1 }. The animation duration is dynamically set in updateUI() via r.style.animationDuration = dur, where dur = (pat[phase].dur * 2) + 's' — doubling the phase duration makes the animation complete exactly one full scale cycle per inhale-exhale pair.

Hold state pausing

During a hold phase, r.style.animationPlayState = 'paused' freezes the rings at their current scale position, visually communicating "stay expanded" during the hold. On inhale and exhale phases, animationPlayState is set back to 'running'.

The phase countdown timer

setInterval(tick, 1000) decrements remaining each second. When it reaches zero, the phase index increments (wrapping via modulo) and remaining resets to the new phase's duration. The updateUI() function then updates both the label text and countdown number displayed inside the core element.

Pause and resume controls

The toggle() function pauses and resumes the session by clearing or restarting the setInterval and toggling the ring's animationPlayState. This lets users pause mid-session if interrupted without losing their place in the pattern.

Step by step

How to Use

  1. 1
    Observe the breathing animation running by defaultThe animation starts automatically on the 4-4 box breathing pattern. Watch the layered rings expand during the Breathe in phase (countdown 4,3,2,1) and contract during the Breathe out phase. The Pause button lets you stop mid-session.
  2. 2
    Switch between breathing patterns using the dropdownUse the dropdown selector to change patterns: 4-4 Box Breathing for general stress relief, 4-7-8 (longer exhale, clinically studied for anxiety reduction), and 5-5 Equal Breathing for balanced calm. The animation duration and phase labels update immediately on change.
  3. 3
    Add a custom breathing pattern to the patterns objectIn the JS panel, add a new key to the patterns object: "6-2-6": [{label:"Breathe in",dur:6},{label:"Hold",dur:2},{label:"Breathe out",dur:6}]. Then add a matching option in the HTML select element: <option value="6-2-6">6-2-6 Extended</option>.
  4. 4
    Change the ring colours and glow to match your app themeIn the CSS panel, update the rgba(99,102,241,...) values in .r1 through .r4 backgrounds to your accent colour. Adjust the blur() values to control the softness of the outer glow rings. The inner .r1 has no blur for a sharp center, while .r4 has blur(8px) for the outermost ambient glow.
  5. 5
    Add a session duration limiterTrack completed cycles in a counter variable. After N cycles (e.g. 5 complete breath cycles), call the toggle() function to stop the session and show a completion message. Each cycle is one full pass through all phases in the pattern array.
  6. 6
    Export as a standalone breathing exercise page or React componentClick HTML for a self-contained breathing exercise page, JSX for a React component managing phase state and animation via useEffect and useState, or Tailwind for a styled React version ready for integration into a wellness or productivity application.

Real-world uses

Common Use Cases

Wellness and mindfulness app breathing exercises
Guided breathing is a core feature of mental wellness apps like Calm and Headspace. This component provides the visual breathing guide that users follow for stress management, anxiety relief, and daily mindfulness practice. The three built-in patterns cover the most common medically recommended techniques, and custom patterns are trivially added to the data structure.
Anxiety and panic attack reduction tools
The 4-7-8 technique — inhale 4 seconds, hold 7, exhale 8 — is one of the most widely studied breathing interventions for acute anxiety. The animated circle makes the timing automatic, so users in a stressed state don't have to count manually. Pair with calming background audio and a low-stimulation dark colour scheme for maximum effectiveness in a crisis-support app.
Pre-meditation and focus session starters
Use the breathing animation as a mandatory pre-session step before entering a meditation, a focus timer like the Pomodoro countdown or Pomodoro widget, or a deep work session. A 60-second breathing exercise (two complete 4-4 cycles) primes the nervous system for focused work. The component's pause and pattern-switch controls let users customise the warm-up to their preference before committing to a longer session.
Learn CSS animation duration control via inline styles
The animation duration for each ring is set dynamically via element.style.animationDuration = dur where dur is derived from the current phase object. This overrides the CSS-declared animation duration at runtime, demonstrating how inline styles cascade above class-based styles. Edit the duration calculation in the JS panel to see how different values affect the expand/contract speed relative to the countdown.
Workout and fitness app post-exercise recovery
Show a breathing guide during the rest periods between workout sets or immediately after high-intensity exercise. Controlled breathing (specifically box breathing) accelerates heart rate recovery by activating the parasympathetic nervous system. The compact visual fits naturally in a rest timer screen alongside a countdown to the next set.
High-stakes form onboarding and checkout anxiety reduction
Insert a brief optional breathing prompt before high-stakes user actions: completing a large purchase, submitting an important multi-step form, or publishing content for the first time. Reducing pre-action anxiety decreases form abandonment and increases completion confidence. The prompt can be dismissed immediately but provides a genuine UX benefit for anxious users.
Related: Cascading Dependency Skeleton Loader — Parent Then Children, Honestly
See the Cascading Dependency Skeleton Loader — Parent Then Children, Honestly for a related loaders pattern worth pairing with this one.
Related: Route Tracking Progress Loader
See the Route Tracking Progress Loader for a related loaders pattern worth pairing with this one.
Related: Code Editor Skeleton Loader
See the Code Editor Skeleton Loader for a related loaders pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

Each pattern is an array of { label, dur } phase objects stored in the patterns object. When a pattern is selected via setPattern(key), the pat variable is set to the pattern array and phase resets to 0. The setInterval(tick, 1000) decrements the remaining counter each second. When remaining reaches zero, phase increments by 1 and wraps back to 0 via modulo when it reaches pat.length. The updateUI() function then reads pat[phase].dur to set the new remaining countdown and pat[phase].label to update the instruction text. The animation duration is set as (pat[phase].dur * 2) + 's' — doubling the phase duration aligns the CSS scale animation peak with the midpoint of the breathe-in duration.

The @keyframes breathe animation is applied in CSS with a static duration. In updateUI(), the duration is overridden at runtime using element.style.animationDuration = dur where dur equals the doubled phase duration as a string like '8s'. Inline styles in CSS cascade above class-based declarations, so this override takes effect immediately without removing or re-adding the animation class. Setting animationPlayState to 'paused' during hold phases freezes the rings at their peak scale, visually communicating the hold state.

Add a new entry to the patterns object: patterns['6-2-6'] = [{label:'Breathe in',dur:6},{label:'Hold',dur:2},{label:'Breathe out',dur:6}]. Then add a matching option in the HTML select element: <option value='6-2-6'>6-2-6 Extended</option>. The setPattern() function reads the select value and looks up the pattern by key, so no other JS changes are needed. You can also add entirely new phase labels — any string works as the label.

Use the Web Audio API to generate a brief tone at each phase transition. In updateUI(), create a tone when the phase changes: const ctx = new (window.AudioContext || window.webkitAudioContext)(); const osc = ctx.createOscillator(); const gain = ctx.createGain(); osc.connect(gain); gain.connect(ctx.destination); osc.frequency.value = pat[phase].label.includes('in') ? 440 : pat[phase].label.includes('Hold') ? 528 : 220; gain.gain.setValueAtTime(0.1, ctx.currentTime); gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.3); osc.start(ctx.currentTime); osc.stop(ctx.currentTime + 0.3). Different frequencies for each phase provide distinct audio cues: high for inhale, mid for hold, low for exhale.