A Bit of SASS Magic: Automatic Text Color in CSS

We already talked about SASS and how it can revolutionize your approach to writing CSS. We talked about variables and indenting; powerful features but easy to handle nevertheless. We mentioned that SASS has more advanced functions, and in this article we are going to explore a handy one.


The SASS component 

When designing any website but a small one, a good practice to keep it consistent is to create some standard components and reuse them in many variants. Buttons are a quite typical example since we need many of them and for different purposes and actions. In a multi-step form we have one button for going further and one for going back, and it is definitely a good idea to give them different colors; one reassuring, like green, for the advancing action, and the other to evoke a more neutral feeling (red is a color more suited to other situations, like an important confirmation dialog).

The main purpose of using SASS is to write more efficient and less bloated CSS code. SASS really shines when it comes to writing reusable components: with standard CSS, we design several buttons, each with its own style, while in SASS we can create a general button component, that includes all the variants we need. If we want to take this concept to the next level, we might be annoyed to input a different text color for light and dark button backgrounds; this is a good reason to explore the advanced possibilities offered by SASS functions.

Copy
<button class="button confirmation">Confirmation</button>
<button class="button warning">Warning</button>
<button class="button info">Info</button>
<button class="button confirmation disabled">Disabled</button>
Copy
.button {
  border-radius:8px;
  display:block;
  padding:1em 3em; margin-bottom:6px;
  font-size:100%; font-weight:bold; text-align:center;
  background-image:none;
  border:1px solid transparent;
  -webkit-user-select:none; 
     -moz-user-select:none;
      -ms-user-select:none;
  
  &.confirmation {
    $color:MediumSeaGreen;
    
   background-color:$color;
   color:set-button-text-color($color);
  }
  &.warning {
    $color:DarkOrange;
    
    background-color:$color; 
    color:set-button-text-color($color);
  }
  &.info { 
    $color:DarkSlateBlue;
    
    background-color:$color;
    color:set-button-text-color($color);
  }
  &.disabled { 
    pointer-events:none;
    cursor:not-allowed;
    opacity:0.6;
  }
}

The function

A function in SASS may look similar to a mixin, but a function outputs a value, while a mixin outputs CSS lines we can reuse. Functions bring to SASS some of the logic and features of a programming language like JavaScript, whose syntax is very similar. Back to our idea to automatically set the text color of the button component, a very simple function can be the solution to our problem.

Let's examine our button component: it has a basic button structure and additional classes for the confirmation, warning, info and disabled variants. In each of the additional variant classes, we set the background color as a variable, so that it can be used by our function. The basic concept is to detect the luminance of the background, so that we can use white text for dark background colors and black for the light ones. There's a built-in function in SASS that is called lightness(), and we can use it for detecting the luminance of a color. We call the function with @function, and we give it a name, followed by the name of the variable to evaluate in parenthesis. The rest is pretty straightforward, since we use a simple if statement (must be prefixed by an "@") to check the luminance value of the background color (the exact number is not easy to determine; make some tries) and set the corresponding color for the text.

Copy
@function set-button-text-color($color) {  
    @if (lightness( $color ) > 40) {
      @return black;
    }
    @else {
      @return white;
    }
}

Now that we have defined our function (must be at the top of the document since the variable is declared for the first time), we can use it as a value for the CSS color property, like that: color:set-button-text-color($color). When we use the name of the function as a CSS value, we can specify a value for $color; this adds flexibility to functions, but in this example it makes more sense to declare the background color as a variable and not as a parameter.

More great blog posts from Alessandro Loverde