Cleaning up our color palette 🎨

(Sam Saffron) #1

At the moment all our CSS has mountains of extreme levels of repetition when it comes to picking colors.

When we need a color that is not in our “base” palate, we reach out to one of these 2 functions:


This function allows us to choose 1 color for the dark theme and one for the light theme.


This function allows you to apply different levels of “brightness” to a color depending on weather you are in dark or light themes.

This is very very messy now cause we have enormous amounts of repetition.

The line:

dark-light-choose(scale-color($highlight, $lightness: -50%), scale-color($highlight, $lightness: 50%));

Is repeated 30 or so times in our scss files, and that is only for the 50% color.

The line:

 dark-light-diff($primary, $secondary, 90%, -60%);

Is similarly duplicated in tons of spots.

This mess leads to a few problems:

  • Did I just pick the right line to cut and paste ?

Should I pick dark-light-diff($primary, $secondary, 90%, -60%); or dark-light-diff($primary, $secondary, 90%, -65%); like the polls plugin picked?

  • Why have all this repeated text everywhere?

  • Do we really need these many colors?

How do we make some progress here?

I feel there are a few different options we have here which require some careful thought.

  • Option 1: move to CSS class based coloring, and define colors for each class. Then we could use .dim-text for when we want dim text and so on.

  • Option 2: shorten the functions… eg: have … dark-light(90%) automatically expand to dark-light-diff($primary, $secondary, 90%, -75%) or something along those lines, come up with sane defaults

  • Option 3: define a proper color palate in foundation scss that includes vars for EVERY color we ever are allowed to use and only draw from those vars.

Which of these options sound the most appealing to you? Am I missing anything?

cc @riking @awesomerobot

(Neil Lalonde) #2

I think we can come up with more color variables. This one is very common:

dark-light-diff($primary, $secondary, 90%, -60%)

There must be a name for when you would want to use that… It’s always used as either a border or background color. So maybe it can be a variable named $blendedBorderColor or something like that. (muted? faded?)

I don’t know if we should bother trying to eliminate all uses of dark-light-diff, but we can probably remove most of them with new variables.

(Kris) #3

The large multitude of individual colors were replaced with a small number of color variables, which makes it simple to configure in the GUI… but the functions increased complexity significantly and made it all pretty confusing to maintain… plus the output is still a lot of individual colors. Agree with you :100:

Taking a quick look at CSS stats for meta… and the root problem is still probably that Discourse uses too many individual colors.

Look at all those grays! 10 reds! 8 greens!

Definitely worth standardizing further:

  • stick with our 10 (or less) base color variables
  • simplify the number of output colors we actually need to use
  • put those base variables into a consistent set of functions to manage the theming logic

Example: Take that base $danger and output it to X variations of $danger and those are the only variations of $danger used everywhere (maybe a $danger-dark, $danger, $danger-light kind of structure?). This kills the open-ended ability to define a 90% or 95% or 85%. The trickiest part is knowing what’s dark/light background so you can layer dark/light text on top in a legible way. Maybe something to do with comparing relative color luminance?

(Kris) #4

I’m going to think about it some more… but something like a high/medium/low contrast option which uses $secondary as the default basis for comparison, with the option to override $secondary…

/* compares $X to $secondary — if contrast is high don't change $X, 
if contrast is not high scale-color $X until contrast is high */

color: contrast($X, high); 

/* compares $X to $Y — if contrast is low don't change $X, 
if contrast is not low scale-color $X until contrast is low */

background: $Y; 
border-color: contrast($X, $Y, low);

contrast() would determine the contrast ratio between $X and $secondary (or $Y) and then scale-color $X based on high/med/low variable… so there’s no open ended 1-100% to scale-color (which we do twice per color declaration right now) we’re only using pre-determined high/med/low contrast to appropriately color various elements away from the background color…

(Jeff Atwood) #5

I think this is too critical to outsource; we need to start cleaning this up ASAP, @sam should lead and recruit whoever he needs.

I’d start with consolidating all the repetition into a few buckets grouped by intensity

  • dark_light_high
  • dark_light_med
  • dark_light_low
  • dark_light_very_low

etc and forcing changes where we had one that was inexplicably “not quite medium” into medium.

(Kris) #6

Turns out someone has essentially already built what I was thinking of. This always assumes you want an acceptable level of contrast (by WCAG standards) — but should be adaptable to set different contrast levels for things like borders/inactive buttons, etc

User summary stats text colour not matching theme
(Jeff Atwood) #7

Ok as long as it is adaptable, text readability contrast is a far cry from separator bars between posts, etc.

(Kris) #8

I was toying with this

but turns out someone else already nailed it

This scales contrast up to X minimum, but should be modifiable to keep it within a range (for when we want to bring in low-contrast borders and such)

(Sam Saffron) #9

Any news on this, I definitely want to clean stuff up internally for 1.9 but we are going to have to pick some sort of pattern to follow here.

(Kris) #10

My past few weeks have been pretty hectic at home and at work, but I think they’re calming down a bit now. As a first step I can start this weekend with a general clean up/simplification as suggested by @codinghorror above. That should generally reduce any color work going forward. Let’s see where I get with that and I’ll give a status update Sunday night.

(Kris) #11

I just pushed to my fork for now if anyone’s curious — I cut things down to a dozen total dark-light-diff variables, e.g.:

$primary-low: dark-light-diff($primary, $secondary, 90%, -65%);
$primary-medium: dark-light-diff($primary, $secondary, 50%, -20%);

I need to do some more thorough testing on this to make sure I didn’t cut too much. There were over a dozen variants of dark-light-diff for $primary alone.

This also doesn’t yet encompass dark-light-choose.

So. many. colors. :rainbow:

(David Taylor) #12

I realise it’s very nitpicky, but since this PR was merged today, @mentions seem to have lost a lot of contrast. This makes them quite hard to read on some screens.



(Joshua Rosenfeld) #13

I just noticed the same thing, was trying to determine what changed.

(Sam Saffron) #14

@awesomerobot :arrow_backward: can you take care of this :star_struck:

(Kris) #15

@david - thanks for nitpicking!

(Sam Saffron) #16

This style really really stands out, old one had a muted black, I find it a bit distracting.

I wonder if we should just go with the same color we use for users in the header there?

(Kris) #17

The base text color seemed like the simple go-to, but it definitely stands out more than it used to.

I have no qualms with using the user color instead.

(Leo McArdle) #18

Is further simplification planned here?

From a theme development perspective getting full control over the colours used in Discourse is still quite painful. To take the tertiary colour as an example, there’s still 30 instances of scale-color($tertiary, $lightness: N%).

I’d rather not override every one of those in my custom CSS, and my mad science experiment :man_scientist: overriding the scale-color function to output only a limited, palette defined, set of colours didn’t work.

The best situation from my end would be a complete replacement of the use of scale-color with, for example, $tertiary, $tertiary-low, $tertiary-very-low, etc. alongside the ability to override those variables from a theme.

Override global Sass variables from theme
(Jeff Atwood) #19

I thought @awesomerobot made a serious pass on cleaning these up? Perhaps a few were missed?

(Kris) #20

I cleaned up dark-light-diff specifically as kind of the phase 1 here — dark-light-choose is used a lot, which has nested scale-color functions, as well one-off scale-color/lighten/darken functions used in various places. There are a good 3-5 different ways colors get defined and modified in our sass files.

@LeoMcA is right in assessing that we need to replace all color functions with a singular color system, it just requires going through every color definition and adjusting it to fit a consistent template (without breaking each definition across theme variations).

I can spend some more time on it these weekend and try to eliminate scale-color as a next step, I think that’s probably the next biggest color headache after those crazy long dark-light-diff functions that were being used.