CSS High-Contrast Selection Border on any Background

TL;DR - With CSS background gradients we can create a lightweight animated border treatment that guarantees sufficient contrast over any background image by mimicking a well-know pattern from traditional desktop software. View result.

The Problem.

Recently I was working with a team member at Braid who needed to solve a client-managed-content user-interface problem. The client in question is able to supply a background image and several foreground images for customizable products on their website. The idea being that as customers make their selections parts of the product represented by the foreground images would swap out to reflect the user’s selections. A cool idea, and a good user experience, but something that proved to be challenging to solve when it came to reliably showing the end-user what item was currently selected for customization.

How do you guarantee you’ll show a high enough contrast selection border when you don’t know the color or brightness of either the foreground or the background images? If you do a single color border how do you know whether it should be a light or dark color without requiring the client to define it for every customizable product? If the contrast ends up being low enough then a user won’t be able to determine which area is selected and may even fail to understand that the product itself has selectable areas for customization. Not ideal.

When the contrast is too low.

Let’s take a look at some pretend products with customizable areas that are user-selectable. Each box has a few selectable areas for customization. We’ll start with 3 boxes, all with the same selectable products: one with a light background, one with a medium-tone background, and one with a dark background. Play with the colors and change the selected products to see the issue at hand.

Live Demo
choose a border color to test

As you can see, it’s difficult to find a color that will work well as a selection color across all the above backgrounds. Even more so if you’re trying to avoid picking an off-brand accent color such as fluorescent cyan or magenta. Keep in mind that these are only three example backgrounds. In real-world usage the client will be able to choose any background color image they want — further complicating the problem.

How can we improve our selection border so that it is distinguishable across all 3 of our demo product boxes?

Two colors are better than one.

A single color is unlikely to solve our problem for our demo product boxes — especially without having to lean on something garishly off-brand. Let’s try to adhere to the subdued color palette for the client's brand and accentuate our active selection without sticking out like a sore thumb.

What happens if we apply 2 borders — one light and one dark — for our selection outline?

Live Demo

That’s an improvement! We can now see that there is a selection border regardless of color and brightness of any client-supplied background. If we’re being honest though this doesn’t look great. In the case of the 2nd box the borders feel noisy because the light and dark borders in our current treatment are both visible and required to occupy different space in our UI. This also means the dashes do not line up visually because the outermost border has to cover more area.

Providing a two-color border treatment has gotten us closer to our goal. How can we make it better?

Marching ants - a well-worn pattern.

If you’ve ever worked with desktop software such as Photoshop that allows you to make selections on top of images then you’re probably familiar with the “marching ants” selection border. It’s a great pattern because the combination of high-contrast border elements and the movement of the border create enough contrast to be visible over any type of background.

Can we recreate this with CSS? Native CSS borders are not going to fit the bill because we cannot animated the border dashes. Also, setting our border to dashed is about all the control we get. There are no CSS properties we can define for the length of the dashes or the amount of offset we would like to have between dashes. But fear not! With some clever use of background gradients and background sizing we can make our own dashed border and we'll be able to provide our desired animation to it. Let’s start with new borders and check our resulting contrast.

Live Demo

The above boxes now have clearly defined selections without the problem multiple offset borders! The 2nd box with the mid-tone background still feels a bit muddy though. Because our selection border is static it melts into the background. This treatment is close but adding in the animation is going to go a long way towards distinguishing the selection border from the background at all times.

Adding some movement.

Let’s create a CSS @keyframe animation to offset the background of our fake borders to give the illusion of the marching ants.

Live Demo

And there we have it! CSS-only marching ants as a selection border in our web application. Now we can unleash our client to supply any combination of background and foreground image elements without needing to worry about case-by-case color overrides. If we’re using a CSS pre-processor such as Sass then we could easily extract our marching ants border into a mixin to be applied on demand.

I've created a Codepen for anyone who cares to see the CSS for this marching ants border treatment

https://codepen.io/boyd/pen/vYGejJB

Feel free to take this example and apply it in your own work.