A few years ago I wrote a little tool called The Site Color Wizard that adjusted the hue, saturation and brightness of all the images on your site. However, few people use… Maybe it’s not done well, or maybe it’s a fake need.

Thanks to the development of Web standards and changes in design styles, front-end developers have gradually changed from cutting diagrams to code. The CSS preprocessor also makes up for the lack of presentation power of CSS to some extent. Many UI frameworks (such as Element) use base color values as configuration items for users to customize, and the rest of the colors adjust brightness/saturation on top of them, or mix them with other colors. It’s impossible to change color with one click, but it’s ok to change the color scheme of the entire site by rebuilding it.

In addition to being customizable, this makes the code more maintainable. I can even express some ideas about color matching (or let me, who is not good at designing, write a UI that is at least passable in color matching), compared to CSS code with lots of color values.

Color scheme?

The following pattern is taken from the management console of Qiniu:

.btn.btn-primary {
    color: #1989fa;
    background-color: rgba(25.137.250.04);
    border-color: rgba(25.137.250.4)
}
Copy the code

Do the math in your head (Shift + left click) and you’ll see that the top three colors are the same color, but with different transparencies.


Since the background of the page is pure white, adjusting the color transparency can be seen as adjusting the brightness of the color. The buttons are only “one color”, but they look harmonious.

It can be seen that the design idea of the normal state of the main button is as follows:

  1. Use # 1989FA as the base color;
  2. Text color use base color;
  3. Make the base color 96% brighter as the background color;
  4. Make the base color 60% brighter for the border color.

Preprocessor?

Using a preprocessor like Sass it is easy to implement the above requirements:

$primary-color: #1989fa;

$text-color: $primary-color;
$background-color: scale-color($primary-color. $lightness: 96%);
$border-color: scale-color($primary-color. $lightness: 60%);

.btn-primary {
  color: $text-color;
  background-color: $background-color;
  border-color: $border-color;
}
Copy the code

Sass evaluates the expression at compile time, generating CSS code that looks like this:

.btn-primary {
  color: #1989fa;
  background-color: #f6faff;
  border-color: #a3d0fd;
}
Copy the code

However, using a precompiler means building — there will always be those who don’t like the “build” process or prefer a more “native” solution.

So, can this be achieved to some extent with pure CSS? The answer is yes, in the case of the Seven Cow management console, transparency is used to achieve the effect of increasing brightness. The problem is that the color values appear multiple times and are still not maintainable.

CSS variable

CSS variables are an experimental technique, but most modern browsers already support them, so consider using them if your site is intended for users with mostly modern browsers. I’ll try to use this technique to describe UI color schemes and write pure CSS that are easier to maintain.

I’m not going to go into the details of CSS variables, but you can check out MDN and related specifications if you’re interested. But don’t worry, even if you don’t know much about CSS variables, there will be some simple explanations for using CSS variables later in this article.

I’m going to write a page as an example.

The color

Well, as a front-end engineer who can’t design, I’m ready to find a ready-made color theme. Choose a favorite Color theme on Adobe Color CC and start matching colors. With a color theme, it’s easier to match colors. Just pick 3 or 4 colors and you’ll have a nice UI.

Background color and text color

To ensure readability, simply pick the two colors with the greatest contrast and brightness difference. In this color theme, of course, the first two are black and white #323a40 and # e5eEF4. I wanted to make a dark color scheme, so I chose the former as the background color and the latter as the text color.

:root {
  --background-color: #323a40;
  --text-color: #e5eef4;
}
Copy the code

CSS variables start with two hyphens. Defining CSS variables is similar to setting properties. This code defines the CSS variables –background-color and –text-color. The :root selector selects the root node (i.e. < HTML >), which differs from HTML in that it has a higher priority and is suitable for defining global CSS variables.

html {
  background: var(--background-color);
  color: var(--text-color);
}
Copy the code

It is also easy to refer to defined CSS variables using the var function. The background color and text color of the page are now set.

DIY in JSFiddle

The main color

Then, choose a primary color. Primary colors are often used for hyperlinks, home buttons, and logos. To make them stand out, choose a color that contrasts both the background color and the text color. Here, I choose the third color in the color theme, #37b0c0.

:root {
  --background-color: #323a40;
  --text-color: #e5eef4;
  --primary-color: #37b0c0;

  --input-size: 30px;
  --input-padding-horizontal: 10px;
  --button-border-radius: 4px;
}

button {
  background: none;
  border: 1px solid var(--primary-color);
  border-radius: var(--button-border-radius);
  color: var(--primary-color);
  height: var(--input-size);
  padding-left: var(--input-padding-horizontal);
  padding-right: var(--input-padding-horizontal);
  transition: all .15s ease;
}

button:hover {
  background: var(--primary-color);
  color: var(--background-color);
  cursor: pointer;
}
Copy the code

CSS variables not only define color values, the above code also uses CSS variables to define the size of the button, the inner margin, and the radius of the border.

DIY in JSFiddle

transparency

There are no color functions like Darken and lighten in CSS. Consider using transparency to achieve the effect of lighten or lighten to some extent. Unfortunately, CSS also has no function for manipulating color transparency. We can only break down the definition of the three components of color:

:root {
  --background-color-r: 51;
  --background-color-g: 59;
  --background-color-b: 64;
  --background-color: rgb(
    var(--background-color-r).
    var(--background-color-g).
    var(--background-color-b)
  );

  --text-color-r: 229;
  --text-color-g: 238;
  --text-color-b: 244;
  --text-color: rgb(
    var(--text-color-r).
    var(--text-color-g).
    var(--text-color-b)
  );

  --primary-color-r: 62;
  --primary-color-g: 176;
  --primary-color-b: 190;
  --primary-color: rgb(
    var(--primary-color-r).
    var(--primary-color-g).
    var(--primary-color-b)
  );

  --input-size: 30px;
  --input-padding-horizontal: 10px;
  --button-border-radius: 4px;
}
Copy the code

Yeah, that’s a tricky definition. However, each color value appears only once.

input. button {
  --border-color: rgba(
    var(--text-color-r).
    var(--text-color-g).
    var(--text-color-b).
    var(--border-color-alpha. .3)
  );
  border: 1px solid var(--border-color);
}
Copy the code

Var (–border-color-alpha,.3) refers to the value of the –border-color-alpha variable. If the variable is undefined or invalid, the value is reverted to.3. In this way, the border color of the input and button will be the background color mixed with 30% of the text color.

input:focus {
  --border-color-alpha: .6;
}
Copy the code

When the focus is on the input, the –border-color-alpha value will change to.6, and the border color will change to the background color blending 60% of the text color.

I wrote a friendly header using the same method.

DIY in JSFiddle

During the day theme

The product manager came to me and said that most programmers found my page friendly, but a few non-night programmers found the theme too harsh during the day and wanted a “day theme”.

The good news is that JavaScript can set the values of CSS variables, whereas daytime themes only need to swap background and text colors.

const themes = [
  {
    name: 'dark'.
    scheme: {
      '--background-color-r': 51.
      '--background-color-g': 59.
      '--background-color-b': 64. 
      '--text-color-r': 229.
      '--text-color-g': 238.
      '--text-color-b': 244
    }
  },
  {
    name: 'light'.
    scheme: {
      '--background-color-r': 229.
      '--background-color-g': 238.
      '--background-color-b': 244. 
      '--text-color-r': 51.
      '--text-color-g': 59.
      '--text-color-b': 64
    }
  }
];

let currentTheme = 0;
window.nextTheme = function (a) {
  currentTheme = (currentTheme + 1) % themes.length;
  const theme = themes[currentTheme];
  Object.keys(theme.scheme).forEach(name = > {
    const value = theme.scheme[name];
    document.documentElement.style.setProperty(name. value);
  });
}
Copy the code

DIY in JSFiddle

Color mixing

Transparency doesn’t solve everything, so if you need to mix with another color (consider using HSL for pure black and white), or if you need gradient, you can only use some “dark technology”.

For example, if you want to set the background color to 50% text color + 50% main color:

. {
  --base-color: var(--text-color);
  --mix-color: rgba(
    var(--primary-color-r).
    var(--primary-color-g).
    var(--primary-color-b).
    .5
  );
  background-color: var(--base-color);
  background-image: linear-gradient(
    to bottom.
    var(--mix-color).
    var(--mix-color)
  );
}
Copy the code

Known issues

In addition to being less convenient to use than CSS preprocessors, Safari doesn’t work in some cases. For instance

:root {
  --r: 255;
  --g: 0;
  --b: 0;
}

.foo {
  border: 10px solid
    rgba(var(--r). var(--g). var(--b). .5);
}
Copy the code

In Safari the border will be rendered currentColor instead of translucent red.

The solution is simply to define one more CSS variable internally.

DIY on JSFiddle (compare Chrome and Safari)