MightyMeta

fading-button-bg-b

Fading Button Backgrounds 2

| 62 Comments

When Firefox 4 is released this October, February? browsers that support the CSS3 transition property will make up approximately 30% of the market (providing current Firefox users upgrade). With this in mind, it now becomes viable to consider CSS as an alternative to using JavaScript to achieve fading :hover effects on buttons and other interface elements.

Why CSS?

A popular method for fading background images is the ‘Pufferfish’ technique which uses JQuery to append an additional <div> or <span> element to the HTML and animate the fade on :hover using the opacity property. The main issue with this, apart from the reliance on non-semantic HTML, is that the opacity property is inherited by any children of the element that it is applied to. In other words, if you make a button fade on :hover, then any web text that it contains also vanishes.

Here is an example of this problem.

Dragon Interactive, authors of Pufferfish, got around this by using images for text, but this isn’t ideal as it makes pages harder to update, rules out fun with @font-face, and is not so good for accessibility.

I had a go at solving this a couple of months ago, and sort of gave up as the only solution seemed to involve absolute positioning using buttons of fixed sizes, which isn’t suitable for most layouts. I also couldn’t get Internet Explorer to work with it at all (IE Issues now resolved).

Below is where I’ve got to so far using CSS3 transitions to achieve the same result. I’m much happier with this because it involves no extra HTML and just a few lines of CSS. It’s a work in progress, and still has some caveats, but it seems like a more elegant solution.

Why Background Images?

Recently there has been a bit of discussion as to how CSS3 could reduce or even eliminate the need for images in web page designs. This is due to new properties that enable things such as rounded corners, drop shadows and gradients to be created procedurally with CSS rather than in an image editor. These methods can go a long way but have their limits if working with a design that requires any sort of texture or complex shading. If this is the case, then background images must be used.

Fading between two background images is problematic however. Both JavaScript and CSS3 animations rely on changing numerical values incrementally over time. This works well if you want to move or rotate an element using XY coordinates, or even change a colour using RGB or HSL, but the value for the background-image property is a text string, a URL, so you can’t animate it. opacity has a numeric value, but then you have the issue of web text vanishing.

I looked into inserting additional <span> elements but this doesn’t work so well with CSS as it does with JavaScript, because the :hover pseudo class can not be made to target elements other than those it has selected. To cut a long explanation short, the button text covered up the <span> and prevented it from fading.

Therefore my solution to date codges together a bit of CSS3 transitions with another CSS3 property, rgba, which allows us to animate an element’s opacity without affecting contained elements, but only works on solid colours.

Demo

Download Source Files

Compatibility

  • Firefox 4+, Chrome 4+, Safari 4+ — full support
  • Firefox 3, Chrome 1–3, Safari 3, Opera 9+*, Internet Explorer 9+rgba support only
  • The rest — fallback

*Note: Opera’s current support for the CSS3 transitions module is partial, and doesn’t as yet extend to working with opacity. Info on Opera’s support for transitions is here.

Tutorial

1. First of all, create a background image in your preferred image editor. Below is the one used in this example:

Background Image

You’ll notice that this is a sprite, and that it is fairly large to accommodate text resizing. Neither of these techniques are essential to this method, but are advisable for general site performance and accessibility.

2. Create a standard unordered list for the menu.

<ul id="nav">
   <li><a>Home</a></li>
   <li><a>About</a></li>
   <li><a>Gallery</a></li>
   <li><a>Contact</a></li>
</ul>

3. Style the list in the usual fashion, setting the background image for both the normal and :hover{} states.

#nav {
margin: 0;
padding: 0;
list-style-type: none;
}

#nav li {
display: block;
float: left;
margin: 0 5px;
}

#nav a {
display: block;
padding: 25px 35px;
font-family:Arial, sans-serif;
font-size: 1.2em;
font-weight: bold;
color: #fff;
text-decoration: none;
text-align:center;
background: url(../images/bg.jpg) no-repeat center -200px;
}

#nav a:hover {
background: url(../images/bg.jpg) no-repeat center top;
}

So far this should look identical in every browser:

Fading Menu Step 3

4. Now we can add some CSS3 decorations. These will display in Firefox 3.5+, Chrome, Safari 4+ and Opera 10.5+ and Internet Explorer 9+. Older browsers will default to how the buttons look in step (3).

#nav {
margin: 0px;
padding: 0px;
list-style-type: none;
}

#nav li {
display: block;
float: left;
margin: 0 5px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
-o-border-radius: 10px;
border-radius: 10px;
-moz-box-shadow: 1px 1px 1px #666;
-webkit-box-shadow: 1px 1px 1px #666;
-o-box-shadow: 1px 1px 1px #666;
box-shadow: 1px 1px 1px #666;
}

#nav a {
display: block;
padding: 25px 35px;
font-family:Arial, sans-serif;
font-size: 1.2em;
font-weight: bold;
color: #fff;
text-decoration: none;
text-shadow: 1px 1px 1px #666;
text-align:center;
background: url(../images/bg.jpg) no-repeat center -200px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
-o-border-radius: 10px;
border-radius: 10px;
}

#nav a:hover {
background: url(../images/bg.jpg) no-repeat center top;
}

Fading Menu Step 4

5. Finally, the code for the fading transition is added. How this works will be explained below:

#nav {
margin: 0px;
padding: 0px;
list-style-type: none;
}

#nav li {
display: block;
float: left;
margin: 0 5px;
background: url(../images/bg.jpg) no-repeat center top;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
-o-border-radius: 10px;
border-radius: 10px;
-moz-box-shadow: 1px 1px 1px #666;
-webkit-box-shadow: 1px 1px 1px #666;
-o-box-shadow: 1px 1px 1px #666;
box-shadow: 1px 1px 1px #666;

}

#nav a {
display: block;
padding: 25px 35px;
font-family:Arial, sans-serif;
font-size: 1.2em;
font-weight: bold;
color: #fff;
text-decoration: none;
text-shadow: 1px 1px 1px #666;
text-align:center;
background: url(../images/bg.jpg) no-repeat center -200px;
background: rgba(80, 125, 200, 0.55);
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
-o-border-radius: 10px;
border-radius: 10px;
-webkit-transition: background 0.5s linear;
-moz-transition: background 0.5s linear;
-o-transition: background 0.5s linear;
transition: background 0.5s linear;
}

#nav a:hover {
background: url(../images/bg.jpg) no-repeat center top;
background: rgba(100, 125, 175, 0);
}

Three things have happened here.

Firstly, on line 11 of the code above, an additional background property has been added to #nav li, giving it the same background image as #nav a:hover.

Secondly, additional background properties with rgba values have been set for both #nav a and #nav a:hover. rgba lets us set a solid bluey-grey colour for a background, and also specify an alpha transparency level, from 1 (fully opaque) to 0 (fully transparent).

In this example, the :hover rule set to 0, whereas #nav a is given the value of ‘0.55′. This makes the bluey-grey colour semi-opaque and allows the textured image declared in #nav li to show through, appearing darker and greyer than normal.

The difference between these two opacity values can now be animated, giving a fading image effect.

Apart from not being inherited by child elements, the rgba property is useful because if the browser recognises it, the solid colour will be used in place of the background image originally declared in that rule. Yet if the browser doesn’t support rgba, the background image remains intact, allowing you to create fallbacks for older browsers without the use of hacks, conditional comments or browser detection scripts.

Thirdly, the transition properties for each vendor are added on lines 39–42. The syntax in this case is pretty straightforward:

transition: background 0.5s linear;

‘background’ specifies the property that you want to animate.

‘0.5s’ states how long you want the animation to last for, in seconds (more intuitive than JS’s milliseconds? — discuss…)

‘linear’ specifies the timing of the transition. It is possible to create ease-in and ease-out timings. The current state of the W3C spec regarding transition timing is here and a useful tutorial/demo by Richard Bradshaw can be found here. Linear is the bog-standard default option.

Here’s a link to a demo of the final result again:

Demo (best viewed in FF4, Chrome or Safari)

Conclusion

The result isn’t a true fade between two background images (the only way to achieve this cross-browser is using JS using this method), but it does give the impression of being so, and allows us to create flexible buttons with a bit of texture, without extra markup. What it can’t do is simulate a fade between two completely different images, oh well :(

The menu can be edited dynamically by simply altering the HTML, which means it can be incorporated into a CMS template, can be enlarged for disabled users and is screen reader and search engine friendly. It also reverts back to a non-fading version if browser support isn’t there, which at the moment will be about 70% of the time, although this will improve as adoption of the transition property increases.

If you enjoyed this post, please consider sharing it using the above buttons, leaving a comment or subscribing to the RSS feed.

62 Comments

  1. nice menu, so simple and clear in explanation
    thanks ^^

  2. Pingback: Filling Websites With Unique Content.

  3. Great effect and well explained. I like seconds.

  4. Pingback: iWeb Master Class Part 1.2 :Apple On The Longtail

  5. Pingback: Effetto fade sui pulsanti con i css3!

  6. Pingback: Weekly Design News – Resources, Tutorials and Freebies (N.49) :Speckyboy Design Magazine

  7. Hi, really appreciate this.. i am wondering can i use this to fade an image in when hovering over ? i work with vBulletin 4 styles and the forum-rows lately ive been using a different color when hovering over.. but would be nice if i could fade an image in on mouse over.

    Thanks, bookmarked and will check back soon for help on this, Cheers

    • @ Xbox Kinect. Yes it should be possible. Use the same syntax, but select your forum row element instead of what is outlined in this tutorial. The method does rely on there being one element nested within another (in this case an anchor within a list item) If your forum row doesn’t have that, then you may have to add in an extra or to your markup, so that you can have the image hidden behind a colour.

  8. Thanks for u r information

    its very useful

  9. Pingback: 50 Refreshing CSS Tutorials, Techniques and Resources :Speckyboy Design Magazine

  10. Thanks for the nice information. I am sure, I will tweet this to my twitter account. This will help a lot of users.

  11. Pingback: August’s Best Resources for CSS3

  12. Pingback: 60 Awesome Tutorials, Tricks, and Tools that will Make You a CSS Master | Tech King

  13. another awesome tutorial. it was so nice to read and easy to follow.

  14. Great effect and well explained. I like seconds.

  15. Thanks for the info

  16. Thanks for the post. I like new properties, I will implement for Mac users, hopefuly Firefox upgrade.

  17. Thank you very much for the post.

  18. Nice reference before designing background. A good BG needs lots of thinking and work.

  19. I keep checking the website for new tuts but this one has been very interesting and knowledge full . GREAT guys keep it up

  20. Hey James,

    I was able to accomplish a little more of an actual fade with the images. If you were to nest elements inside of the anchor tag, you can fade the opacity in or out on those sub items base on the hover state of your parent.

    <a href="#" class='myButton myStyle_TransparentHover'><span>&nbsp;</span><strong>Remove Alert</strong></a>

    Putting my text inside a second element inside of the anchor tag (the strong tag) is required so that my background image isn’t fading in over my text. The span tag is placed absolutely inside the anchor tag, and has its width set to 100%, so it will match width wise with whatever you do with the strong tag. The only trick is the height. You could hard code that, but I use a nbsp and match the font size and padding of my strong.

    I know its a lot of work, but the effect is beautiful.
    http://screencast.com/t/ZU2AxY6fgw

    .myButton {
        display: inline-block;
        *display: inline;
        *zoom:1;
    }
    .myButton.myStyle_TransparentHover {
        position: relative;
        color: #4C4C4C;
    }
    .myButton.myStyle_TransparentHover span {
        border: 1px solid #A7C3CC;
        color: rgba(0,0,0,0);
        display: inline-block;
        *display: inline;
        *zoom:1;
        background: transparent url(/i/ui/button/transparent-gradient.png) left top repeat-x;
        border-radius: 3px;
        -webkit-border-radius: 3px;
        -moz-border-radius: 3px;
        padding: 5px 0;
        -webkit-background-clip: padding-box;
        position: absolute;
        top: 0;
        left: 0;
        opacity: 0;
        width: 100%;
        padding: 5px 0;
        -moz-transition: opacity .25s linear;
    	-webkit-transition: opacity .25s linear;
    	-o-transition: opacity .25s linear;
    	transition: opacity .25s linear;
    	font-weight: bold;
    	line-height: 1;
    }
    html.ie .myButton.myStyle_TransparentHover span {
        display: none;
    }
    .myButton.myStyle_TransparentHover strong  {
        display: inline-block;
        *display: inline;
        *zoom:1;
        padding: 5px 15px;
        font-weight: bold;
        position: relative;
    	line-height: 1;
    }
    .myButton.myStyle_TransparentHover:hover span {
        opacity: 1;
    }
    html.ie .myButton.myStyle_TransparentHover:hover span {
        display: inline-block;
        *display: inline;
    }
    
    .myButton.myStyle_TransparentHover_Arrow span {
        padding-right: 4px
    }
    .myButton.myStyle_TransparentHover_Arrow strong {
        background: url(/i/ui/list/drop-down/down-arrow.png) right center no-repeat;
        padding-right: 14px
    }
    

    There’s also some extra code to handle hiding and showing for IE without the transition.

  21. With some javascript to simulate menu behavior (mostly adding and removing classes on focus, blur, and clicks):
    http://screencast.com/t/3hsWv2ncU

    You can create some beautiful interfaces with css3 and javascript.

  22. Thanks for the tip on using linear, so use to using ease-in-out I forgot to change the transition type.

  23. Nice work. I appreciate to your work.

  24. very nice work..

    I am just newbie to web design field.…this kind of tutorials help me lot to learn..

    Thank you

  25. It´s very usefull, but, I was looking for something that I think doesn´t exists in CSS3:
    the same effect, but with differents images:




    I tried to add an id to the li element, but it doesnt move at all…

    Anyway, CSS3 is cool!

  26. Is there a way to do this with a transparent first sprite and a colored second half. The effect would be to mouse over a link and have a background appear and then disappear when the mouse is removed.

    • Not using this technique with a background image.

      If you just wanted a solid colour to fade in on hover you can use RGBa and transition between alpha values. Doesn’t work in IE yet.

  27. Very useful information there! I just thought of to became your regular reader but the problem is your sweet blog does not seem friendly when it show in KMeleon browser which I use regularly other than the old school IE 6, hope you can get it fix soon, thanks in advance.

  28. This great, exactly what I was looking for. Just one problem, the buttons turn white after rolling over them in IE9.

    IE7/IE8 both degrade nicely, just IE9 in IE9 Standards mode glitches.

    • I don’t have time at the moment to try, but I can imagine using keyframes would solve this (given IE10 will display properly, since it will support keyframes).

  29. I feel like a dummy.. but inspecting the demo, i only see one part of the image is used. I don’t see the reasen u use a sprite.. lost a lot of time with this

    • Hi Dave,

      The second part of the sprite image is used as a fallback for browsers that don’t support CSS transitions. This isn’t ideal since modern browsers will be loading unnecessary data. Feel free to tidy this up.

  30. Great, My Problem Solved

  31. I’m a beginner on this whole thing of HTML and CSS, my website isn’t even validated by w3c, YET, but I’m working on that..
    But I don’t know what I’m missing, I just can’t get the fading effect, it just keeps on that sliding transition…
    If you could see what I’m doing wrong, I’d be very thankful.

    Here’s the css:

    #botao1 {
    float:left;
    margin:0;
    }
    #botao1 a {
    background:url(images/botao1.gif) no-repeat;
    display:block;
    height:125px;
    width:135px;
    border-radius:8px;
    transition: background .25s linear;
    –moz-transition: background .25s linear;
    –webkit-transition: background .25s linear;
    –o-transition: background .25s linear;
    }
    #botao1 a:hover {
    background-position:-136px 0px;
    border-radius:8px;
    }

    • There is a sliding effect because you are changing the position of the background imagebackground-position:-136px on hover.

      You can’t (currently) transition the opacity of a background image with CSS, which is why the technique detailed in this post uses solid colors and RGBa to fake it.

      • ah.. I see, now I got it.
        I didn’t notice it was a single image and an overlay color, actually I was wondering what was all that “aRGB” about! xD

        Thank u so much, saved me from many future headaches hahaha
        By the way, it’s a great tutorial and I’ll try to use it on some other way! :D
        thanks again!

  32. Hey, that was awesome.… and very helpful too… Thank You…
    :)

  33. Nice post an very well explained.Thank you for sharing this wonderful tips.
    Web Design Service

  34. Works great, thanks for the post :]

  35. you just change color opacity nothing fade image
    when I delete background image line in CSS then there is no change

    so if you have idea to fade background image please share me thanks

    • watch this space — I have a new method for doing this that I will write about soon, using the new WebKit filters with a fallback for FF.

  36. For heaven sakes, write a disclaimer under the title that this is NOT about background-image, but rather about background color that is faking background-image.

    • I think it’s pretty clear if you read the opening paragraph. The title does not mention background-image specifically either…

  37. You have described very clearly with your questions and answers. Thanks!!!

  38. Your blog is clearly explain about the necessary of background images. Thanks for sharing useful information. Website Desing Bangalore

  39. That’s great very well tutorials you have shared here thanks:-)

  40. Hi,
    great tutorial, I hope you are still checking this post. I had it working great following your directions. When I a started to alter it to fit my design part of it stopped working. The animation works fine except the image in my # li a does not show. It only shows the rbga value. my sprite is 74px high, and I have it set like so
    #navMenu li a {
    display: block;
    padding: 11px 12px;
    font-family:Arial, sans-serif;
    font-size: 12px;
    color: #fff;
    text-decoration: none;
    text-shadow: 1px 1px 1px #666;
    text-align:center;
    background: url(../images/nav_sprite.png) no-repeat center –37px;
    background: rgba(80, 125, 200, 0.55);
    –webkit-transition: background 0.5s linear;
    –moz-transition: background 0.5s linear;
    –o-transition: background 0.5s linear;
    transition: background 0.5s linear;
    }

  41. nice post. thanks for sharing this post.

  42. Very good collection of jQuery, Thanks for the information, Those are some cool Script. Sure I will try this

  43. Thanks for the information, Very good information being from the same industry hope it will be useful for us. Thanks

    with regards
    designtheme

  44. Great tutorial and thanks for the information. As you know, the end result has kind of a faded out look as compared to the original image because of the rgb color overlay. Can you suggest any CSS code that would remove the overlay but keep the animation and full vibrancy of the background image? Thanks!

  45. Nice information, There is obviously a lot. Your points are very valuable and knowledgeable. Great site! Thanks!

Leave a Reply

Required fields are marked *.


MightyMeta, 8 St Lawrence Lane, Ashburton, Devon, UK, TQ13 7DD

Powered by WordPress | Theme Derived From "Yoko" by by Elmastudio

Scroll To Top