Generating Consistent Hover Effects Programmatically

Submitted by Josh on

A while back, I had a project in which I had a series of buttons that needed to be styled in a rainbow of candy colors, for a list of items that all lead to different spots in the same content hierarchy. The design mockups I was given for the project were detailed but did not appear to be internally consistent from color to color; the base colors were chosen from a brand guide, but the guide did not provide any detail for how to lighten or darken the colors for user interaction states. I started by developing CSS to match the mockups, but the problem kept gnawing at me. If these were solid colors, it would be pretty easy to adjust their luminance using any number of tools that can take a color as input and then adjust its HSL levels equally as needed. Since I was working with gradients, though, doing them manually would be an extremely painful and time-consuming undertaking. While trawling around looking for a programmatic way to get around my frustration, I discovered a five-year-old article by Craig Buckler, How to Calculate Lighter or Darker Hex Colors in Javascript. Using that code as a basis, I then was able to extend the script to work with the awesome CSS Gradient Generator at Colorzilla, which I've used for years as the fastest way to spit out CSS gradients for whatever browsers I'm supporting.

In short, here's what we do here:

  1. Set up an array of hex values to batch convert the colors.
  2. Name the colors for organization's sake, in a second array. These first two steps could also be driven by user input if one wished to build this into a tool with a full browser UI.
  3. Create a function that can ingest these inputs and step through them, producing the desired output.

What happens in the function is largely based on how complex your output gradient needs to be. If you're looking at a gradient in which there are only two stops, and you want the second stop to be 10% lighter than the first, your function will complete quickly. In this particular case, the gradient I needed to create was fairly complex, and I needed to create two of them per color, and not just one - while setting this up, I realized that for maximum consistency I should completely drop the style of the mockups and recreate every gradient using identical parameters, with different base colors. In my version, the script starts with the base color and then builds out two gradients based on the color, forking them immediately so that the second gradient will be exactly 20% higher luminance than the first at all stops. The function will output each gradient two ways - first, as an importable Colorzilla URL so that the designers could see the exact result of the output in a browser, and the second as a string of arguments to be put into a LESS mixin, enabling each of these seven buttons to share a CSS template for ease of maintenance.

See the Pen QjPvGN by Josh Alvies (@Rangers51) on CodePen.

Running this allowed me to iterate through color changes in a matter of minutes instead of roughly a half hour per change, while also giving me the confidence that everything I was doing was as consistent as possible. Between research and development, getting to this point cost me no more than four hours' time, easily paid back between time saved and the level of quality improvement created. While I did this in JS, any language with conversion from and to hex and base 10 would be able to execute the same logic.