J'ai récemment actualisé les graphiques animés de mon site Web avec un nouveau thème et un groupe de personnages pionniers, mettant en pratique de nombreuses techniques que j'ai partagées dans cette série. Certaines de mes animations changent d'apparence lorsque quelqu'un interagit avec elles ou à différents moments de la journée.
Les couleurs du graphique sur les pages de mon blog changent chaque jour du matin au soir. Ensuite, il y a le mode neige, qui ajoute des couleurs froides et un thème hivernal, grâce à un calque de superposition et un mode de fusion.
En travaillant là-dessus, j'ai commencé à me demander si les valeurs de couleur relatives CSS pourraient me donner plus de contrôle tout en simplifiant le processus. Remarque : Dans ce didacticiel, je me concentrerai sur les valeurs de couleur relatives et sur l'espace colorimétrique OKLCH pour thématiser les graphiques et les animations. Si vous souhaitez plonger profondément dans la couleur relative, Ahmad Shadeed a créé un superbe guide interactif. Quant aux espaces colorimétriques, aux gammes et à OKLCH, notre propre Geoff Graham a écrit à leur sujet.
L’utilisation répétée des éléments était essentielle. Les arrière-plans ont été réutilisés autant que possible, les zooms et les superpositions permettant de créer de nouvelles scènes à partir de la même œuvre d'art. C’est né d’une nécessité, mais cela a également encouragé une réflexion en termes de séries plutôt que de scènes individuelles. Le problème avec la mise à jour manuelle des palettes de couleurs Passons directement à mon défi. Dans des titres Toon comme celui-ci – basé sur l’épisode « Lullabye-Bye Bear » du Yogi Bear Show de 1959 – et dans mon travail en général, les palettes sont limitées à quelques couleurs sélectionnées.
Je crée des nuances et des teintes à partir de ce que j'appelle ma couleur « fond de teint » pour élargir la palette sans ajouter de teintes supplémentaires.
Dans Sketch, je travaille dans l'espace colorimétrique HSL, ce processus implique donc d'augmenter ou de diminuer la valeur de luminosité de ma couleur de fond. Honnêtement, ce n’est pas une tâche ardue, mais choisir une couleur de fond de teint différente nécessite de créer un tout nouvel ensemble de nuances et de teintes. Faire cela manuellement, encore et encore, devient vite laborieux.
J'ai mentionné l'espace colorimétrique HSL — H (teinte), S (saturation) et L (luminosité) —, mais ce n'est qu'une des nombreuses façons de décrire la couleur. RVB – R (rouge), G (vert), B (bleu) – est probablement le plus familier, du moins sous sa forme Hex. Il existe également LAB — L (légèreté), A (vert-rouge), B (bleu-jaune) — et le modèle LCH plus récent, mais désormais largement pris en charge — L (légèreté), C (chroma), H (teinte) — dans sa forme OKLCH. Avec LCH — plus précisément OKLCH en CSS — je peux ajuster la valeur de luminosité de ma couleur de fond.
Ou je peux modifier sa saturation. La chrominance LCH et la saturation HSL décrivent toutes deux l'intensité ou la richesse d'une couleur, mais elles le font de différentes manières. LCH m'offre une gamme plus large et un mélange plus prévisible entre les couleurs.
Je peux également modifier la teinte pour créer une palette de couleurs partageant les mêmes valeurs de luminosité et de chrominance. En HSL et LCH, le spectre de teinte commence au rouge, passe par le vert et le bleu et revient au rouge.
Pourquoi OKLCH a changé ma façon de penser la couleur La prise en charge par les navigateurs de l’espace colorimétrique OKLCH est désormais largement répandue, même si les outils de conception, notamment Sketch, n’ont pas rattrapé leur retard. Heureusement, cela ne devrait pas vous empêcher d'utiliser OKLCH. Les navigateurs se feront un plaisir de convertir les valeurs Hex, HSL, LAB et RVB en OKLCH pour vous. Vous pouvez définir une propriété CSS personnalisée avec une couleur de base dans n'importe quel espace, y compris Hex : /* Couleur de fond de teint */ --fondation : #5accd6 ;
Toutes les couleurs qui en dérivent seront automatiquement converties en OKLCH : --foundation-light : oklch(de var(--foundation) [...]; } --foundation-mid: oklch(de var(--foundation) [...]; } --foundation-dark : oklch(de var(--foundation) [...]; }
La couleur relative en tant que système de conception Considérez la couleur relative comme disant : « Prenez cette couleur, modifiez-la, puis donnez-moi le résultat. » Il existe deux manières d'ajuster une couleur : les changements absolus et les changements proportionnels. Leur code se ressemble, mais se comportent très différemment une fois que vous commencez à échanger les couleurs de fond de teint. Comprendre cette différence est ce qui peut transformer l’utilisation de la couleur relative en un système. /* Couleur de fond de teint */ --fondation : #5accd6 ;
Par exemple, la valeur de luminosité de ma couleur de fond est de 0,7837, tandis qu'une version plus foncée a une valeur de 0,5837. Pour calculer la différence, je soustrais la valeur inférieure de la valeur supérieure et j'applique le résultat à l'aide d'une fonction calc() : --foundation-dark : oklch (de var (--foundation) calc(l - 0,20) c h);
Pour obtenir une couleur plus claire, j'ajoute plutôt la différence : --foundation-light : oklch (de var (--foundation) calc(l + 0,10) ch);
Chromales ajustements suivent le même processus. Pour réduire l'intensité de ma couleur de fond de 0,1035 à 0,0035, je soustrais une valeur à l'autre : oklch (de var (--foundation) l calqué(c - 0,10) h);
Pour créer une palette de teintes, je calcule la différence entre la valeur de teinte de ma couleur de fond (200) et ma nouvelle teinte (260) : oklch (de var (--foundation) l c calc(h + 60));
Ces calculs sont absolus. Lorsque je soustrais un montant fixe, je dis en fait : « Soustrayez toujours ce montant ». La même chose s'applique lors de l'ajout de valeurs fixes : calculer(c - 0,10) calculer(c + 0,10)
J’ai appris à mes dépens les limites de cette approche. Lorsque je comptais sur la soustraction de valeurs de chrominance fixes, les couleurs s'effondraient vers le gris dès que je changeais de fond de teint. Une palette qui fonctionnait pour une couleur s'est effondrée pour une autre. La multiplication se comporte différemment. Lorsque je multiplie la chrominance, je dis au navigateur : « Réduisez l’intensité de cette couleur d’une proportion ». La relation entre les couleurs reste intacte, même lorsque le fond de teint change : calculer(c * 0,10)
Mes règles de déplacement, de mise à l'échelle et de rotation
Déplacer la légèreté (ajouter ou soustraire), Chroma d'échelle (multiplier), Faites pivoter la teinte (ajoutez ou soustrayez des degrés).
Je mets à l'échelle la chrominance parce que je veux que les changements d'intensité restent proportionnels à la couleur de base. Les relations de teinte sont rotationnelles, donc multiplier la teinte n'a aucun sens. La légèreté est perceptuelle et absolue : la multiplier produit souvent des résultats étranges.
D'une couleur à un thème entier La couleur relative me permet de définir une couleur de base et de générer toutes les autres couleurs dont j'ai besoin (remplissages, traits, points de dégradé, ombres) à partir de celle-ci. À ce stade, la couleur cesse d’être une palette et commence à être un système. Les illustrations SVG ont tendance à réutiliser les mêmes quelques couleurs dans les remplissages, les traits et les dégradés. La couleur relative vous permet de définir ces relations une seule fois et de les réutiliser partout, un peu comme les animateurs réutilisaient les arrière-plans pour créer de nouvelles scènes.
Modifiez la couleur de base une fois et chaque couleur dérivée est mise à jour automatiquement, sans rien recalculer manuellement. En dehors des graphiques animés, je pourrais utiliser cette même approche pour définir les couleurs des états des éléments interactifs tels que les boutons et les liens. La couleur de fond que j'ai utilisée dans mon titre Toon « Lullabye-Bye Bear » est un bleu d'aspect cyan. L'arrière-plan est un dégradé radial entre mon fond de teint et une version plus foncée.
Pour créer des versions alternatives aux ambiances totalement différentes, il me suffit de changer la couleur du fond de teint : --fondation : #5accd6 ; --grad-end : var(--foundation); --grad-start : oklch (depuis var (--foundation) calc(l - 0,2357) calc(c * 0,833) h);
Pour lier ces propriétés personnalisées à mon dégradé SVG sans dupliquer les valeurs de couleur, j'ai remplacé les valeurs de couleur d'arrêt codées en dur par des styles en ligne :
Ensuite, je devais m'assurer que mon texte Toon contraste toujours avec la couleur de fond de teint que je choisis. Une rotation de teinte de 180 degrés produit une couleur complémentaire qui ressort certes, mais qui peut vibrer de manière inconfortable : .text-light { remplir : oklch (de var (--foundation) l c calc(h + 180)); }
Un décalage de 90° produit une couleur secondaire vive sans être totalement complémentaire : .text-light { remplir : oklch (de var (--foundation) l c calc(h - 90)); }
Ma reconstitution du titre Toon de 1959 de Quick Draw McGraw, « El Kabong », utilise les mêmes techniques mais avec une palette plus variée. Par exemple, il existe un autre dégradé radial entre la couleur de fond et une teinte plus foncée.
Le bâtiment et l’arbre en arrière-plan sont simplement des nuances différentes de la même couleur de base. Pour ces chemins, j'avais besoin de deux couleurs de remplissage supplémentaires : .bg-milieu { remplir : oklch (de var (--foundation) calc(l - 0,04) calc(c * 0,91) h); }
.bg-dark { remplir : oklch (de var (--foundation) calc(l - 0,12) calc(c * 0,64) h); }
Quand les fondations commencent à bouger
Jusqu’à présent, tout ce que j’ai montré est resté statique. Même lorsque quelqu’un utilise un sélecteur de couleurs pour changer la couleur du fond de teint, ce changement se produit instantanément. Mais les graphiques animés restent rarement immobiles – l’indice est dans le nom. Donc, si la couleur fait partie du système, il n’y a aucune raison pour qu’elle ne puisse pas également s’animer.
Pour animer la couleur de fond, je dois d'abord la diviser en ses canaux OKLCH— légèreté, saturation et teinte. Mais il y a une étape supplémentaire importante : je dois enregistrer ces valeurs en tant que propriétés personnalisées saisies. Mais qu’est-ce que cela signifie ?
Par défaut, un navigateur ne sait pas si une valeur de propriété personnalisée CSS représente une couleur, une longueur, un nombre ou autre chose. Cela signifie souvent qu’ils ne peuvent pas être interpolés de manière fluide pendant l’animation et passer d’une valeur à la suivante.
L'enregistrement d'une propriété personnalisée indique au navigateur le type de valeur qu'elle représente et comment elle doit se comporter au fil du temps. Dans ce cas, je souhaite que le navigateur traite mes canaux de couleur comme des nombres afin qu'ils puissent être animés de manière fluide.
@property --f-l {
syntaxe : "
@property --f-c {
syntaxe : "
@property --f-h {
syntaxe : "
Une fois enregistrées, ces propriétés personnalisées se comportent comme du CSS natif. Le navigateur peut les interpoler image par image. Je reconstruis ensuite la couleur de fond à partir de ces canaux : --foundation: oklch(var(--f-l) var(--f-c) var(--f-h));
Cela rend la couleur de base animable, comme toute autre valeur numérique. Voici une simple animation de « respiration » qui modifie doucement la luminosité au fil du temps : @keyframes respire { 0 %, 100 % { --f-l : 0,36 ; } 50 % { --f-l : 0,46 ; } }
.toon-titre { animation : respirez pendant 10 s avec une facilité d'entrée et d'expiration infinie ; }
Étant donné que toutes les autres couleurs des remplissages, des dégradés et des traits sont dérivées de --foundation, elles s'animent toutes ensemble et rien n'a besoin d'être mis à jour manuellement. Une couleur animée, de nombreux effets Au début de ce processus, je me suis demandé si les valeurs de couleurs relatives CSS pouvaient offrir plus de possibilités tout en les rendant plus simples à mettre en œuvre. J'ai récemment ajouté un nouveau fond de mine d'or à la page de contact de mon site Web, et la première itération comprenait des lampes à huile qui brillent et oscillent.
Je voulais explorer comment l'animation des couleurs relatives CSS pourrait rendre l'intérieur de la mine plus réaliste en le teintant avec les couleurs des lampes. Je voulais qu’ils affectent le monde qui les entoure, comme le fait la vraie lumière. Ainsi, plutôt que d’animer plusieurs couleurs, j’ai construit un petit système d’éclairage qui anime une seule couleur.
Ma première tâche a été d'insérer un calque de superposition entre l'arrière-plan et mes lampes :
J'ai utilisé mix-blend-mode: color car cela teinte ce qui se trouve en dessous tout en préservant la luminance sous-jacente. Comme je souhaite que la superposition ne soit visible que lorsque les animations sont activées, j'ai activé la superposition : .svg-mine #overlay { affichage : aucun ; }
@media (préfère le mouvement réduit : aucune préférence) { .svg-mine[data-animations=on] #overlay { affichage : bloc ; opacité : 0,5 ; } }
La superposition était en place, mais pas encore connectée aux lampes. J'avais besoin d'une source de lumière. Mes lampes sont simples, et chacune contient un élément circulaire que j'ai flouté avec un filtre. Le filtre produit un flou très doux sur tout le cercle.
Au lieu d’animer la superposition et les lampes séparément, j’anime un seul jeton de couleur « flamme » et j’en tire tout le reste. Tout d’abord, j’enregistre trois propriétés personnalisées typées pour les canaux OKLCH :
@property --fl-l {
syntaxe : "
J'ai animé ces chaînes, en poussant délibérément quelques images vers l'orange pour que le scintillement se lit clairement comme une lueur de feu :
@keyframes flamme { 0 %, 100 % { --fl-l : 0,86 ; --fl-c : 0,12 ; --fl-h : 95 ; } 6% { --fl-l : 0,91 ; --fl-c : 0,10 ; --fl-h : 92 ; } 12 % { --fl-l : 0,83 ; --fl-c : 0,14 ; --fl-h : 100 ; } 18 % { --fl-l : 0,88 ; --fl-c : 0,11 ; --fl-h : 94 ; } 24 % { --fl-l : 0,82 ; --fl-c : 0,16 ; --fl-h : 82 ; } 30 % { --fl-l : 0,90 ; --fl-c : 0,12 ; --fl-h : 90 ; } 36 % { --fl-l : 0,79 ; --fl-c : 0,17 ; --fl-h : 76 ; } 44 % { --fl-l : 0,87 ; --fl-c : 0,12 ; --fl-h : 96 ; } 52 % { --fl-l : 0,81 ; --fl-c : 0,15 ; --fl-h : 102 ; } 60 % { --fl-l : 0,89 ; --fl-c : 0,11 ; --fl-h : 93 ; } 68 % { --fl-l : 0,83 ; --fl-c : 0,16 ; --fl-h : 85 ; } 76 % { --fl-l : 0,91 ; --fl-c : 0,10 ; --fl-h : 91 ; } 84 % { --fl-l : 0,85 ; --fl-c : 0,14 ; --fl-h : 98 ; } 92% {--fl-l : 0,80 ; --fl-c : 0,17 ; --fl-h : 74 ; } }
Ensuite, j'ai étendu cette animation au SVG, afin que les variables partagées soient disponibles à la fois pour les lampes et ma superposition :
@media (préfère le mouvement réduit : aucune préférence) { .svg-mine[data-animations=on] { animation : flamme 3,6 s linéaire infinie ; isolement : isoler ;
/* Crée une couleur de flamme à partir de canaux animés */ --flame : oklch(var(--fl-l) var(--fl-c) var(--fl-h));
/* Couleur de la lampe dérivée de la flamme */ --lamp-core: oklch(from var(--flame) calc(l + 0.05) calc(c * 0.70) h);
/* Teinte de superposition dérivée de la même flamme */ --overlay-tint : oklch (de var (--flame) calc(l + 0,06) calc(c * 0,65) calc(h - 10)); } }
Enfin, j'ai appliqué ces couleurs dérivées aux lampes lumineuses et à la superposition qu'elles affectent : @media (préfère le mouvement réduit : aucune préférence) { .svg-mine[data-animations=on] #mine-lamp-1 > cercle, .svg-mine[data-animations=on] #mine-lamp-2 > cercle { remplir : var(--lamp-core); }
.svg-mine[data-animations=on] #overlay { affichage : bloc ; remplir : var(--overlay-tint); opacité : 0,5 ; } }
Lorsque la flamme vire à l’orange, les lampes se réchauffent et la scène s’en réchauffe. Lorsque la flamme refroidit, tout s’installe. Le meilleur, c’est que rien n’est écrit manuellement. Si je change la couleur de base ou modifie les plages d'animation des flammes, l'ensemble du système d'éclairage se met à jour simultanément. Vous pouvez voir le résultat final sur mon site internet. Réutilisation, réutilisation, revisité Les animateurs d'Hanna-Barbera ont été obligés de réutiliser des éléments par nécessité, mais je réutilise les couleurs car cela rend mon travail plus cohérent et plus facile à entretenir. Les valeurs de couleur relatives CSS me permettent de :
Définir une seule couleur de fond de teint, Décrivez comment les autres couleurs s'y rapportent, Réutilisez ces relations partout, et Animez le système en modifiant une valeur.
La couleur relative ne facilite pas seulement la création de thèmes. Cela encourage une façon de penser où la couleur, comme le mouvement, est intentionnelle – et où changer une valeur peut transformer une scène entière sans réécrire l’œuvre en dessous.