Comment configurer des schémas de couleurs d'application avec des propriétés personnalisées CSS
Publié: 2022-03-10Les variables sont un outil de base qui aide à organiser les couleurs sur un projet. Pendant longtemps, les ingénieurs frontaux ont utilisé des variables de préprocesseur pour configurer les couleurs d'un projet. Mais maintenant, de nombreux développeurs préfèrent le mécanisme natif moderne pour organiser les variables de couleur : les propriétés personnalisées CSS. Leur avantage le plus important par rapport aux variables de préprocesseur est qu'elles fonctionnent en temps réel, pas au stade de la compilation du projet, et prennent en charge le modèle en cascade qui vous permet d'utiliser l'héritage et la redéfinition des valeurs à la volée.
Lorsque vous essayez d'organiser un jeu de couleurs d'application, vous pouvez toujours placer toutes les propriétés personnalisées liées à la couleur dans la section racine, les nommer et les utiliser à tous les endroits nécessaires.
C'est une option, mais cela vous aide-t-il à résoudre les problèmes de thématisation des applications, de marque blanche, d'actualisation de la marque ou d'organisation d'un mode clair ou sombre ? Que faire si vous avez besoin d'ajuster le jeu de couleurs pour augmenter le contraste ? Avec l'approche actuelle, vous devrez mettre à jour chaque valeur de vos variables.
Dans cet article, je souhaite suggérer une approche plus flexible et plus résistante sur la façon de diviser les variables de couleur à l'aide de propriétés personnalisées, ce qui peut résoudre bon nombre de ces problèmes.
Configuration de la palette de couleurs
La coloration de tout site Web commence par la configuration d'un jeu de couleurs. Un tel schéma est basé sur la roue chromatique. Habituellement, seules quelques couleurs primaires forment la base d'une palette, les autres sont des couleurs dérivées - tons et demi-teintes. Le plus souvent, la palette est statique et ne change pas pendant l'exécution de l'application Web.
Selon la théorie des couleurs, il n'y a que quelques options pour les combinaisons de couleurs :
- Schéma monochromatique (une couleur primaire)
- Schéma complémentaire (deux couleurs primaires)
- Schéma triade (trois couleurs primaires)
- Schéma tétradique (quatre couleurs primaires)
- Motif adjacent (deux ou trois couleurs primaires)
Pour mon exemple, je vais générer un jeu de couleurs triade à l'aide du service Paletton :
J'ai maintenant trois couleurs principales. Sur la base de ceux-ci, je calculerai les tons et les tons moyens (le format HSL en combinaison avec la fonction calc
est un outil très utile pour cela). En modifiant la valeur de luminosité, je peux générer plusieurs couleurs supplémentaires pour la palette.
Maintenant si la palette est modifiée, alors il faudra changer uniquement la valeur des couleurs primaires. Le reste sera recalculé automatiquement.
Si vous préférez les formats HEX ou RVB, cela n'a pas d'importance ; une palette peut être formée au stade de la compilation du projet avec les fonctions correspondantes du préprocesseur (par exemple avec SCSS et la fonction color-adjust
). Comme je l'ai déjà mentionné, cette couche est principalement statique ; il est extrêmement rare que la palette puisse être modifiée dans une application en cours d'exécution. C'est pourquoi nous pouvons le calculer avec des préprocesseurs.
Remarque : Je recommande également de générer à la fois le littéral HEX et le RVB pour chaque couleur. Cela permettra de jouer avec le canal alpha à l'avenir.
Le niveau palette est le seul niveau où la couleur est encodée directement dans les noms des variables, c'est-à-dire qu'on peut identifier de manière unique la couleur en lisant le nom.
Définir le thème ou les couleurs fonctionnelles
Une fois la palette réalisée, la prochaine étape est le niveau des couleurs fonctionnelles . À ce niveau, la valeur de la couleur n'est pas aussi importante que son objectif, la fonction qu'elle remplit et ce qu'elle colorie exactement. Par exemple, la couleur de la marque principale ou de l'application, la couleur de la bordure, la couleur du texte sur fond sombre, la couleur du texte sur fond clair, la couleur d'arrière-plan du bouton, la couleur du lien, la couleur du lien de survol, la couleur du texte d'astuce, etc. .
Ce sont des choses extrêmement courantes pour presque tous les sites Web ou applications. On peut dire que ces couleurs sont responsables d'un certain thème de couleur de l'application. De plus, les valeurs de ces variables sont strictement extraites de la palette. Ainsi, nous pouvons facilement changer de thèmes d'application en opérant simplement avec différentes palettes de couleurs.
Ci-dessous, j'ai créé trois contrôles d'interface utilisateur typiques : un bouton, un lien et un champ de saisie. Ils sont colorés à l'aide de variables fonctionnelles contenant des valeurs de la palette que j'ai précédemment générée ci-dessus. La principale variable fonctionnelle responsable du thème de l'application (marque conditionnelle) est la variable de couleur primaire.
À l'aide des trois boutons en haut, vous pouvez changer de thème (changer la couleur de la marque pour les commandes). Le changement se produit en utilisant l'API CSSOM appropriée (setProperty).
Cette approche est pratique non seulement pour la thématisation, mais également pour la configuration de pages Web individuelles. Par exemple, sur le site Web zubry.by, j'ai utilisé une feuille de style commune et une variable fonctionnelle --page-color
pour coloriser le logo, les en-têtes, les contrôles et la sélection de texte pour toutes les pages. Et dans les propres styles de chaque page, je viens de redéfinir cette variable pour définir la page sa couleur primaire individuelle.
Utiliser les couleurs des composants
Les grands projets Web contiennent toujours une décomposition ; nous divisons tout en petits composants et les réutilisons dans de nombreux endroits. Chaque composant a généralement son propre style, ce qui signifie que peu importe ce que nous avons utilisé pour décomposer les modules BEM ou CSS, ou une autre approche ; il est important que chacun de ces morceaux de code puisse être appelé portée locale et réutilisé.
En général, je vois l'intérêt d'utiliser des variables de couleur au niveau du composant dans deux cas.
Le premier est lorsque les composants qui, selon le guide de style de l'application, sont répétés avec différents paramètres, par exemple des boutons pour différents besoins comme le bouton principal (marque), le bouton secondaire, le tertiaire, etc.
La seconde est lorsque les composants ont plusieurs états avec des couleurs différentes, par exemple les états de survol des boutons, actifs et de mise au point ; états normaux et invalides pour le champ d'entrée ou de sélection, et ainsi de suite.
Un cas plus rare où les variables de composant peuvent être utiles est la fonctionnalité d'une "marque blanche". La «marque blanche» est une fonctionnalité de service qui permet à l'utilisateur de personnaliser ou de personnaliser une partie de l'interface utilisateur pour améliorer l'expérience d'interaction avec ses clients. Par exemple, des documents électroniques qu'un utilisateur partage avec ses clients via un service ou des modèles d'e-mail. Dans ce cas, les variables au niveau du composant aideront à configurer certains composants séparément du reste du thème de couleur de l'application.
Dans l'exemple ci-dessous, j'ai maintenant ajouté des contrôles pour personnaliser les couleurs du bouton principal (marque). En utilisant des variables de couleur au niveau du composant, nous pouvons configurer les contrôles de l'interface utilisateur séparément les uns des autres.
Comment déterminer le niveau d'une variable ?
Je suis tombé sur la question de savoir comment comprendre ce qu'on peut mettre à la racine (thème ou niveau fonctionnel), et ce qu'il faut laisser au niveau d'un composant. C'est une excellente question à laquelle il est difficile de répondre sans voir la situation dans laquelle vous travaillez.
Malheureusement, la même approche qu'en programmation ne fonctionne pas avec les couleurs et les styles, si nous voyons trois morceaux de code identiques, nous devons le refactoriser.
La couleur peut être répétée d'un composant à l'autre, mais cela ne signifie pas qu'il s'agit d'une règle. Il ne peut y avoir aucune relation entre ces composants. Par exemple, la bordure du champ de saisie et l'arrière-plan du bouton principal. Oui, dans mon exemple ci-dessus, c'est le cas, mais vérifions l'exemple suivant :
La couleur gris foncé est répétée - il s'agit de la bordure du champ de saisie, de la couleur de remplissage de l'icône de fermeture et de l'arrière-plan du bouton secondaire. Mais ces composants ne sont en aucun cas liés les uns aux autres. Si la couleur de la bordure du champ de saisie change, nous ne modifierons pas l'arrière-plan du bouton secondaire. Pour un tel cas il faut garder ici uniquement la variable de la palette.
Et le vert ? Nous pouvons clairement le définir comme la couleur principale ou de la marque, très probablement, si la couleur du bouton principal change, la couleur du lien et de l'en-tête du premier niveau changera également.
Qu'en est-il du rouge ? L'état non valide des champs de saisie, les messages d'erreur et les boutons destructeurs auront la même couleur au niveau de l'application entière. Ceci est un modèle. Maintenant, je peux définir plusieurs variables fonctionnelles communes dans la section racine :
En ce qui concerne le niveau de couleurs des composants, nous pouvons facilement identifier les composants personnalisables à l'aide de propriétés personnalisées.
Le bouton est répété avec différents paramètres, la couleur d'arrière-plan et le texte pour différents cas d'utilisation changent - cas primaire, secondaire, tertiaire, destructif ou négatif.
Le champ de saisie a deux états - incorrect et normal, où les couleurs d'arrière-plan et de bordure diffèrent. Et donc, plaçons ces paramètres dans des variables de couleur au niveau des composants correspondants.
Pour le reste des composants, il n'est pas nécessaire de définir des variables de couleur locales, cela sera redondant.
Vous devez vous plonger dans le langage de modèle de votre projet, qui est probablement développé par l'équipe de conception et UX. Les ingénieurs doivent bien comprendre tout le concept d'un langage visuel, ce n'est qu'alors que nous pourrons déterminer ce qui est commun et devrait vivre à un niveau fonctionnel, et ce qui devrait rester dans la portée locale de la visibilité.
Mais tout n'est pas si compliqué, il y a des choses évidentes. Le fond général de la page, le fond et la couleur du texte principal, c'est dans la plupart des cas ce qui définit le thème de votre application. Il est extrêmement pratique de collecter les éléments responsables de la configuration d'un mode particulier (comme le mode sombre ou clair).
Pourquoi ne pas tout mettre dans la section racine ?
J'ai vécu une telle expérience. Sur le projet Lition, l'équipe et moi avons été confrontés au fait que nous devions prendre en charge IE11 pour l'application Web, mais pas pour le site Web et les atterrissages. Un UI Kit commun a été utilisé entre les projets, et nous avons décidé de mettre toutes les variables à la racine, cela nous permettra de les redéfinir à n'importe quel niveau.
Et aussi avec cette approche pour l'application Web et le cas IE11, nous avons simplement passé le code via le plug-in de post-processeur suivant et transformé ces variables en littéraux pour tous les composants de l'interface utilisateur du projet. Cette astuce n'est possible que si toutes les variables ont été définies dans la section racine car le post-processeur ne peut pas comprendre les spécificités du modèle en cascade.
Maintenant, je comprends que ce n'était pas la bonne voie. Premièrement, si vous mettez les couleurs des composants dans la section racine, vous enfreignez le principe de séparation des préoccupations. En conséquence, vous pouvez vous retrouver avec du CSS redondant dans la feuille de style. Par exemple, vous avez le dossier des composants où chaque composant a ses propres styles. Vous disposez également d'une feuille de style commune dans laquelle vous décrivez les variables de couleur dans la section racine. Vous décidez de supprimer le composant bouton ; dans ce cas, vous devez penser à supprimer également les variables associées au bouton du fichier de styles communs.
Deuxièmement, ce n'est pas la meilleure solution en termes de performances. Oui, un changement de couleur ne provoque que le processus de repeinture, pas de refusion/mise en page, ce n'est pas trop coûteux en soi, mais lorsque vous apportez des modifications au plus haut niveau, vous utiliserez plus de ressources pour vérifier l'ensemble de l'arborescence que lorsque celles-ci les changements sont dans une petite zone locale. Je recommande de lire le benchmark de performance des variables CSS de Lisi Linhart pour plus de détails.
Sur mon projet actuel Tispr, l'équipe et moi utilisons split et ne vidons pas tout à la racine, au niveau supérieur seulement une palette et des couleurs fonctionnelles. De plus, nous n'avons pas peur d'IE11, car ce problème est résolu par le polyfill correspondant. Installez simplement le module npm ie11-custom-properties et importez la bibliothèque dans votre bundle JS d'application :
// Use ES6 syntax import "ie11-custom-properties"; // or CommonJS require('ie11-custom-properties');
Ou ajoutez un module par balise de script :
<script async src="./node_modules/ie11-custom-properties/ie11CustomProperties.js">
En outre, vous pouvez ajouter la bibliothèque sans npm via CDN. Le travail de ce polyfill est basé sur le fait qu'IE11 a un support minimal pour les propriétés personnalisées, où les propriétés peuvent être définies et lues en fonction de la cascade. Ce n'est pas possible avec les propriétés commençant par des doubles tirets, mais éventuellement avec un seul tiret (mécanisme similaire aux préfixes de fournisseur). Vous pouvez en savoir plus à ce sujet dans la documentation du référentiel, ainsi que vous familiariser avec certaines limites. Les autres navigateurs ignoreront ce polyfill.
Vous trouverez ci-dessous une palette de l'application Web Tispr ainsi que les contrôles de la fonctionnalité "marque blanche" pour les documents électroniques (tels que les contrats d'utilisation, les factures ou les propositions).
Pourquoi ne pas stocker les variables de couleur du côté JavaScript ?
Autre question raisonnable : pourquoi ne pas stocker les variables de palette et de fonction dans du code JavaScript ? Cela peut également être modifié dynamiquement et les couleurs redéfinies ultérieurement via des styles en ligne. Cela pourrait être une option, mais cette approche serait probablement moins optimale car vous devez avoir accès à certains éléments et modifier leurs propriétés de couleur. Avec les variables CSS, vous ne modifierez qu'une seule propriété, c'est-à-dire la valeur de la variable.
En JavaScript, il n'y a pas de fonctions natives ou d'API pour travailler avec les couleurs. Dans le CSS Color Module 5, il y aura de nombreuses possibilités de créer des couleurs dérivées ou de les calculer d'une manière ou d'une autre. Du point de vue du futur, les propriétés personnalisées CSS sont plus riches et plus flexibles que les variables JS. De plus, avec les variables JS, il n'y aura pas de possibilité d'utiliser l'héritage en cascade et c'est le principal inconvénient.
Conclusion
La division des couleurs en trois niveaux (palette, fonctionnel et composant) peut vous aider à mieux vous adapter aux changements et aux nouvelles exigences lorsque vous travaillez sur un projet. Je pense que les propriétés personnalisées CSS sont le bon outil pour organiser la répartition des couleurs - peu importe ce que vous utilisez pour le style : CSS pur, préprocesseurs ou approche CSS-in-JS.
Je suis venu à cette approche par ma propre expérience, mais je ne suis pas seul. Sara Soueidan a décrit dans son article une approche similaire dans laquelle elle a divisé les variables en niveaux global et composant.
J'aimerais également suggérer la lecture de l'article de Lea Verou où elle décrit des cas possibles d'application de variables CSS (pas seulement en termes de couleur).