Jquery - fade out link background hover colour

I have been trying all afternoon to achieve an effect where the background colour of a hovered on link in a list fades out slowly when the mouse rolls off it.

I have found a few tutorials online which are similar to what I want to achieve (but none that are exactly right) like these:

http://stackoverflow.com/questions/808790/jquery-fade-background-on-hover

but despite playing around with them for hours I have had no luck so far… in fact I have yet to have anything have any effect on my links whatsoever!

Here’s the file I am working on

http://www.spiritlevel.co.uk/fadelinktest/listtest.html

I want the background colour of the links in the list to appear immediately on rollover but to fade out over about a second on roll out. I want them to continue fading even when a different link is rolled over so if you whizz up and down the list of links you get a nice gradiated effect with each link’s background colour at a slightly different stage of fading out.

I read that I need the jQuery color plugin to do this but I am not sure if that info is up to date as the links to it are dead on the query site - so I also tried with the core ui plugin which I hope I got right when I went through the custom build process on the query site…

I have had more success with a CSS3 transitions approach which can be seen here:

http://www.spiritlevel.co.uk/fadelinktest/listtest2.html

but this is not ideal for a couple of reasons - firstly as it is css3 it only works in modern webkit browsers and secondly there seems no way to have only a fade out without a fade in - in this example I would like the fade out to be longer but if I increase the transition time from 0.3s then the fade in becomes too long and it feels a bit clunky and unresponsive.

I would really appreciate it if someone could help me get this working - thanks

You don’t need jquery at all to create the fading effects - anyway, jquery is just a bunch of pre-written javascript functions.

You can do all you want with less plain javascript code by setting a setInterval() to progressively alter the value of the opacity of the background.

Thanks webdev1958 but I would rather use jQuery as I am using it for over things on the site and to be honest I wouldn’t know where to start with plain js.

I have been trying and failing again today. Nothing I do seems to have any effect on my links whatsoever - to the extent that I was concerned that jQuery or jQuery colour were not linked properly - but they are.

In case it was not clear from my previous post, the relevant code I have been trying is included on the linked pages, but my server is currently down so I will repeat a simplified version of it here (probably good to do that anyway) in the hope I can get some help figuring out what I am doing wrong.

Here’s one version of the query I am trying…


<script type="text/javascript" src="js/jquery-1.6.4.min.js"></script>
 <script type="text/javascript" src="js/jquery.color.js"></script>
 
 <script type="text/javascript">
var originalBG = $("#projectContent .listings li a").css("background-color");
  var fadeColor = "#008BFD"; 

$("#projectContent .listings li a").hover( function () {
    $(this).animate( { backgroundColor:fadeColor}, 450 )
  },
  function () {
    $(this).animate( {backgroundColor: originalBG}, 950 )
  }
  );
  </script>

Here’s my css


#projectContent .listings{display:block; width:780px; border-top:1px solid #008BFD; margin:0; padding:0; float:left}
#projectContent .listings li{list-style:none; padding:0; line-height:1.6em}
#projectContent .listings li a{display:block; width:780px; color:#969991; text-decoration:none; border-bottom:1px solid #666; float:left; padding:0 0 1px 0;background-color:#F5F5F5; }
#projectContent .listings a:hover{background-color:#008BFD; color:#fff;}
</style>

and here’s my HTML


<div id="projectContent">
<ul class="listings">
<li><a href="*">Another Project</a></li>
<li><a href="*">Year</a></li>
<li><a href="*">Location</a></li>
<li><a href="*">Country</a></li>
<li><a href="*">Area</a></li>
</ul>
</div>

Ideally I would like the fade colour to be specified by the a:hover css rather than the js so could I use something like this instead of the above when setting up the variables?


 <script type="text/javascript">
var originalBG = $("#projectContent .listings li a").css("background-color");
  var fadeColor = $("#projectContent .listings li a:hover").css("background-color");

$("#projectContent .listings li a").hover( function () {
    $(this).animate( { backgroundColor:fadeColor}, 450 )
  },
  function () {
    $(this).animate( {backgroundColor: originalBG}, 950 )
  }
  );
  </script>

I have also tried this


  <script type="text/javascript">
$('.listings li a').hover(function(){
    $(this).stop().animate({backgroundColor: '#f5f5f5'});
}, function() {
    $(this).stop().animate({backgroundColor: '#008BFD'});
});
</script>

but no luck with that either…

Can some please help me out here and tell me what I am doing wrong - thanks

This “off the cuff” and basic plain js version does what you want, if I understand you correctly. (tested in IE9 and FF8)

It might help you sort out your jquery logic.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
        <title></title>
        <style type="text/css">
            #listings {
                width: 200px;
            }
            .bg {
                width: 100%;
                height: 30px;
                background-color: rgb(255,255,255);
            }
            .lnkConts {
                position: relative;
                top: -25px;
                height: 0px;
            }
        </style>
        <script type="text/javascript">
            var speed = 200; //milliseconds for fade interval
            var step = 1;      // fade increment for each iteration

            function fadeOut(obj){
                obj.timer = setInterval(function(){setOpacity(obj);},speed);
            }
            function setOpacity(obj){
                ((obj.curOpac -= step) < 0)? 0 : obj.curOpac;
                if(typeof(obj.style.opacity) == 'string'){
                    obj.style.opacity = obj.curOpac/10;
                } else {
                    obj.style.filter = 'alpha(opacity=' + obj.curOpac*10 + ')';
                }
                if(obj.curOpac <= 0) {
                    clearInterval(obj.timer);
                }
            }
            window.onload=function(){
                var liO = document.getElementsByClassName('bg');
                for(i=0; i<liO.length; i++){
                    liO[i].onmouseover = function(){
                        if(this.timer){
                            clearInterval(this.timer);
                        }
                        this.style.backgroundColor='rgb(222,184,135)';
                        this.curOpac = 10 + step;
                        setOpacity(this);
                    }
                    liO[i].onmouseout = function(){
                        fadeOut(this);
                    }
                }
            }
        </script>
    </head>
    <body>
        <div id="projectContent">
            <div id="listings">
                <div class="bg"></div><div class="lnkConts"><a href="">Another Project</a></div>
                <div class="bg"></div><div class="lnkConts"><a href="">Year</a></div>
                <div class="bg"></div><div class="lnkConts"><a href="">Location</a></div>
                <div class="bg"></div><div class="lnkConts"><a href="">Country</a></div>
                <div class="bg"></div><div class="lnkConts"><a href="">Area</a></div>
            </div>
        </div>
    </body>
</html>

webdev 1958 - First, a big thank you for taking the time to try and help me out with this - I really appreciate your help.

The code you have written is almost what i am after in terms of the effect - the only issue with it visually is that the fade starts happening when you hover over the actual link text when it should stay highlighted - it stays highlighted when you hover over the div that contains the link but if you go over the link itself it starts fading out which shouldn’t happen until you move out of the div area.

However, I need to be able to maintain my html unordered list structure ul/li etc rather than putting each link in it’s own div. I am really after a method that works by animating/fading the css background-color of the (hovered) link as opposed to fading the background of a div which contains it. This would also allow for very simple and graceful degradation if the user did not have javascript running - the css controls the hover style and the javascript animates the css if it is running.

Having struggled with this jQuery version for so long, which does keep the unordered list formatting and (attempts to) animate the links background-color hover, I would still really like to find out what I am doing wrong in that regard and to try and get it working. I just don’t understand why the code I have used above is having no effect…

Thanks for your help and code once again but if you or anyone else can help me with the li a:hover/fade css background-color method I would beextremely grateful.

I have removed that undesirable “feature” :slight_smile:

I haven’t used jquery for years now and I am rusty with it at best. So unfortunately I can’t help you with a jquery solution.

With the way css opacity works, afaik child elements are forced to inherit the opacity of their parent and so I can’t quickly find a solution using your preferred markup.

So, fingers crossed, the animation is now what you want and as a last resort if all else fails, you can use the code below if you don’t have to use your original markup.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
        <title></title>
        <style type="text/css">
            #listings {
                width: 200px;
                background-color: rgb(255,228,181);
            }
            .bgLnk {
                width: 100%;
                height: 30px;
            }
            .lnkConts {
                position: relative;
                top: -25px;
                left: 20px;
                height: 0px;
            }
            .lnkConts a{
                display: block;
            }
        </style>
        <script type="text/javascript">
            var speed = 200; //milliseconds for fade interval
            var step = 1;
            function setupBg4Lnk(obj){
                if(obj.timer){
                    clearInterval(obj.timer);
                }
                obj.style.backgroundColor='rgb(222,184,135)';
                obj.curOpac = 10 + step;
                setOpacity(obj);
            }
            function fadeOut(obj){
                if(obj.timer){clearInterval(obj.timer);}
                obj.timer = setInterval(function(){setOpacity(obj);},speed);
            }
            function setOpacity(obj){
                ((obj.curOpac -= step) < 0)? 0 : obj.curOpac;
                if(typeof(obj.style.opacity) == 'string'){
                    obj.style.opacity = obj.curOpac/10;
                } else {
                    obj.style.filter = 'alpha(opacity=' + obj.curOpac*10 + ')';
                }
                if(obj.curOpac <= 0) {
                    clearInterval(obj.timer);
                }
            }
            window.onload=function(){
                var bgLnk = document.getElementsByClassName('bgLnk');
                for(i=0; i<bgLnk.length; i++){
                    bgLnk[i].onmouseover = function(){
                        setupBg4Lnk(this);
                    }
                    bgLnk[i].onmouseout = function(){
                        fadeOut(this);
                    }
                }
                var aO = document.getElementById('listings').getElementsByTagName('a');
                for(i=0; i<aO.length; i++){
                    aO[i].num = i+1;
                    aO[i].onmouseover=function(){
                        setupBg4Lnk(document.getElementById('bgLnk'+this.num));
                    }
                    aO[i].onmouseout=function(){
                        fadeOut(document.getElementById('bgLnk'+this.num));
                    }
                }
            }
        </script>
    </head>
    <body>
        <div id="projectContent">
            <div id="listings">
                <div class="bgLnk" id="bgLnk1"></div>
                <div class="lnkConts"><a href="url1">Another Project</a></div>
                <div class="bgLnk" id="bgLnk2"></div>
                <div class="lnkConts"><a href="url2">Year</a></div>
                <div class="bgLnk" id="bgLnk3"></div>
                <div class="lnkConts"><a href="url3">Location</a></div>
                <div class="bgLnk" id="bgLnk4"></div>
                <div class="lnkConts"><a href="url4">Country</a></div>
                <div class="bgLnk" id="bgLnk5"></div>
                <div class="lnkConts"><a href="url5">Area</a></div>
            </div>
        </div>
    </body>
</html>
Edit:

This is a slightly better version than the updated code in my last post.

With this, the div’s for the link background don’t need an id.

Off Topic:

fwiw, I think a longer cutoff than the current 30 mins to edit posts would be more beneficial -say 60-90 mins would be more appropriate imho :slight_smile:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
        <title></title>
        <style type="text/css">
            #listings {
                width: 200px;
                background-color: rgb(255,228,181);
            }
            .bgLnk {
                width: 100%;
                height: 30px;
            }
            .lnkConts {
                position: relative;
                top: -25px;
                left: 20px;
                height: 0px;
            }
            .lnkConts a{
                display: block;
            }
        </style>
        <script type="text/javascript">
            var speed = 200; //milliseconds for fade interval
            var step = 1;
            function setupBg4Lnk(obj){
                if(obj.timer){
                    clearInterval(obj.timer);
                }
                obj.style.backgroundColor='rgb(222,184,135)';
                obj.curOpac = 10 + step;
                setOpacity(obj);
            }
            function fadeOut(obj){
                if(obj.timer){clearInterval(obj.timer);}
                obj.timer = setInterval(function(){setOpacity(obj);},speed);
            }
            function setOpacity(obj){
                ((obj.curOpac -= step) < 0)? 0 : obj.curOpac;
                if(typeof(obj.style.opacity) == 'string'){
                    obj.style.opacity = obj.curOpac/10;
                } else {
                    obj.style.filter = 'alpha(opacity=' + obj.curOpac*10 + ')';
                }
                if(obj.curOpac <= 0) {
                    clearInterval(obj.timer);
                }
            }
            window.onload=function(){
                bgLnk = document.getElementsByClassName('bgLnk');
                for(i=0; i<bgLnk.length; i++){
                    bgLnk[i].onmouseover = function(){
                        setupBg4Lnk(this);
                    }
                    bgLnk[i].onmouseout = function(){
                        fadeOut(this);
                    }
                }
                var aO = document.getElementById('listings').getElementsByTagName('a');
                for(i=0; i<aO.length; i++){
                    aO[i].num = i;
                    aO[i].onmouseover=function(){
                        setupBg4Lnk(bgLnk[this.num]);
                    }
                    aO[i].onmouseout=function(){
                        fadeOut(bgLnk[this.num]);
                    }
                }
            }
        </script>
    </head>
    <body>
        <div id="projectContent">
            <div id="listings">
                <div class="bgLnk"></div><div class="lnkConts"><a href="url1">Another Project</a></div>
                <div class="bgLnk"></div><div class="lnkConts"><a href="url2">Year</a></div>
                <div class="bgLnk"></div><div class="lnkConts"><a href="url3">Location</a></div>
                <div class="bgLnk"></div><div class="lnkConts"><a href="url4">Country</a></div>
                <div class="bgLnk"></div><div class="lnkConts"><a href="url5">Area</a></div>
            </div>
        </div>
    </body>
</html>

The 30 minute limit allows people to go back to edit posts, while limiting the amount of abuse that can come from editing older posts after they’ve been replied to.
If you find that you need to edit a post after the 30 minute cut-off, you can flag your post with a comment about what you would like to be adjusted. One of the volunteers here will ensure that the change occurs in a prompt manner.[/ot]

Off Topic:

ok thanks :slight_smile:

webdev 1959

Once again thank you so much for taking the time to help.

I have finally got my preferred method and structure working as someone on another site pointed out my schoolboy error of failing to include thedocument ready function so my js was executing before the body loaded…doh!

For anyone else who finds this thread and is looking for a similar solution, the following code works (providing you have both jquery and the jquery color plugin loaded)


<script type="text/javascript">
$(function () {
var originalBG = $("#ul li a").css("background-color");
var fadeColor = "red"; 

// Without this line the first mouseover isn't animated correctly.

	$("#ul li a").animate({backgroundColor: originalBG}, 0);

$("#ul li a").hover(
    function () {
        $(this).stop().animate( { backgroundColor: fadeColor}, 500 )
    },
    function () {
        $(this).stop().animate( {backgroundColor: originalBG}, 1000 )
    }
);
});
</script>

glad you sorted it out :slight_smile: