scss font color

6 Magical Steps to Dynamically Change CSS Font Color Based on Background, Using SCSS

When we originally published this post on February 7, 2018, we incorrectly identified this as CSS and not SASS or SCSS. We have since corrected this post to be more specific and accurate.

The day I discovered the ability to change css font color based on the lightness or darkness of the background was the day I realized how magical SCSS can be. Up until then, I thought that could only be handled using JavaScript. Boy was I wrong, and boy was my heart happy!

In my previous post, we discussed how to write an @each loop that combed through a list of colors and applied different background colors to every flash message variant.

Today we’re going to spice things up a little and learn how you can dynamically change your font color based on the background of each flash message.

We’ll start with using all of the same code from my previous post.

I’m not going to go into detail about that code here, but basically this loop is going through each type of flash message and assigning a background based on the instance. The next thing we want to do is change the text color based on the background color for each flash message.

Show me the lightness!

Step 1

First, we need to write a function that will calculate a color’s lightness. lightness( ) does just that! This is a built-in SASS function that calculates the lightness of a color’s RGB value. The value returned by the function is between 0 and 100; 0 being the darkest and 100 being the lightest. Therefore, if the value of the background color returns on the lower end of the spectrum, meaning the background is dark, we would want to set a lighter CSS font color.

@function set-flash-text-color($color: nth($status, 1)) {
  @if (lightness($color) > 60) {
    @return $body-font-color; // Lighter background, return dark color
  } @else {
    @return $white; // Darker background, return light color
  }
}

For this example, I used 60% as the threshold for setting my greater than/less than values. (Note: Most people will start at 50% since it’s halfway between 0 and 100. I used 60 to get my desired color combinations). This was because I wanted the text in Flash--info to be dark, but still wanted the text in Flash--success and Flash--alert to be white (changing the percentage to 50% would affect the success and alert messages).

Step 2

In the @each function we created in my last post, you can now declare the css font color by adding color: set-flash-text-color(nth($status, 2)); after where the background color is set.

@each $status in $flashes {
  .Flash--#{nth($status, 1)} {
    background: nth($status, 2);
    color: set-flash-text-color(nth($status, 2));
  }
}

Step 3

Marvel in the magic! That’s just it. Your css font colors will now change depending on the color of the background!

Step 4

The last thing we need to style is the close button. We want to set the close button to dynamically change both when it is static and when it is hovered. To do this, duplicate the function above twice.

But, we’ll want to make a few changes to the duplicated code:

@function set-flash-close-button($color: nth($status, 1)) {
  @if (lightness($color) > 50) {
    @return $black-30; // Lighter background, return dark color
  } @else {
    @return $white-65; // Darker background, return light color
  }
}

@function set-flash-close-button-hover($color: nth($status, 1)) {
  @if (lightness($color) > 50) {
    @return $black-45; // Lighter background, return dark color
  } @else {
    @return $white-45; // Darker background, return light color
  }
}

First, rename both of the new functions. We’ll call them set-flash-close-button and set-flash-close-button-hover.

Next, I changed the lightness percentage to 50% for both of the close button functions. Again, this is totally subjective to get the desired CSS font color combinations.

Lastly, I adjusted the return values for both close button functions. You can use whichever two colors you wish, as long as one is on the darker spectrum and the other is on the lighter spectrum.

Step 5

Now that we have the two functions created for close buttons, we can add two variables inside of the @each loop.

@each $status in $flashes {
  $flash-close-btn: set-flash-close-button(nth($status, 2));
  $flash-close-btn-hover: set-flash-close-button-hover(nth($status, 2));

Step 6

The last step we have to take is to declare the css font colors for the close button: both for the default state as well as on hover. To do this, we will use the vars we declared in Step 5 and add the styles inside of the @each loop.

@each $status in $flashes {
  $flash-close-btn: set-flash-close-button(nth($status, 2));
  $flash-close-btn-hover: set-flash-close-button-hover(nth($status, 2));

  .Flash--#{nth($status, 1)} {
    background: nth($status, 2);
    color: set-flash-text-color(nth($status, 2));
    .Close {
      @include global-transition;
      color: $flash-close-btn;
      &:hover,
      &:active,
      &:focus {
        color: $flash-close-btn-hover;
      }
    }
  }
}

The whole shebang:

Hopefully this little css font color unicorn-sprinkle of SCSS magic opens your mind into how great the world of SCSS functions can be! Again, keep that code DRY, ya’ll!

We're building an AI-powered Product Operations Cloud, leveraging AI in almost every aspect of the software delivery lifecycle. Want to test drive it with us? Join the ProdOps party at ProdOps.ai.