Optimize your training by calculating precise heart rate zones based on the Karvonen formula.
Karvonen (Includes Resting HR)
Peak Power (% of Max HR)
Your Personalized Cycling Zones
Zone
Intensity
Range (BPM)
How to Use This Heart Rate Zone Calculator for Cycling
Training with heart rate zones allows cyclists to ensure they are riding at the correct intensity to achieve specific physiological adaptations. This calculator uses the Karvonen Formula, which is widely considered more accurate than simple percentages because it accounts for your Heart Rate Reserve (HRR)—the difference between your maximum heart rate and your resting heart rate.
Understanding the 5 Cycling Intensity Zones
Zone 1 (Recovery): Used for active recovery after hard efforts. It improves blood flow without adding fatigue.
Zone 2 (Endurance/Base): The "bread and butter" of cycling training. This builds aerobic capacity and teaches the body to burn fat efficiently.
Zone 3 (Tempo): A moderate intensity used for building aerobic power. It's the "comfortably hard" pace often used in long climbs.
Zone 4 (Lactate Threshold): The point where lactate begins to accumulate in the blood faster than it can be removed. Training here increases your "FTP" (Functional Threshold Power).
Zone 5 (VO2 Max): Short, high-intensity intervals that improve your maximum oxygen consumption and top-end speed.
Example Calculation
If a 40-year-old cyclist has a resting heart rate of 60 BPM:
Instead of just riding "fast," this cyclist knows that staying between 132 and 144 BPM will provide the maximum endurance benefit without overtraining.
function updateMaxHR() {
var age = document.getElementById("cyclingAge").value;
if (age && age > 0) {
document.getElementById("maxHR").value = 220 – age;
}
}
function calculateCyclingZones() {
var age = parseFloat(document.getElementById("cyclingAge").value);
var mhr = parseFloat(document.getElementById("maxHR").value);
var rhr = parseFloat(document.getElementById("restingHR").value);
var method = document.getElementById("methodSelect").value;
var resultArea = document.getElementById("cyclingResultArea");
var tableBody = document.getElementById("cyclingTableBody");
var summary = document.getElementById("summaryText");
if (!mhr || mhr <= 0) {
alert("Please enter a valid Maximum Heart Rate.");
return;
}
if (method === "karvonen" && (!rhr || rhr <= 0)) {
alert("Resting Heart Rate is required for the Karvonen method.");
return;
}
var hrr = mhr – rhr;
var zones = [
{ name: "Zone 1 (Recovery)", min: 0.50, max: 0.60, class: "zone-1" },
{ name: "Zone 2 (Endurance)", min: 0.60, max: 0.70, class: "zone-2" },
{ name: "Zone 3 (Tempo)", min: 0.70, max: 0.80, class: "zone-3" },
{ name: "Zone 4 (Threshold)", min: 0.80, max: 0.90, class: "zone-4" },
{ name: "Zone 5 (VO2 Max)", min: 0.90, max: 1.00, class: "zone-5" }
];
var html = "";
for (var i = 0; i < zones.length; i++) {
var z = zones[i];
var minBpm, maxBpm;
if (method === "karvonen") {
minBpm = Math.round((hrr * z.min) + rhr);
maxBpm = Math.round((hrr * z.max) + rhr);
} else {
minBpm = Math.round(mhr * z.min);
maxBpm = Math.round(mhr * z.max);
}
html += "
";
html += "
" + z.name + "
";
html += "
" + (z.min * 100) + "% – " + (z.max * 100) + "%
";
html += "
" + minBpm + " – " + maxBpm + " BPM
";
html += "
";
}
summary.innerHTML = "Based on a Max HR of " + mhr + " BPM" +
(method === "karvonen" ? " and a Resting HR of " + rhr + " BPM." : ".");
tableBody.innerHTML = html;
resultArea.style.display = "block";
}