Heart rate zones differ slightly between running and cycling.
Enter the average HR from the last 20 minutes of a 30-minute Time Trial.
Your Training Zones
Based on an LTHR of bpm for :
Zone
Intensity
Heart Rate Range (bpm)
What is Lactate Threshold Heart Rate (LTHR)?
Lactate Threshold Heart Rate (LTHR) is one of the most effective metrics for defining endurance training zones. Unlike Max Heart Rate, which is a genetic ceiling that doesn't change much with fitness, your LTHR represents the point at which lactate begins to accumulate in the blood faster than your body can clear it. This threshold marks the transition from aerobic to anaerobic metabolism.
Knowing your LTHR allows you to train with precision. By establishing personalized heart rate zones based on your threshold, you can ensure that easy runs remain easy enough to build endurance, and interval sessions are hard enough to improve speed and power.
How to Determine Your LTHR
The most common field test for determining LTHR is the 30-minute Time Trial (TT) popularized by coach Joe Friel. To perform this test accurately:
Warm-up: 10-15 minutes of easy activity followed by a few 30-second bursts to prime your system.
The Test: Run or cycle at the maximum sustained effort you can hold for 30 minutes. It should be a steady, hard pace, not a sprint.
The Data: At the 10-minute mark of the test, press the "Lap" button on your heart rate monitor. Continue for the remaining 20 minutes.
The Result: Your average heart rate for that last 20 minutes is your estimated LTHR.
Once you have this number, enter it into the calculator above to define your specific training zones.
Running vs. Cycling Zones
It is important to note that your LTHR is generally different for running and cycling. Typically, running LTHR is 5-10 beats per minute higher than cycling LTHR due to the involvement of more muscle mass and the lack of mechanical support (the bike). This calculator adjusts the zone percentages based on the sport you select to ensure accuracy.
Understanding the Training Zones
Zone 1 (Recovery): Very low intensity, used for warming up, cooling down, or active recovery.
Zone 2 (Aerobic): The "all-day" pace. Primary zone for building base endurance and fat-burning efficiency.
Zone 3 (Tempo): "Comfortably hard." Improves aerobic capacity but can lead to fatigue if overused.
Zone 4 (Sub-Threshold): Just below your LTHR. Critical for raising your threshold.
Zone 5 (Super-Threshold/VO2 Max): Above LTHR. Short bursts of very high intensity to improve maximum output.
function calculateZones() {
// 1. Get input values
var avgHrStr = document.getElementById('avgHrInput').value;
var sport = document.getElementById('sportType').value;
var resultDiv = document.getElementById('resultsArea');
var tbody = document.getElementById('zonesTableBody');
var displayLthr = document.getElementById('displayLthr');
var displaySport = document.getElementById('displaySport');
// 2. Validate Input
if (!avgHrStr || isNaN(avgHrStr)) {
alert("Please enter a valid number for your Average Heart Rate.");
return;
}
var lthr = parseInt(avgHrStr);
// Sanity check for human heart rates
if (lthr 240) {
alert("Please enter a realistic heart rate (between 40 and 240 bpm).");
return;
}
// 3. Define Zone Percentages (Joe Friel methodology)
// Ranges are [low_percent, high_percent]
// Note: Z5c is open ended, we'll cap visualization reasonably
var zones = [];
if (sport === 'run') {
// Running Zones (Friel)
// Z1: 106%
zones = [
{ name: "Zone 1", desc: "Recovery", low: 0, high: 0.85 },
{ name: "Zone 2", desc: "Aerobic", low: 0.85, high: 0.89 },
{ name: "Zone 3", desc: "Tempo", low: 0.90, high: 0.94 },
{ name: "Zone 4", desc: "Sub-Threshold", low: 0.95, high: 0.99 },
{ name: "Zone 5a", desc: "Super-Threshold", low: 1.00, high: 1.02 },
{ name: "Zone 5b", desc: "Aerobic Capacity", low: 1.03, high: 1.06 },
{ name: "Zone 5c", desc: "Anaerobic Capacity", low: 1.07, high: 1.20 } // Cap for display
];
} else {
// Cycling Zones (Friel)
// Z1: 106%
zones = [
{ name: "Zone 1", desc: "Recovery", low: 0, high: 0.81 },
{ name: "Zone 2", desc: "Aerobic", low: 0.81, high: 0.89 },
{ name: "Zone 3", desc: "Tempo", low: 0.90, high: 0.93 },
{ name: "Zone 4", desc: "Sub-Threshold", low: 0.94, high: 0.99 },
{ name: "Zone 5a", desc: "Super-Threshold", low: 1.00, high: 1.02 },
{ name: "Zone 5b", desc: "Aerobic Capacity", low: 1.03, high: 1.06 },
{ name: "Zone 5c", desc: "Anaerobic Capacity", low: 1.07, high: 1.20 } // Cap for display
];
}
// 4. Calculate Values and Build HTML
var tableHtml = "";
for (var i = 0; i < zones.length; i++) {
var z = zones[i];
var minHr, maxHr;
// Calculate Min
if (i === 0) {
minHr = 0; // Or a practical floor like 0 or resting
} else {
// The min of this zone is usually the max of previous + 1,
// but strictly following percentages:
minHr = Math.round(lthr * z.low);
}
// Calculate Max
if (i === zones.length – 1) {
maxHr = "Max"; // Open ended
} else {
maxHr = Math.round(lthr * z.high);
}
// Format range string
var rangeStr = "";
if (i === 0) {
rangeStr = " " + Math.round(lthr * z.low);
} else {
rangeStr = minHr + " – " + maxHr;
}
tableHtml += "