Le 20 août 2026, j'ai découvert que le bouton d'achat de ma page de vente était invisible. Pas cassé : invisible. Le libellé s'affichait en doré, sur un fond doré.
Quatre de mes automatisations envoyaient les gens vers cette page. Ils cliquaient, ils arrivaient, ils voyaient un rectangle jaune sans un mot dessus. Je ne sais toujours pas depuis combien de temps.
Le code était juste. Le navigateur n'a rien signalé. Aucun outil ne plante quand un texte devient illisible — c'est la classe de bug la plus coûteuse : celle qui ne crie pas.
Deux règles CSS visaient le même élément :
.content-block a { color: var(--gold); } /* spécificité 0,1,1 */
.source-cta { color: #000; } /* spécificité 0,1,0 */
Instinctivement on lit la seconde comme « plus précise » : elle cible une classe unique, faite pour ce bouton. C'est le contraire. Le navigateur ne juge pas l'intention, il compte.
Trois nombres, lus de gauche à droite comme un score. Le premier qui diffère tranche, quel que soit l'ordre dans le fichier.
| Position | Ce qu'on compte | Exemple |
|---|---|---|
| 1 — identifiants | chaque #id | #panier → 1,0,0 |
| 2 — classes | classes, attributs, pseudo-classes | .source-cta → 0,1,0 |
| 3 — éléments | balises et pseudo-éléments | a, ::after → 0,0,1 |
.content-block a vaut 0,1,1 — une classe et une balise. .source-cta vaut 0,1,0. Égalité sur les classes, puis 1 contre 0 sur les éléments. La première gagne, et le bouton hérite de la couleur des liens.
Le réflexe est !important. Il marche, et il rend la feuille de style impossible à débugger la fois suivante : la prochaine exception devra surenchérir.
Requalifier la classe par son contexte suffit :
.content-block a.source-cta { color: #000; } /* 0,2,1 — deux classes, une balise */
Deux classes contre une : la règle reprend la main sans jamais toucher à la cascade générale.
Vingt lignes à coller dans la console de n'importe quelle page. Il compare la couleur calculée de chaque texte visible à celle du fond derrière lui, et liste tout ce qui passe sous le seuil lisible — 4,5 : 1 pour du texte courant, 3 : 1 pour du gros.
// Colle ceci dans la console de ta page. Il compare, pour chaque element
// visible portant du texte, la couleur calculee du texte et celle du fond
// derriere lui, et signale tout ce qui passe sous le seuil lisible.
(function () {
const lum = (c) => {
const [r, g, b] = c.match(/\d+/g).map(Number).map((v) => {
v /= 255;
return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
});
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
};
const fond = (el) => {
let n = el;
while (n && n !== document.documentElement) {
const bg = getComputedStyle(n).backgroundColor;
if (bg && !/rgba\(0, 0, 0, 0\)|transparent/.test(bg)) return bg;
n = n.parentElement;
}
return 'rgb(255, 255, 255)';
};
const vus = [];
document.querySelectorAll('*').forEach((el) => {
if (!el.offsetParent && getComputedStyle(el).position !== 'fixed') return;
const txt = [...el.childNodes]
.filter((n) => n.nodeType === 3 && n.textContent.trim())
.map((n) => n.textContent.trim()).join(' ');
if (!txt) return;
const s = getComputedStyle(el);
const l1 = lum(s.color), l2 = lum(fond(el));
const ratio = (Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05);
const gros = parseFloat(s.fontSize) >= 24 || (parseFloat(s.fontSize) >= 18.66 && +s.fontWeight >= 700);
const seuil = gros ? 3 : 4.5;
if (ratio < seuil) vus.push({ ratio: +ratio.toFixed(2), seuil, texte: txt.slice(0, 40), el });
});
if (!vus.length) { console.log('Aucun texte sous le seuil.'); return; }
console.table(vus.sort((a, b) => a.ratio - b.ratio));
})();
Il remonte l'arbre pour trouver le vrai fond. Un texte posé sur un conteneur transparent hérite du fond du parent — c'est exactement ce qui rendait mon bouton illisible sans qu'aucune règle ne paraisse fautive.
J'ai lancé le contrôle sur toutes les pages du site. Trois étaient touchées, pas une. Le même bouton, la même cause, dupliquée par copier-coller.
Depuis, je ne me fie plus au rendu supposé : je capture la page servie et je la regarde. Un rendu techniquement parfait peut masquer exactement ce qu'on voulait montrer.
Ce qui est cassé ne crie pas. C'est la seule leçon de cette histoire, et elle vaut bien au-delà du CSS.
Ce contrôle attrape les contrastes. Il ne dit pas si ta page convertit. Si tu veux qu'on regarde ce que ton site coûte et où il perd des gens, on commence par un audit — et si le calcul ne tombe pas en ta faveur, je te le dis.
Recevoir mon auditLE BOUTON INVISIBLE | TONY PAYET / AUTOMATION BOOST | 2026 EDITION
← Toutes les ressources