Styliser la balise progress

Styliser la balise progress

Publié par Fabrice le 22 octobre 2026 - Temps de lecture estimé : 16 minutes
Catégories : Webmastering
Étiquettes :

Petits exercices de style sur la balise progress, couplés aux nouveautés CSS (dont certaines ne sont pas encore utilisables en production).

La personnalisation de la balise progress nécessite l'utilisation de pseudo-éléments dédiés :

  • ::-moz-progress-bar : la barre de progression pour Firefox
  • ::-webkit-progress-value : la barre de progression pour Webkit (Chrome, Safari, Edge et Opera)
  • ::-webkit-progress-bar : la barre de fond pour Webkit (Chrome, Safari, Edge et Opera)
  • La barre de fond sous Firefox se définit avec background-color directement sur l'élément progress

Le reset

Les coins arrondis (si nécessaire) avec border-radius doivent être définis à quatre endroits !


/* Reset for progress */
progress {	
	-webkit-appearance: none;
	appearance: none; 
	border: none;
	vertical-align: baseline;
	width: 100%;
	background-color: #ccc; /* Empty background for Firefox */
	border-radius: 1ch;
}
/* Empty background and radius (Chrome, Safari, Edge, Opera) */
progress::-webkit-progress-bar {
	background-color: #ccc;
	border-radius: 1ch;
}
progress::-webkit-progress-value {
	border-radius: 1ch;
}
/* Radius (Firefox) */
progress::-moz-progress-bar {
	border-radius: 1ch;
}

La base : une couleur

Dans de nombreux cas, cette solution est suffisante et facile à mettre en œuvre : la valeur et son maximum.


<p><progress max="100" value="33"></progress></p>

L'ajout de la couleur de la barre de progression en CSS avec deux pseudo-éléments :


progress[value]::-moz-progress-bar { background-color: #4863A0; }
progress[value]::-webkit-progress-value { background-color: #4863A0; }

Plusieurs couleurs de fond gérées avec des classes

Cette fois, il s'agit d'appliquer différentes couleurs en fonction du niveau d'avancement via l'ajout d'une classe - possiblement gérée via JavaScript.


<p><progress class="s0" max="4" value="0"></progress></p>
<p><progress class="s1" max="4" value="1"></progress></p>
<p><progress class="s2" max="4" value="2"></progress></p>
<p><progress class="s3" max="4" value="3"></progress></p>
<p><progress class="s4" max="4" value="4"></progress></p>

Le code CSS, lui commence à s'alourdir : 8 lignes pour 4 couleurs.


progress[value].s1::-moz-progress-bar { background-color: #c73754; }
progress[value].s1::-webkit-progress-value { background-color: #c73754; }
progress[value].s2::-moz-progress-bar { background-color: #dabc19; }
progress[value].s2::-webkit-progress-value { background-color: #dabc19; }
progress[value].s3::-moz-progress-bar { background-color: #4e6fac; }
progress[value].s3::-webkit-progress-value { background-color: #4e6fac; }
progress[value].s4::-moz-progress-bar { background-color: #326e4c; }
progress[value].s4::-webkit-progress-value { background-color: #326e4c; }

Plusieurs couleurs de fond gérées avec value

Même principe que précédemment, mais en utilisant l'attribut value - cela nécessite d'avoir des paliers connus à l'avance et pas trop nombreux !


<p><progress max="100" value="0"></progress></p>
<p><progress max="100" value="25"></progress></p>
<p><progress max="100" value="50"></progress></p>
<p><progress max="100" value="75"></progress></p>
<p><progress max="100" value="100"></progress></p>

Les valeurs sont directement gérées en CSS.


progress[value="25"]::-moz-progress-bar { background-color: #c73754; }
progress[value="25"]::-webkit-progress-value { background-color: #c73754; }
progress[value="50"]::-moz-progress-bar { background-color: #dabc19; }
progress[value="50"]::-webkit-progress-value { background-color: #dabc19; }
progress[value="75"]::-moz-progress-bar { background-color: #4e6fac; }
progress[value="75"]::-webkit-progress-value { background-color: #4e6fac; }
progress[value="100"]::-moz-progress-bar { background-color: #326e4c; }
progress[value="100"]::-webkit-progress-value { background-color: #326e4c; }

Couleur qui change selon la valeur avec attr and @container style()

[expérimentale] solution non compatible avec Safari et les navigateurs mobiles - 2026/10

Le code HTML reste très simple


<p><progress max="100" value="0"></progress></p>
<p><progress max="100" value="17.5"></progress></p>
<p><progress max="100" value="45"></progress></p>
<p><progress max="100" value="70"></progress></p>
<p><progress max="100" value="100"></progress></p>

Cette fois la gestion de la couleur est automatique et varie en fonction de paliers (dans l'exemple 25, 50 et 75) - le tout en mixant attr pour récupérer la valeur via une variable, @container style() et un opérateur de comparaison pour les paliers.


progress[value] {
	--value: attr(value type(<number>), 1);
} 
progress[value]::-moz-progress-bar {
	background-color: #326e4c;
	@container style(--value < 75) {background-color: #4e6fac;}
	@container style(--value < 50) {background-color: #dabc19;}
	@container style(--value < 25) {background-color: #c73754;}
}
progress[value]::-webkit-progress-value {
	background-color: #326e4c;
	@container style(--value < 75) {background-color: #4e6fac;}
	@container style(--value < 50) {background-color: #dabc19;}
	@container style(--value < 25) {background-color: #c73754;}
}

Avec affichage de la valeur sur la barre de progression

[expérimentale] solution non compatible avec Safari et les navigateurs mobiles - 2026/10

Balise progress avec affichage de la valeur sur la barre de progression

Ce serait bien de compliquer un peu les choses : et si on affichait la valeur sur la barre de progression en ajoutant quelques contraintes. Elle s'affiche à gauche et en noir pour les petites valeurs, à droite et en blanc pour les grandes valeurs.

Dans ce cas de figure, la véritable astreinte réside dans le fait qu'une variable ne peut se transmettre à un élément adjacent. Il est donc nécessaire d'ajouter un attribut data- à l'élément parent, en l'occurrence le paragraphe.


<p data-percent="0"><progress max="100" value="0"></progress><span>0 %</span></p>
<p data-percent="2.5"><progress max="100" value="2.5"></progress><span>2.5 %</span></p>
<p data-percent="4"><progress max="100" value="4"></progress><span>4 %</span></p>
[...]
<p data-percent="70"><progress max="100" value="70"></progress><span>70 %</span></p>
<p data-percent="96"><progress max="100" value="96"></progress><span>96 %</span></p>
<p data-percent="100"><progress max="100" value="100"></progress><span>100 %</span></p>

La surimpression de la valeur sur la barre de progression est réalisée avec grid stack. Pour la couleur de la barre de progression, le principe est le même que pour l'exemple précédent. La couleur et la position de la valeur, elles, sont gérées d'abord avec une valeur par défaut, puis par un @container style() et un opérateur de comparaison pour les plus petites valeurs.


p {
	display: grid;
	grid: 1fr / 1fr;
	--percent: attr(data-percent type(<number>), 1);
}
p > * {
	grid-area: 1 / 1;
	align-self: center;
	font-weight: 600;
	font-size: 1.2em;
}
span {		
	color: #fff;
	padding-left: calc((var(--percent) * 1%) - 7ch);
	@container style(--percent < 10) {
		padding-left: 1ch;
	}
	@container style(--percent < 7) {
		color: #000;
		padding-left: 5ch;
	}
	@container style(--percent = 0) {
		padding-left: 1ch;
	}
}
progress[value]::-moz-progress-bar {
	background-color: #326e4c;
	@container style(--value < 75) {background-color: #4e6fac;}
	@container style(--value < 50) {background-color: #dabc19;}
	@container style(--value < 25) {background-color: #c73754;}
}
progress[value]::-webkit-progress-value {
	background-color: #326e4c;
	@container style(--value < 75) {background-color: #4e6fac;}
	@container style(--value < 50) {background-color: #dabc19;}
	@container style(--value < 25) {background-color: #c73754;}
}

Avec affichage de la valeur en utilisant la fonction CSS if

[expérimentale] solution non compatible avec Safari, Firefox et les navigateurs mobiles - 2026/10

Le code HTML est identique à l'exemple précédent.

Au lieu de @container style(), il existe une autre solution, mais avec un support encore plus faible actuellement : la fonction if - les CSS s'approchant alors d'un véritable langage de programmation !


p {
	display: grid;
	grid: 1fr / 1fr;
	--percent: attr(data-percent type(<number>), 1);
}
p > * {
	grid-area: 1 / 1;
	align-self: center;
	font-weight: 600;
	font-size: 1.2em;
}
span {		
	padding-left: if(
		style(--percent = 0): 1ch;
		style(--percent < 7): 5ch;
		style(--percent < 10): 1ch;
		else: calc((var(--percent) * 1%) - 7ch);
	);
	color: if(
		style(--percent < 7): #000;
		else: #fff;
	);
}
/* Fallback - Firefox does not support if else */
progress[value]::-moz-progress-bar {
	background-color: #326e4c;
	@container style(--value < 75) {background-color: #4e6fac;}
	@container style(--value < 50) {background-color: #dabc19;}
	@container style(--value < 25) {background-color: #c73754;}
}
progress[value]::-webkit-progress-value {
	background-color: if(
		style(--percent < 25): #c73754;
		style(--percent < 50): #dabc19;
		style(--percent < 75): #4e6fac;
		else: #326e4c;
	);
}

Voir les démos sur CodePen

Conclusion

La balise progress reste souvent sous-utilisée, sans doute à cause d'une personnalisation encore assez complexe, excepté pour le premier exemple. Mais ce travail reste un excellent exercice pour comprendre les nouveautés de CSS : @container style(), opérateurs de comparaison et fonction if, qui, même si elles sont encore loin d'être utilisables en production, préfigurent le futur de la feuille de style, à savoir une complexité accrue et une approche de type langage de programmation.