Skema warna tanpa bantuan desainer


Tentunya banyak dari Anda telah berada dalam situasi di mana Anda harus cepat memilih warna untuk dekorasi, dan perancang sibuk dengan tugas-tugas yang lebih penting, dalam suasana hati yang buruk atau berlibur. Tugasnya tidak sulit, tetapi terkadang Anda harus menunggu jawaban selama beberapa hari.

Nama saya Emil Frolov, saya seorang teknisi di tim layanan internal di DomKlik. Dalam artikel ini saya akan memberi tahu Anda bagaimana ide perpustakaan lahir, yang sekarang menghemat banyak waktu ketika memilih warna. Solusinya sederhana, tetapi sangat bermanfaat, bawa ke layanan.

Apalagi jika Anda perlu memilih warna untuk skema gelap.

Tugas


DomKlik memiliki portal perusahaan, yang setiap bagiannya memiliki skema warnanya sendiri. Sebelumnya, untuk membuat bagian baru, setiap kali saya harus menyiksa desainer dan meminta mereka untuk mengambil set warna baru dan mentransfernya ke antarmuka. Ternyata sejumlah besar kode tambahan, menghabiskan banyak waktu untuk korespondensi, menunggu dan koordinasi. Saya benar-benar ingin menyederhanakan dan mempercepat seluruh proses.

Kami mencari solusi yang sudah jadi di Internet, tetapi tidak ada yang cocok ditemukan. Dan kemudian kami memutuskan untuk menulis perpustakaan: Anda memasukkan warna (merek) yang diberikan oleh perancang, dan perpustakaan memilih beberapa warna yang lebih cocok. Kami juga ingin perpustakaan menghasilkan skema warna gelap juga.
Ini bukan resep untuk kebahagiaan, melainkan gagasan bahwa setiap orang dapat berkembang dalam kerangka proyek mereka. Anda dapat melihat demo kecil di sini .

Ide dan solusi


Kami berpikir bagaimana melakukannya. Kami mulai dengan algoritma generasi warna berbasis-dasar. Di Internet Anda ini lagi tidak ada yang siap ditemukan. Tetapi mereka menemukan perpustakaan yang dapat mengubah pengaturan warna yang berbeda.

Banyak orang tahu bahwa ada banyak algoritme pencocokan warna yang berbeda:



Saya tidak mengerti cara mengecatnya, mereka sudah melakukan ini ratusan kali sebelum saya. Tetapi ada beberapa poin kunci:

  1. Bagi kami mereka mubazir.
  2. Saya ingin memilih warna untuk diri saya sendiri.

Oleh karena itu, perancang dan pengembang, bergabung menjadi satu impuls, memutuskan untuk mengambil skema secara manual sekali.

Untuk mulai dengan, kami menggambarkan warna dasar:

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';
  ...
}

Berdasarkan ini, Anda dapat mulai membuat. Kami mendapatkan objek untuk bekerja dengan warna dasar.

  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);
    ...
  }

Saya pikir tidak masuk akal untuk sepenuhnya menggambarkan seluruh pemilihan warna, tetapi sebagai contoh saya akan memberikan beberapa baris:

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);
  ...
}

Setelah kami selesai memilih warna primer, kami menghadapi masalah berikut.

Dan warna apa yang menampilkan teks pada elemen?

Tugas itu tidak sesulit kelihatannya. Untuk mengatasinya dari nilai hex, kita perlu mendapatkan kecerahan elemen. Kami melakukan ini dengan dua fungsi pembantu. Yang pertama menerjemahkan hex ke RGB:

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;
};

Fungsi kedua dari RGB mendapatkan kecerahan latar belakang dan memutuskan apakah warnanya gelap atau terang:

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';
};

Anda mungkin berpikir bahwa sekarang semuanya sudah siap untuk langkah selanjutnya. Tapi tidak, kami masih ingin dukungan untuk tema gelap di luar kotak? Iya! Kami menginginkannya!

Anda mungkin memperhatikan bahwa kami mengibarkan bendera ke fungsi kami inverse. Mari kita ubah sedikit kode kita dengan mengingat flag ini:

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);

  ...
}

Itu saja. Kami dapat memberikan daftar warna:

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(),
  ...
}

Dalam dua hari, dengan bantuan desainer kami, saya membuat perpustakaan, yang pada outputnya memberikan palet warna untuk tema gelap dan terang.

Pertanyaan selanjutnya: bagaimana cara menggunakannya?

Sangat sederhana. Untuk mengimplementasikan skema warna yang dihasilkan, kami menggunakan penyisipan variabel CSS melalui blok gaya. Ini menghindari konflik dengan variabel CSS yang digunakan pustaka CSS lainnya.

  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);

Dan sekarang yang paling enak. Perhatian perhatian! Sekarang, dengan beberapa baris, ketika kita menambahkan dukungan tema gelap untuk setengah elemen:

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

Hasilnya adalah pustaka tempat kami melewati warna merek utama dan mendapatkan serangkaian variabel CSS, yang kemudian kami gunakan untuk mewarnai proyek kami.

Sebagian besar waktu dihabiskan untuk memilih skema warna. Saya harus secara manual memilah-milah banyak parameter yang berbeda sehingga warna-warna digabungkan satu sama lain. Tapi sekarang, pada setiap iterasi pemilihan warna untuk bagian baru portal, kami menghemat beberapa hari.

Karena perancang mengambil bagian dalam pembuatan algoritma, masih tidak ada kasus bahwa ia tidak puas dengan warna yang dihasilkan oleh perpustakaan. Ya, dan skema warna tidak terlalu besar, sulit untuk membuat kesalahan.

Saya menekankan sekali lagi bahwa kami tidak mengklaim sebagai satu-satunya keputusan yang tepat. Ide ini diimplementasikan, dan itu bekerja dengan baik. Saya mencoba untuk membawakan Anda poin-poin utama, dan detail serta ruang lingkup implementasinya hanya bergantung pada Anda dan proyek Anda.

Terimakasih atas perhatiannya.

All Articles