Jeu de couleurs sans l'aide d'un designer


Beaucoup d'entre vous ont sûrement été dans une situation où vous devez choisir rapidement les couleurs pour la décoration, et le designer est occupé à des tâches plus importantes, de mauvaise humeur ou en vacances. La tâche n'est pas difficile, mais il faut parfois attendre une réponse pendant plusieurs jours.

Je m'appelle Emil Frolov, je suis technophile dans l'équipe des services internes de DomKlik. Dans cet article, je vais vous expliquer comment est née l'idée d'une bibliothèque, qui permet désormais de gagner beaucoup de temps lors du choix des couleurs. La solution est simple, mais très utile, mettez-la en service.

Surtout si vous devez choisir des couleurs pour le schéma sombre.

Tâche


DomKlik dispose d'un portail d'entreprise, dont chaque section a son propre jeu de couleurs. Auparavant, pour créer une nouvelle section, à chaque fois, je devais tourmenter les designers et leur demander de prendre un nouvel ensemble de couleurs et de les transférer sur l'interface. Il s'est avéré une énorme quantité de code supplémentaire, a passé beaucoup de temps sur la correspondance, l'attente et la coordination. Je voulais vraiment simplifier et accélérer tout le processus.

Nous avons cherché des solutions toutes faites sur Internet, mais rien n'a été trouvé. Et puis ils ont décidé d'écrire une bibliothèque: vous entrez la couleur (marque) que le designer donne, et la bibliothèque sélectionne quelques couleurs plus appropriées. Nous voulions également que la bibliothèque génère également des jeux de couleurs sombres.
Ce n'est pas une recette du bonheur, mais plutôt une idée que chacun peut développer dans le cadre de son projet. Vous pouvez voir une petite démo ici .

Idée et solution


Nous avons pensé comment le faire. Nous avons commencé avec un algorithme de génération de couleurs basique. Sur votre Internet, rien de nouveau n'a été trouvé. Mais ils ont trouvé une bibliothèque qui peut modifier différents paramètres de couleur.

Beaucoup de gens savent qu'il existe de nombreux algorithmes de correspondance des couleurs:



je ne vois aucun sens à les peindre, ils l'ont déjà fait des centaines de fois avant moi. Mais il y a quelques points clés:

  1. Pour nous, ils sont redondants.
  2. Je voulais choisir des couleurs pour moi.

Par conséquent, le concepteur et le développeur, fusionnés en une seule impulsion, ont décidé de reprendre le schéma manuellement une fois.

Pour commencer, nous avons décrit les couleurs de base:

export const getColors = (projectColor, inverse) => {
  ...
  const BASE_SUCCESS = '#00985f';
  const BASE_WARNING = '#ff9900';
  const BASE_PROGRESS = '#fe5c05';
  const BASE_ALERT = '#ff3333';
  const BASE_SYSTEM = '#778a9b';
  const BASE_NORMAL = '#dde3e5';
  const BASE_WHITE = '#ffffff';
  const BASE_BLACK = '#000';
  const TYPO_BASE_BLACK = '#242629';
  const TYPO_LINK = '#33BDFF';
  ...
}

Sur cette base, vous pouvez commencer à créer. Nous obtenons des objets pour travailler avec des couleurs de base.

  import color from 'color-js';

  export const getColors = (projectColor, inverse) => {
    ...
    const baseWhite = color(BASE_WHITE);
    const baseBlack = color(BASE_BLACK);
    const baseTypoBlack = color(TYPO_BASE_BLACK);
    ...
  }

Je pense que cela n'a aucun sens de décrire pleinement la sélection complète des couleurs, mais pour un exemple, je vais donner quelques lignes:

export const getColors = (projectColor, inverse) => {
  ...
  const bgBrand = baseProject;
  const bgHard = baseColor.setLightness(0.4);
  const bgSharp = baseColor.setLightness(0.18);
  const bgStripe = baseColor.setLightness(0.1);
  const bgGhost = baseColor.setLightness(0.07);
  ...
}

Après avoir fini de choisir les couleurs primaires, nous avons rencontré le problème suivant.

Et quelle couleur affiche le texte sur les éléments?

La tâche n'était pas aussi difficile qu'il n'y paraissait. Pour le résoudre à partir de la valeur hexadécimale, nous devons obtenir la luminosité de l'élément. Nous l'avons fait avec deux fonctions d'assistance. Le premier traduit hex en RVB:

const hexToRgb = (hex) => {
  const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
  const newHex = hex.replace(shorthandRegex, (
    magenta,
    red,
    green,
    blue
  ) => red + red + green + green + blue + blue);

  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(newHex);

  return result ? {
    red: parseInt(result[1], 16),
    green: parseInt(result[2], 16),
    blue: parseInt(result[3], 16)
  } : null;
};

La deuxième fonction de RGB obtient la luminosité de l'arrière-plan et décide si la couleur est sombre ou claire:

export const getBgTextColor = (bgColor) => {
  const rgb = hexToRgb(bgColor);
  const light = (rgb.red * 0.8 + rgb.green + rgb.blue * 0.2) / 510 * 100;

  return light > 70 ? '#000000' : '#ffffff';
};

Vous pourriez penser que maintenant tout est prêt pour la prochaine étape. Mais non, nous voulons toujours la prise en charge d'un thème sombre hors de la boîte? Oui! Nous le voulons!

Vous avez probablement remarqué que nous passons un drapeau à notre fonction inverse. Modifions un peu notre code avec ce drapeau à l'esprit:

import color from 'color-js';

export const getColors = (projectColor, inverse) => {
  ...
  const BASE_SUCCESS = '#00985f';
  const BASE_WARNING = '#ff9900';
  const BASE_PROGRESS = '#fe5c05';
  const BASE_ALERT = '#ff3333';
  const BASE_SYSTEM = '#778a9b';
  const BASE_NORMAL = '#dde3e5';
  const BASE_WHITE = '#ffffff';
  const BASE_BLACK = '#000';
  const TYPO_BASE_BLACK = '#242629';
  const TYPO_LINK = '#33BDFF';

  ...

  const baseWhite = color(BASE_WHITE);
  const baseBlack = color(BASE_BLACK);
  const baseTypoBlack = color(TYPO_BASE_BLACK);
  const baseColor = inverse ? baseWhite : baseBlack;
  const typoColor = inverse ? baseWhite : baseTypoBlack;

  ...

  const bgHard = inverse ? baseColor.setLightness(0.4) : baseColor.lightenByAmount(0.85);
  const bgSharp = inverse ? baseColor.setLightness(0.18) : baseColor.lightenByAmount(0.95);
  const bgStripe = inverse ? baseColor.setLightness(0.1) : baseColor.lightenByAmount(0.96);
  const bgGhost = inverse ? baseColor.setLightness(0.07) : baseColor.lightenByAmount(0.99);

  ...
}

C'est tout. Nous pouvons donner une liste de couleurs:

return {
  ...
    // BG
    'color-bg-hard': bgHard.toString(),
    'color-bg-sharp': bgSharp.toString(),
    'color-bg-stripe': bgStripe.toString(),
    'color-bg-ghost': bgGhost.toString(),
    'color-bg-primary': bgDefault.toString(),
  ...
}

En deux jours, avec l'aide de notre designer, j'ai créé une bibliothèque, qui à la sortie donne une palette de couleurs pour un thème sombre et clair.

Question suivante: comment l'utiliser?

Très simple. Pour implémenter le jeu de couleurs généré, nous avons utilisé l'insertion de variables CSS via le bloc de style. Cela évite les conflits avec les variables CSS que les autres bibliothèques CSS utilisent.

  const colors = getColors(color, themeKey === 'dark');
  const colorsVars = Object.keys(colors).map((key) => `--${key}: ${customColors[key]}`).join(';');
  
  const link = document.createElement('style');
  const headTag = document.getElementsByTagName('head')[0];

  link.type = 'text/css';
  link.id = 'project-theme-scope';
  const stylesBody = `:root {${colorsVars}}`;

  link.innerText = stylesBody;

  headTag.append(link);

Et maintenant le plus délicieux. Attention ATTENTION! Maintenant, avec quelques lignes, lorsque nous ajoutons un support de thème sombre pour la moitié des éléments:

  body {
    background: var(--color-bg-ghost);
    color: var(--color-typo-primary);
  }

Le résultat est une bibliothèque dans laquelle nous transmettons la couleur principale de la marque et obtenons un ensemble de variables CSS, que nous utilisons ensuite pour coloriser notre projet.

La plupart du temps a été consacré au choix d'une palette de couleurs. J'ai dû trier manuellement un tas de paramètres différents pour que les couleurs soient combinées les unes avec les autres. Mais maintenant, à chaque itération de la sélection des couleurs pour les nouvelles sections du portail, nous économisons plusieurs jours.

Puisque le concepteur a participé à la création de l'algorithme, il n'y avait toujours aucun cas qu'il n'était pas satisfait des couleurs générées par la bibliothèque. Oui, et les couleurs ne sont pas trop grandes, il est difficile de se tromper.

Je souligne une fois de plus que nous ne prétendons pas être la seule bonne décision. Cette idée est mise en œuvre et elle fonctionne bien. J'ai essayé de vous apporter les points principaux, et les détails et la portée de la mise en œuvre ne dépendent que de vous et de votre projet.

Merci pour l'attention.

All Articles