#Foundation Progress Bars
Foundation progress bars are used to display the progress of task completion or status. This chapter will introduce various uses of Foundation progress bars.
#Basic Progress Bar
Use .progress and .progress-meter to create basic progress bars:
<div class="progress" role="progressbar" tabindex="0" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100">
<div class="progress-meter" style="width: 50%"></div>
</div>#Different Progress Values
<div class="progress">
<div class="progress-meter" style="width: 0%"></div>
</div>
<div class="progress">
<div class="progress-meter" style="width: 25%"></div>
</div>
<div class="progress">
<div class="progress-meter" style="width: 50%"></div>
</div>
<div class="progress">
<div class="progress-meter" style="width: 75%"></div>
</div>
<div class="progress">
<div class="progress-meter" style="width: 100%"></div>
</div>#Progress Bar Colors
Foundation provides multiple color options:
<div class="progress primary">
<div class="progress-meter" style="width: 50%"></div>
</div>
<div class="progress secondary">
<div class="progress-meter" style="width: 50%"></div>
</div>
<div class="progress success">
<div class="progress-meter" style="width: 50%"></div>
</div>
<div class="progress warning">
<div class="progress-meter" style="width: 50%"></div>
</div>
<div class="progress alert">
<div class="progress-meter" style="width: 50%"></div>
</div>#Color Usage Guide
| Class | Color | Common Use |
|---|---|---|
.primary | Blue | Default progress |
.secondary | Gray | Secondary progress |
.success | Green | Success/Complete |
.warning | Yellow | Warning/Attention |
.alert | Red | Danger/Error |
#Progress Bars with Text
Display text inside the progress bar:
<div class="progress" role="progressbar" tabindex="0">
<span class="progress-meter" style="width: 50%">
<p class="progress-meter-text">50%</p>
</span>
</div>#Text at Different Positions
<style>
.progress-with-label {
position: relative;
}
.progress-label {
position: absolute;
width: 100%;
text-align: center;
line-height: 1rem;
color: #333;
font-size: 0.75rem;
font-weight: bold;
}
</style>
<div class="progress progress-with-label">
<span class="progress-meter success" style="width: 75%"></span>
<span class="progress-label">75% Complete</span>
</div>#Native HTML5 Progress Bar
Foundation also supports native <progress> elements:
<progress max="100" value="75"></progress>#Styling Native Progress Bars
<style>
progress {
width: 100%;
height: 1rem;
-webkit-appearance: none;
appearance: none;
}
progress::-webkit-progress-bar {
background-color: #e6e6e6;
border-radius: 0;
}
progress::-webkit-progress-value {
background-color: #1779ba;
}
progress::-moz-progress-bar {
background-color: #1779ba;
}
</style>
<progress max="100" value="75"></progress>#Striped Progress Bar
Add striped effect:
<style>
.progress.striped .progress-meter {
background-image: linear-gradient(
45deg,
rgba(255, 255, 255, 0.15) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, 0.15) 50%,
rgba(255, 255, 255, 0.15) 75%,
transparent 75%,
transparent
);
background-size: 1rem 1rem;
}
</style>
<div class="progress primary striped">
<div class="progress-meter" style="width: 60%"></div>
</div>#Animated Progress Bar
Add animation effect:
<style>
.progress.animated .progress-meter {
animation: progress-bar-stripes 1s linear infinite;
background-image: linear-gradient(
45deg,
rgba(255, 255, 255, 0.15) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, 0.15) 50%,
rgba(255, 255, 255, 0.15) 75%,
transparent 75%,
transparent
);
background-size: 1rem 1rem;
}
@keyframes progress-bar-stripes {
from { background-position: 1rem 0; }
to { background-position: 0 0; }
}
</style>
<div class="progress success animated">
<div class="progress-meter" style="width: 75%"></div>
</div>#Progress Bar Height
Customize progress bar height:
<style>
.progress.thin { height: 0.5rem; }
.progress.thick { height: 1.5rem; }
.progress.extra-thick { height: 2rem; }
</style>
<div class="progress thin primary">
<div class="progress-meter" style="width: 50%"></div>
</div>
<div class="progress primary">
<div class="progress-meter" style="width: 50%"></div>
</div>
<div class="progress thick primary">
<div class="progress-meter" style="width: 50%"></div>
</div>
<div class="progress extra-thick primary">
<div class="progress-meter" style="width: 50%"></div>
</div>#Stacked Progress Bar
Display multiple values in one progress bar:
<style>
.progress-stacked {
display: flex;
background-color: #e6e6e6;
border-radius: 0;
height: 1.5rem;
}
.progress-stacked .progress-segment {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 0.75rem;
}
</style>
<div class="progress-stacked">
<div class="progress-segment" style="width: 30%; background: #3adb76;">Completed 30%</div>
<div class="progress-segment" style="width: 20%; background: #1779ba;">In Progress 20%</div>
<div class="progress-segment" style="width: 15%; background: #ffae00;">Pending 15%</div>
</div>#Circular Progress Bar
Use SVG to create circular progress bars:
<style>
.circular-progress {
width: 100px;
height: 100px;
position: relative;
}
.circular-progress svg {
transform: rotate(-90deg);
}
.circular-progress .bg {
fill: none;
stroke: #e6e6e6;
stroke-width: 8;
}
.circular-progress .meter {
fill: none;
stroke: #1779ba;
stroke-width: 8;
stroke-linecap: round;
stroke-dasharray: 283;
stroke-dashoffset: calc(283 - (283 * var(--progress)) / 100);
transition: stroke-dashoffset 0.5s ease;
}
.circular-progress .value {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 1.25rem;
font-weight: bold;
}
</style>
<div class="circular-progress" style="--progress: 75">
<svg width="100" height="100">
<circle class="bg" cx="50" cy="50" r="45"></circle>
<circle class="meter" cx="50" cy="50" r="45"></circle>
</svg>
<span class="value">75%</span>
</div>#Progress Bars with Labels
Combine with labels to display status:
<div class="grid-x grid-margin-x">
<div class="cell small-10">
<div class="progress success">
<div class="progress-meter" style="width: 100%"></div>
</div>
</div>
<div class="cell small-2">
<span class="label success">Complete</span>
</div>
</div>
<div class="grid-x grid-margin-x">
<div class="cell small-10">
<div class="progress warning">
<div class="progress-meter" style="width: 60%"></div>
</div>
</div>
<div class="cell small-2">
<span class="label warning">60%</span>
</div>
</div>
<div class="grid-x grid-margin-x">
<div class="cell small-10">
<div class="progress alert">
<div class="progress-meter" style="width: 25%"></div>
</div>
</div>
<div class="cell small-2">
<span class="label alert">25%</span>
</div>
</div>#JavaScript Dynamic Update
#Basic Update
function updateProgress(element, value) {
var meter = element.querySelector('.progress-meter');
meter.style.width = value + '%';
// Update ARIA attributes
element.setAttribute('aria-valuenow', value);
// If there's text, update it
var text = meter.querySelector('.progress-meter-text');
if (text) {
text.textContent = value + '%';
}
}
// Usage
var progressBar = document.querySelector('.progress');
updateProgress(progressBar, 75);#Simulating Loading Progress
function simulateProgress(element, duration) {
var meter = element.querySelector('.progress-meter');
var start = 0;
var end = 100;
var startTime = null;
function animate(currentTime) {
if (!startTime) startTime = currentTime;
var elapsed = currentTime - startTime;
var progress = Math.min((elapsed / duration) * end, end);
meter.style.width = progress + '%';
element.setAttribute('aria-valuenow', Math.round(progress));
if (progress < end) {
requestAnimationFrame(animate);
}
}
requestAnimationFrame(animate);
}
// Complete within 5 seconds
simulateProgress(document.querySelector('.progress'), 5000);#Complete Example
<!DOCTYPE html>
<html class="no-js" lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Foundation Progress Bars Example</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/foundation-sites@6.7.5/dist/css/foundation.min.css">
<style>
.demo-section {
margin-bottom: 30px;
}
.demo-section h3 {
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 1px solid #ddd;
}
.progress { margin-bottom: 10px; }
.progress.thin { height: 0.5rem; }
.progress.thick { height: 1.5rem; }
.progress.striped .progress-meter,
.progress.animated .progress-meter {
background-image: linear-gradient(
45deg,
rgba(255, 255, 255, 0.15) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, 0.15) 50%,
rgba(255, 255, 255, 0.15) 75%,
transparent 75%,
transparent
);
background-size: 1rem 1rem;
}
.progress.animated .progress-meter {
animation: progress-bar-stripes 1s linear infinite;
}
@keyframes progress-bar-stripes {
from { background-position: 1rem 0; }
to { background-position: 0 0; }
}
.progress-stacked {
display: flex;
background-color: #e6e6e6;
height: 1.5rem;
margin-bottom: 10px;
}
.progress-stacked .progress-segment {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 0.75rem;
}
.progress-with-label {
position: relative;
}
.progress-label {
position: absolute;
width: 100%;
text-align: center;
line-height: 1rem;
color: #fff;
font-size: 0.75rem;
font-weight: bold;
top: 0;
}
.circular-progress {
width: 100px;
height: 100px;
position: relative;
display: inline-block;
margin: 10px;
}
.circular-progress svg { transform: rotate(-90deg); }
.circular-progress .bg {
fill: none;
stroke: #e6e6e6;
stroke-width: 8;
}
.circular-progress .meter {
fill: none;
stroke-width: 8;
stroke-linecap: round;
stroke-dasharray: 283;
stroke-dashoffset: calc(283 - (283 * var(--progress)) / 100);
transition: stroke-dashoffset 0.5s ease;
}
.circular-progress .value {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 1.25rem;
font-weight: bold;
}
</style>
</head>
<body>
<div class="grid-container">
<h1>Foundation Progress Bars Showcase</h1>
<div class="demo-section">
<h3>Basic Progress Bars</h3>
<div class="progress">
<div class="progress-meter" style="width: 25%"></div>
</div>
<div class="progress">
<div class="progress-meter" style="width: 50%"></div>
</div>
<div class="progress">
<div class="progress-meter" style="width: 75%"></div>
</div>
<div class="progress">
<div class="progress-meter" style="width: 100%"></div>
</div>
</div>
<div class="demo-section">
<h3>Different Colors</h3>
<div class="progress primary">
<div class="progress-meter" style="width: 60%"></div>
</div>
<div class="progress secondary">
<div class="progress-meter" style="width: 60%"></div>
</div>
<div class="progress success">
<div class="progress-meter" style="width: 60%"></div>
</div>
<div class="progress warning">
<div class="progress-meter" style="width: 60%"></div>
</div>
<div class="progress alert">
<div class="progress-meter" style="width: 60%"></div>
</div>
</div>
<div class="demo-section">
<h3>Progress Bars with Text</h3>
<div class="progress thick primary progress-with-label">
<span class="progress-meter" style="width: 65%"></span>
<span class="progress-label">65% Complete</span>
</div>
</div>
<div class="demo-section">
<h3>Different Heights</h3>
<p>Thin:</p>
<div class="progress thin primary">
<div class="progress-meter" style="width: 50%"></div>
</div>
<p>Default:</p>
<div class="progress primary">
<div class="progress-meter" style="width: 50%"></div>
</div>
<p>Thick:</p>
<div class="progress thick primary">
<div class="progress-meter" style="width: 50%"></div>
</div>
</div>
<div class="demo-section">
<h3>Striped Progress Bars</h3>
<div class="progress primary striped">
<div class="progress-meter" style="width: 60%"></div>
</div>
<div class="progress success striped">
<div class="progress-meter" style="width: 60%"></div>
</div>
</div>
<div class="demo-section">
<h3>Animated Progress Bars</h3>
<div class="progress primary animated">
<div class="progress-meter" style="width: 75%"></div>
</div>
<div class="progress success animated">
<div class="progress-meter" style="width: 75%"></div>
</div>
</div>
<div class="demo-section">
<h3>Stacked Progress Bar</h3>
<div class="progress-stacked">
<div class="progress-segment" style="width: 35%; background: #3adb76;">Completed</div>
<div class="progress-segment" style="width: 25%; background: #1779ba;">In Progress</div>
<div class="progress-segment" style="width: 15%; background: #ffae00;">Pending</div>
</div>
</div>
<div class="demo-section">
<h3>Circular Progress Bars</h3>
<div class="circular-progress" style="--progress: 25">
<svg width="100" height="100">
<circle class="bg" cx="50" cy="50" r="45"></circle>
<circle class="meter" cx="50" cy="50" r="45" style="stroke: #cc4b37;"></circle>
</svg>
<span class="value">25%</span>
</div>
<div class="circular-progress" style="--progress: 50">
<svg width="100" height="100">
<circle class="bg" cx="50" cy="50" r="45"></circle>
<circle class="meter" cx="50" cy="50" r="45" style="stroke: #ffae00;"></circle>
</svg>
<span class="value">50%</span>
</div>
<div class="circular-progress" style="--progress: 75">
<svg width="100" height="100">
<circle class="bg" cx="50" cy="50" r="45"></circle>
<circle class="meter" cx="50" cy="50" r="45" style="stroke: #1779ba;"></circle>
</svg>
<span class="value">75%</span>
</div>
<div class="circular-progress" style="--progress: 100">
<svg width="100" height="100">
<circle class="bg" cx="50" cy="50" r="45"></circle>
<circle class="meter" cx="50" cy="50" r="45" style="stroke: #3adb76;"></circle>
</svg>
<span class="value">100%</span>
</div>
</div>
<div class="demo-section">
<h3>Dynamic Progress Bar</h3>
<div class="progress primary" id="dynamic-progress" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
<div class="progress-meter" style="width: 0%"></div>
</div>
<button class="button" onclick="startProgress()">Start Loading</button>
<button class="button secondary" onclick="resetProgress()">Reset</button>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/foundation-sites@6.7.5/dist/js/foundation.min.js"></script>
<script>
$(document).foundation();
function startProgress() {
var progress = document.getElementById('dynamic-progress');
var meter = progress.querySelector('.progress-meter');
var current = 0;
var interval = setInterval(function() {
current += Math.random() * 10;
if (current > 100) current = 100;
meter.style.width = current + '%';
progress.setAttribute('aria-valuenow', Math.round(current));
if (current >= 100) {
clearInterval(interval);
}
}, 200);
}
function resetProgress() {
var progress = document.getElementById('dynamic-progress');
var meter = progress.querySelector('.progress-meter');
meter.style.width = '0%';
progress.setAttribute('aria-valuenow', 0);
}
</script>
</body>
</html>#Progress Bar Best Practices
- Accessibility: Use
role="progressbar"and ARIA attributes - Real-time Updates: Update progress regularly for long operations
- Color Indication: Use colors to express progress status (green when close to completion)
- Text Feedback: Provide text descriptions for important progress
- Smooth Transitions: Use CSS transition for smoother progress changes
<!-- Accessible progress bar -->
<div class="progress"
role="progressbar"
tabindex="0"
aria-valuenow="75"
aria-valuemin="0"
aria-valuemax="100"
aria-label="File upload progress">
<div class="progress-meter" style="width: 75%">
<span class="progress-meter-text">75%</span>
</div>
</div>#Summary
In this chapter, we learned:
- Creating basic progress bars
- Progress bars with different colors and heights
- Progress bars with text and animation effects
- Striped and stacked progress bars
- Circular progress bars
- JavaScript dynamic progress updates
Next chapter, we will learn Foundation Panels.
Tip: Progress bars are an important part of user experience. They let users know the status of operations and reduce waiting anxiety.