Blog

How to fade a gradient background image with CSS transitions

It turns out you can't fade background images in and out with CSS transitions, you can only move them around.

Table of upcoming events

The Jan 29 event represents the hover state of the table row.

In a recent project, I wanted to apply a CSS transition to the hover state of a table row and some menu items. The problem was that my hover state used a gradient background and I wanted the gradient to fade in and out. Background colors can be faded in, but background images can only be moved around. My solution was to fade in a background color and animate the position of the background image.

When I wanted to fade the hover state of some table rows and menu items that used a gradient image in the background, I had to get a little creative. The transition CSS3 property cannot fade background images, but you can move them from top to bottom, left to right, etc. If you combine these movements with a background color that matches the color your background gradient fades to, you can achieve your desired fade effect.

Check out the source code on my sample page and pick out my staggered CSS, or get right to the meat of it below:

The HTML

We start with a run-of-the-mill unordered list of links:

<ul class="menu">
	<li><a href="#">Item 1</a></li>
	<li><a href="#">Item 2</a></li>
	<li><a href="#">Item 3</a></li>
</ul>

The CSS

First we clean up the list and make it look a little more menu-like:

.menu {
	border: 1px solid #ccc;
	border-width: 1px 0;
	list-style: none;
	margin: 2em 0;
	padding: 0;
	width: 250px;
}

Then we add some girth to the links. I convert them to block level elements, add some padding then set the background-image, but position it outside the viewport. I also add my transition here (omitting vendor prefixes for brevity):

.menu a {
	background: url('../img/gradient.png') 0 -120px repeat-x;
	color: #000;
	display: block;
	padding: 5px 10px;
	text-decoration: none;
	transition: background 0.2s ease-in-out;
}

Finally, I set up my :hover state by setting the background color to the shade of the gradient image that will enter the viewport first. I then set the position of the background-image to the top left corner. The transition effect will fade the background-color from #fff to #ccc while moving the background-image down 120px, which gives the illusion of the gradient fading in.

.menu a:hover {
	background-color: #eee;
	background-position: 0 0;
}

You can play with the timing of the fade by adjusting the position of the background-image in its default state and/or the timing of the transition itself.