Fading CSS background images
Everyone knows CSS hover effects. You can simply define a hover state with CSS and on mouseover the object will change it’s colour, background or other properties to highlight it. While this is easy to use, it gets little more difficult when you want a smoother transition than the one that CSS provides.
Recently I was working on a project with a menu where each menu item had its own background image that would appear on mouseover. I didn’t like the CSS hover and wanted the background to fade in, rather than pop in. Unfortunately CSS background images cannot be faded in, you can either transition a property like background-color, or with fading you would have to fade in the whole element. With a small workaround and a few lines of jQuery I still achieved what I wanted.
The HTML
<ul id="menu"> <li id="menu_1"><a href="/page1/">Page 1</a></li> <li id="menu_2"><a href="/page2/">Page 2</a></li> <li id="menu_3"><a href="/page3/">Page 3</a></li> <li id="menu_4"><a href="/page4/">Page 4</a></li> <li id="menu_5"><a href="/page5/">Page 5</a></li> </ul>
The CSS
#menu {
width: 500px;
float: left;
list-style: none;
padding: 0;
margin: 0;
}
#menu li {
width: auto;
float: left;
position: relative;
}
#menu li span {
position: absolute;
left: 0;
top: 0;
display: none;
z-index: 1;
}
#menu li a {
display: block;
padding: 8px 15px;
position: relative;
z-index: 2;
}
#menu_1 a:hover {
background: url(menu_1.png) 0 0 no-repeat;
}
#menu_2 a:hover {
background: url(menu_2.png) 0 0 no-repeat;
}
#menu_3 a:hover {
background: url(menu_3.png) 0 0 no-repeat;
}
#menu_4 a:hover {
background: url(menu_4.png) 0 0 no-repeat;
}
#menu_5 a:hover {
background: url(menu_5.png) 0 0 no-repeat;
}
Each menu item has a background image that only appears on hover. Note the styling for the span element, this will be injected with Javascript.
The jQuery
$(document).ready(function () {
$('#menu li').each(function() {
var li = $(this);
var link = li.children('a');
li.prepend('<span></span>');
li.children('span').css({
'width': link.outerWidth() + 'px',
'height': link.outerHeight() + 'px'
});
});
$('#menu li a').mouseenter(function() {
var link = $(this);
link.prev().css('background-image', link.css('background-image')).next().css('background', 'transparent');
link.prev().fadeIn();
link.unbind();
link.mouseenter(function() {
link.prev().fadeIn();
}).mouseleave(function() {
link.prev().fadeOut();
});
});
});
First a span element is injected before each link tag. The spans then get the same size properties as the links. Then it waits until the user hovers over a link element, grabs the hover background image and gives it to the span element which is then faded in or out.
The code looks kind of complicated, I haven’t found an easier way of grabbing an element’s hover CSS with jQuery. Another reason is accessibility, for browsers without Javascript it will degrade gracefully and users still get to see the CSS hover. With Javascript enabled the backgrounds will fade in and out instead.
Update: I have slightly optimised the code and uploaded a demo here.
Comments
I’m trying to use your technique but something is wrong in may example.
Dou you have a working demo of this? Thanks.
Try https://www.hobartairparking.com.au/. The menu is based on the example here.
I also just added a demo link to the article.