Calculate your training zones using your Age and Resting Heart Rate
Measure this immediately after waking up for best accuracy.
Please enter valid numbers for Age (10-100) and Resting Heart Rate (30-150).
Estimated Max HR
–
Heart Rate Reserve
–
Your Training Zones
Zone
Intensity
Heart Rate Range
Zone 1 (Recovery)
50% – 60%
–
Zone 2 (Endurance)
60% – 70%
–
Zone 3 (Aerobic)
70% – 80%
–
Zone 4 (Threshold)
80% – 90%
–
Zone 5 (Maximum)
90% – 100%
–
Why Use Resting Heart Rate for Calculations?
Calculating heart rate zones using the standard "220 minus age" formula is a good starting point, but it assumes everyone of the same age has the same cardiovascular fitness. This is often inaccurate for individuals who are very fit or just starting out.
The calculator above uses the Karvonen Formula. This method incorporates your Resting Heart Rate (RHR) into the equation. Your RHR is a strong indicator of your aerobic fitness level. By factoring this in, we calculate your Heart Rate Reserve (HRR), which provides personalized training zones that adapt as you get fitter and your resting heart rate drops.
For example, a 30-year-old with a resting heart rate of 60 bpm calculating their 70% intensity target:
Max HR: 190 bpm
HRR: 130 bpm (190 – 60)
Target: (130 × 0.70) + 60 = 151 bpm
Understanding Training Zones
Zone 1 (50-60%): Very light activity, used for warm-ups, cool-downs, and active recovery.
Zone 2 (60-70%): The "Fat Burning" zone. You should be able to hold a conversation easily. This builds basic endurance and metabolizes fat efficiently.
Zone 3 (70-80%): The Aerobic zone. Improves blood circulation and skeletal muscle strength. Breathing becomes heavier.
Zone 4 (80-90%): The Anaerobic threshold. You can only sustain this for shorter periods. This improves your ability to tolerate lactic acid.
Zone 5 (90-100%): Maximum effort. Used for interval training and sprints. Sustainable only for very short bursts.
function calculateHeartZones() {
// 1. Get Inputs
var ageInput = document.getElementById('inputAge').value;
var rhrInput = document.getElementById('inputRHR').value;
var resultsDiv = document.getElementById('resultsArea');
var errorDiv = document.getElementById('errorMessage');
// 2. Parse values
var age = parseFloat(ageInput);
var rhr = parseFloat(rhrInput);
// 3. Validation Logic
if (isNaN(age) || isNaN(rhr) || age 100 || rhr 150) {
errorDiv.style.display = 'block';
resultsDiv.style.display = 'none';
return;
}
// Hide error if valid
errorDiv.style.display = 'none';
// 4. Calculate Max HR and Heart Rate Reserve (HRR)
var maxHR = 220 – age;
var hrr = maxHR – rhr;
// Edge case: If RHR is higher than max HR (impossible physiologically for living human in context)
if (hrr <= 0) {
errorDiv.innerHTML = "Resting Heart Rate cannot be higher than Maximum Heart Rate.";
errorDiv.style.display = 'block';
resultsDiv.style.display = 'none';
return;
}
// 5. Calculate Zone Thresholds
// Formula: (HRR * percent) + RHR
// Zone 1: 50% – 60%
var z1_min = Math.round((hrr * 0.50) + rhr);
var z1_max = Math.round((hrr * 0.60) + rhr);
// Zone 2: 60% – 70%
var z2_min = z1_max + 1; // Start where previous left off +1 or just use strict calc
// Recalculating strict usually better for ranges:
z2_min = Math.round((hrr * 0.60) + rhr);
var z2_max = Math.round((hrr * 0.70) + rhr);
// Zone 3: 70% – 80%
var z3_min = Math.round((hrr * 0.70) + rhr);
var z3_max = Math.round((hrr * 0.80) + rhr);
// Zone 4: 80% – 90%
var z4_min = Math.round((hrr * 0.80) + rhr);
var z4_max = Math.round((hrr * 0.90) + rhr);
// Zone 5: 90% – 100%
var z5_min = Math.round((hrr * 0.90) + rhr);
var z5_max = maxHR;
// 6. Display Results
document.getElementById('dispMaxHR').innerText = maxHR + " bpm";
document.getElementById('dispHRR').innerText = hrr + " bpm";
document.getElementById('rowZ1').innerText = z1_min + " – " + z1_max + " bpm";
document.getElementById('rowZ2').innerText = z2_min + " – " + z2_max + " bpm";
document.getElementById('rowZ3').innerText = z3_min + " – " + z3_max + " bpm";
document.getElementById('rowZ4').innerText = z4_min + " – " + z4_max + " bpm";
document.getElementById('rowZ5').innerText = z5_min + " – " + z5_max + " bpm";
resultsDiv.style.display = 'block';
}