SASS Color Function

The custom WordPress themes we build use brand colors for certain design elements and the Gutenberg color palette.

We usually have three versions of each color: the main color, and lighter/darker versions for hover effects. We’ll often auto-generate the lighter/darker versions, but sometimes we need to specify a custom color.

In the past I’ve added all of the colors as their own independent variables:

// Brand Colors
// -- normal / darker / lighter
$blue_1: #59BACC;
$blue_2: darken( $blue_1, 10% );
$blue_3: lighten( $blue_1, 10% );
$green_1: #58AD69;
$green_2: #458D53;
$green_3: #7ABE88;

I’ve recently shifted to using a custom SASS function, brand-color(), that makes it easier to select the color.

a {
	color: brand-color( 'blue' );

	&:hover {
		color: brand-color( 'blue', 'darken' );
}

Inside my theme I define a map of $brand_colors. If you only specify the main color, it will auto-generate the lighten and darken variants. But you can also manually specify your own colors for those.

The list of 6 variables above has been reduce to:

$brand_colors: (
	'blue'		: #59BACC,
	'green'		: #58AD69,
	'green_darken'	: #458D53,
	'green_lighten'	: #7ABE88,
);

And here’s my custom brand-color() function. Take a look at my base theme to see how it’s included.

If you’d like to build your own SASS functions, take a look at the @function documentation.

/**
 * Brand Color
 *
 */
@function brand-color( $key, $variant: null ) {
	@if map-has-key( $brand_colors, $key ) {
		$color: map-get( $brand_colors, $key );
		@if ( 'lighten' == $variant ) {
			$lighten_key: $key + '_lighten';
			@if map-has-key( $brand_colors, $lighten_key ) {
				$color: #{map-get( $brand_colors, $lighten_key )};
			} @else {
				$color: lighten( $color, 10% );
			}
		}
		@else if( 'darken' == $variant ) {
			$darken_key: $key + '_darken';
			@if map-has-key( $brand_colors, $darken_key ) {
				$color: #{map-get( $brand_colors, $darken_key )};
			} @else {
				$color: darken( $color, 10% );
			}
		}
		@return $color;
	} @else {
		@error "The #{$key} color could not be found in $brand_colors";
	}
}

Bill Erickson

Bill Erickson is the co-founder and lead developer at CultivateWP, a WordPress agency focusing on high performance sites for web publishers.

About Me
Ready to upgrade your website?

I build custom WordPress websites that look great and are easy to manage.

Let's Talk

Reader Interactions

Comments are closed. Continue the conversation with me on Twitter: @billerickson

Comments

    • Bill Erickson says

      Correct, SASS requires compiling, but all of our styles are so dependent upon SASS that this is not an issue.

      We use version control and deployment tools like DeployHQ or WPEngine’s git push for pushing code updates, so compiling is not an issue.

      There’s a lot of benefits to using SASS for your styles:

      • Organize your styles into smaller and logical partials (example)
      • Generate multiple stylesheets automatically from the partials. For instance, our editor-styles used by Gutenberg contain a small subset of the overall stylesheet (example)
      • Nesting makes CSS more readable
      • Create mixins for commonly used styles, like my font-sizes( $mobile, $tablet, $desktop ); or columns( $columns, $element, $gap ); for generating CSS grid styling with float-based fallback

      CSS variables are definitely interesting, but I haven’t had a need for the useful features they offer over SASS variables.

  1. Stuart Gamblen says

    Is there a way to call this SASS colour function but pass in a custom darken or lighten percentage that overrides the default?

    I’ve tried this but it doesn’t seem to work:

    border-bottom: 2px solid brand-color( $default, $variant: +17% );

    • Bill Erickson says

      I haven’t figured out how to do it yet. When I need that, I’m using map-get() on the array. Ex: border-bottom: 2px solid darken( map-get( $brand_colors, 'primary_darken' ), 17% );

      • Stuart Gamblen says

        Hi Bill,

        Thanks for the response. I couldn’t figure that out but if it helps anyone else I found a solution using:

        @each $name, $color in $brand_colors {

        &.has-#{$name}-background-color:hover,
        &.has-#{$name}-background-color:focus {
        background-color: brand-color( $name, ‘darken’ );
        border: 2px solid brand-color( $name, ‘darken’ );

        // Bypass the default 10% ‘darken’
        border-bottom: 2px solid darken( $color, 17% );
        }
        }