One feature I was particularly excited about in Twenty Fourteen is the “accent color” which lets you personalize your theme by changing the default green to whatever you like. Unfortunately the feature was removed in #26220, mainly due to the fact that it allowed users to make bad choices, like using a color with a bad contrast, rendering their website ugly and unusable1.
I’ve been thinking about this a lot after that commit, and even more lately. Many themes come with color options these days and the vast majority suffer from the very same problem — poor user choices.
Take Weaver for instance. The options panel will let you adjust the color of probably any single element on your site:
I can’t say I love Weaver’s default look and feel — it’s okay. But it’ll only take a few minutes for an average WordPress user to completely ruin it without even knowing it. Then again, Weaver is a pretty popular theme on WordPress.org and if I had to guess why — it’s the amount of freedom it gives its users via theme options.
But that freedom comes with a price. And I’m not talking about the theme’s pro version, no. I’m talking about the risk users take unknowingly. The risk that could result in poor usability, ugliness and insanely high bounce rates, even if the site looks “just perfect” to the owner.
So how can we protect our users from poor decisions, while still giving them their beloved color options? Providing a predefined set of color schemes is one way of doing it, but this post is about something different.
Contrast Correction with Sass or LESS
You’re probably already familiar with CSS preprocessors, so here’s an interesting piece on accessibility and contrast with Sass and LESS. You can use brightness()
or lightness()
to help you choose better contrasting colors. You can use darken()
and lighten()
to alter your colors for better contrast. You can take it a step further and calculate the color luminance and contrast ratios.
But building your WordPress theme stylesheet with Sass or LESS is one thing. Providing users with an option that could somehow magically change and recompile your CSS is another. One way is to bundle a Sass or LESS PHP-based compiler inside your theme, though I’m not sure if the folks over at the Theme Review Team would be very happy about that.
A better way would be to offload CSS compilation into a plugin, ideally one that’s already active on millions of websites, like Jetpack :)
Jetpack Custom CSS
One of the lesser known features in Jetpack’s Custom CSS module is the availability of both LESS and Sass preprocessors, which means that Jetpack already bundles the necessary PHP libraries, and exposes them via functions, such as jetpack_sass_css_preprocess()
:
$accent_color = get_theme_mod( 'accent_color', '#00ff00' );
$sass = sprintf( '$accent-color: %s;', $accent_color );
$sass .= get_the_rest_of_the_sass_code();
$css = jetpack_sass_css_preprocess( $sass ); // boom!
So in the rest of the Sass code you can use the $accent-color
variable which is defined by the user:
.element {
background: $accent-color;
color: if( lightness( $accent-color ) > 50, 'black', 'white' );
&:hover {
background: darken( $accent-color, 5% );
}
}
Where you get the rest of the Sass code is entirely up to you. You can store it as a string in a PHP file, you can query the file system for the actual Sass file (note that Theme Check won’t let you use file_get_contents()
) or you can even wp_remote_get()
it, perhaps as a fallback if nothing else works.
Sass and LESS compilation can take a while, especially when you start using math functions like pow()
or nthroot()
(you’ll need these for luminance), so make sure you’re not compiling your stylesheets on the fly on every single request.
Instead, you can grab a hash of the color choices, and perhaps the stylesheet version, and cache the compiled CSS forever in a theme mod, and if the colors are changed, you’ll simply overwrite the cached entry.
Example
Semicolon is a magazine theme I released earlier this year. It was built with Sass already, so I simply extracted all the color definitions from the main stylesheet into a new colors.scss file, and then used some basic regex to inject user color values and recompile the stylesheet with Jetpack.
I also added automatic contrast correction which is on by default. So if the user picks bad contrasting colors, Semicolon will lighten or darken them until a contrast ratio threshold is reached. This guarantees a certain level of readability, even if it means drastically changing the user colors, like yellow to almost brown.
So this:
Becomes this:
Obviously this is purely experimental for now, and there are probably some edge cases where users would want to turn Auto Contrast off. For example, in Semicolon you can’t set that sidebar widget fill color to the same color you’ve chosen for your page background. In fact, here’s what happens when you set all three values to white:
Which I don’t think is bad, but it will certainly surprise many users. I guess a little tooltip message about why they’re not seeing the colors they’ve picked could help them understand what we did there.
You can grab the theme from WordPress.org or browse the theme code on GitHub. The Sass magic lives inside css/colors.scss and the compilation and caching code is in functions.php (custom_colors()
method).
It’s not meant to be perfect, but I think it’s a good start. Give it a spin and let me know what you think. You’ll need Jetpack’s Custom CSS module active. If you’re working locally, you’ll want Jetpack’s development mode.
I appreciate your thoughts and comments!
1. There’s a neat plugin for the default Twenty Fourteen theme called Fourteen Colors, which also adjusts contrasts using PHP.