Progress
<div role="progressbar">
Visual indicator of completion or usage. Use for file uploads, API quota, build steps, or any measurable operation.
Overview
Preview
Uploading thumbnails.zip40%
API quota8,540 / 10,000
Storage used23%
Processing...
Build progress
40%
Basic progress bar
Preview
Uploading65%
html
<div class="space-y-1.5">
<div class="flex justify-between text-xs">
<span class="text-zinc-400">Uploading</span>
<span class="tabular-nums text-zinc-500">65%</span>
</div>
<div
role="progressbar"
aria-valuenow="65"
aria-valuemin="0"
aria-valuemax="100"
class="h-1.5 w-full overflow-hidden rounded-full bg-zinc-800"
>
<div
class="h-full rounded-full bg-gradient-to-r from-[#D40C37] to-[#e8103f] transition-all duration-300"
style="width: 65%"
></div>
</div>
</div>Colour variants
Preview
html
<!-- Brand / danger (>80%) -->
<div class="h-full rounded-full bg-gradient-to-r from-[#D40C37] to-[#e8103f]" style="width: 85%"></div>
<!-- Warning (50–80%) -->
<div class="h-full rounded-full bg-amber-500" style="width: 60%"></div>
<!-- Success / healthy (<50%) -->
<div class="h-full rounded-full bg-emerald-500" style="width: 30%"></div>Sizes
html
<div class="h-1 w-full overflow-hidden rounded-full bg-zinc-800"><div class="h-full rounded-full bg-[#D40C37]" style="width:65%"></div></div>
<div class="h-1.5 w-full overflow-hidden rounded-full bg-zinc-800"><div class="h-full rounded-full bg-[#D40C37]" style="width:65%"></div></div>
<div class="h-2 w-full overflow-hidden rounded-full bg-zinc-800"><div class="h-full rounded-full bg-[#D40C37]" style="width:65%"></div></div>
<div class="h-3 w-full overflow-hidden rounded-full bg-zinc-800"><div class="h-full rounded-full bg-[#D40C37]" style="width:65%"></div></div>Thick bar with label inside
Preview
72%
html
<div class="h-5 w-full overflow-hidden rounded-full bg-zinc-800 relative">
<div class="h-full rounded-full bg-[#D40C37]/80 flex items-center justify-end pr-2" style="width: 72%">
<span class="text-[9px] font-bold text-white tabular-nums">72%</span>
</div>
</div>Indeterminate / animated
Preview
html
<div class="h-1.5 w-full overflow-hidden rounded-full bg-zinc-800 relative">
<div class="absolute h-full w-1/2 rounded-full bg-[#D40C37] animate-[indeterminate_1.5s_ease-in-out_infinite]"></div>
</div>Add to tailwind.config.js:
js
theme: {
extend: {
keyframes: {
indeterminate: {
'0%': { transform: 'translateX(-100%)' },
'100%': { transform: 'translateX(300%)' },
},
},
},
},With Vue reactivity
vue
<script setup>
import { ref } from 'vue'
const progress = ref(0)
// Simulate upload
function startUpload() {
const interval = setInterval(() => {
progress.value = Math.min(100, progress.value + 5)
if (progress.value >= 100) clearInterval(interval)
}, 200)
}
</script>
<template>
<div>
<div class="h-1.5 w-full overflow-hidden rounded-full bg-zinc-800">
<div
class="h-full rounded-full bg-[#D40C37] transition-all duration-300"
:style="{ width: progress + '%' }"
role="progressbar"
:aria-valuenow="progress"
aria-valuemin="0"
aria-valuemax="100"
></div>
</div>
<button @click="startUpload" class="mt-3 ...">Start upload</button>
</div>
</template>Accessibility notes
- Use
role="progressbar"witharia-valuenow,aria-valuemin,aria-valuemax - For indeterminate bars, omit
aria-valuenowand addaria-label="Loading" - If the progress label is not visible, add
aria-labelto the progressbar element