Shadow Icons with CSS

The group web page I made for the research group I'm in has a neat design detail. Our group has a presence on various sites, and to link to those, we use those sites' icons. The icons are normally flat and colored the same light blue that we use as a color throughout the design. But when you hover over an icon, it changes color, to be the site's familiar colored logo:


Figure 1: Hovering over a social site's icon makes it colorful

It took a few hours, but I managed to make this effect work totally without any JavaScript, with only one copy of the image, and with pretty simple HTML. The markup for each icon looks like this:

<a href="…" class="icon"><span><img src="…" height="25"/></span></a>

To get the shadow-icon effect with this simple markup, I used the CSS3 filter and mix-blend-mode properties.

Making the icons black-and-white

To make the icons grayscale, I used a filter invocation. Filter allows you to re-color an HTML element using a sequence of “filters”. The first and most important filter I used to create shadow icons is grayscale(100%). This reduces an icon to grayscale-only. This removes the color from the icon, but it doesn't make the icon flat. Of course, the Twitter icon is single-color, as is Facebook's, but Youtube's icon is not totally flat, and I thought the details would be distracting.

To remove the highlights, I then added contrast(500%). I was surprised that you could use percentages over 100% on contrast, but you can! Bumping the contrast this high means that the only colors left are black and white.

Finally, the Twitter icon was too washed out with this invocation. Luckily, I had a Twitter icon with some transparency, so I could just set its filter to brightness(0%). This turns the Twitter icon into pure black, matching the other two.

After setting filter appropriately on the img, I had each icon reduced to purely black and white.

Making the icons light-blue

Purely black and white icons would be pretty noticable on the page, however, and I wanted to color them. But I couldn't use something simple, like color or background, because after all these were transformed images, not text or CSS shapes. Instead, I hit upon using mix-blend-mode. Mix-blend-mode lets you change how the background and foreground colors of an element are combined. Of course, normally you just draw the background, then draw the foreground. But by changing the mix-blend-mode, we can ask the browser to use a different method.

I chose screen, which tells the browser to multiply the foreground and background together, where by multiplying colors, I mean multiplying each color channel separately, treating pure black as 1 and pure white as 0, with transparency being 0 as well.11 It's a weird convention, with a long history. Since I had the shape I wanted, in pure black, I could just set the background color to the light blue color I intended and get a light blue icon.

I set the background on the a, and the mix-blend-mode on the span. This ensured that the background colored the whole icon.

Finally, to get the hover effect, I just undid every CSS property on :hover. Perfect!

It's a weird convention, with a long history.

By on . Share it—it's CC-BY-SA licensed.

Any opinions, findings, and conclusions or recommendations expressed in this material are those of the author and do not necessarily reflect the views of the National Science Foundation.