Min’ blog, an online journal of a Vietnamese desinger

CSS swap hover effect

Posted by Min Tran on 19 Jun 2008. 27 comments

Few months ago, I worked on an e-commerce project whose owner (the client) required each and every of the product photos with information to be displayed in a fancy way. It was requested that the product photo be swapped by its product description when the mouse hovers over it. This kind of effect is very interesting and easy to achieve, so I would like to share it with you.

I made a portfolio page as an example to illustrate how it works. Although it should be done with pure xhtml/css, we will need some minimal work-around to make it right in IE6, which will be mentioned later in this article.

image

Markup

To get into this effect, every project should have two pieces of information. The first piece contains a project thumbnail that will be displayed by default (in normal state). The second piece contains the text/description and this piece of project description should replace the thumbnail when it's in hover state.

image

The markup will look like this

<a class="show" href="#" >
        <img src="images/sdd.jpg" alt="Social Developement Direct" />
</a><div class="hide"><a href="#">SDDirect Website Development</a>
        <p>Design and devevelopment the website and custom CMS for SDDirect</p>
</div>

As you see the code above, the thumbnail is wrapped in the <a class="show">, and the project description (the second piece) is put in the <div class="hide">. There will be more than one project and since they have same structure, the ideal way to display them all is using unordered list. That means that every list item will hold a project detail.

<ul id="work">
  <li> <a class="show" href="#"  title="SDDirect Website Development"><img src="images/sdd.jpg" alt="Social Developement Direct" /></a>
    <div class="hide"><a href="#">SDDirect Website Development</a>
      <p>Design and devevelopment the website and custom CMS for SDDirect</p>
    </div>
  </li>
  <li><a  class="show" href="#" title="Whitehorse Website Design" ><img src="images/whitehorse.jpg" alt="White Horse" /></a>
    <div class="hide"><a href="#">Whitehorse Website Design</a>
      <p>Design and develop XHTML/CSS for The White Horse Inn</p>
    </div>
  </li>
  <li>
    <div class="show"><a href="#" title="Lensview Gallery Design" class="thumb"><img src="images/lenseview.jpg" alt="White Horse"  /></a></div>
    <div class="hide"><a href="#">Lensview Gallery Design</a>
      <p>Photo gallery design and integration for Bach Tran</p>
    </div>
  </li>
</ul>

We've done the markup. Now let’s move to the styling part and add some rock ’n’ roll.

Styling and adding the CSS effect

/* ---- styling the list ---- */
		
#work {
		list-style:none;
		margin:0;
		padding:0;
	}
#work li {
		float:left;
		display:block;
		width:235px;
		margin:10px;
		display:inline;
		padding:3px; 
		background:#fff;
		border:1px solid #cad789; 
		height:154px;
		}
#work li a {
		border:none;
		}
#work p   {
		margin-bottom:0;
		}

The code is quite simple, isn't it? I simply float all the items of the unordered list #work to the left, so every item is a 255px x 1574px box, with 10px gutter (margin: 10px). Now let’s add some CSS magic to achieve the effect we want.

#work li .show{
			display:block;
			width:235px;
			height:154px;
		}
#work li .hide {
			color:#d4df9d;
			text-align: left;
			height: 0;
			overflow: hidden;
			background:#687b00;
		    }

What is the code above about? I use the properties height:0; and overflow: hidden; to ensure that the elements assigned with the class hide should be invisible and so only the elements with class name .show appear. Then I add some following CSS code to show the .hide element and hide the .show element when hovering over each li.

#work li:hover .hide{
			cursor: pointer;
			height: 133px;
			padding:10px;
			width:215px;
		}
#work li:hover .show {
		height: 0;
		overflow: hidden;
		}

I use the active pseudo-class #work li:hover to set some properties for the element .hide every time the mouse hovers on the list item of unordered list work. I simply set the height of the .hide to 153px, then hide .show element by adding overflow: hidden; and the property height:0; to change its height to zero.

It's almost finished. You may check the demo here.

Works fine, but how about IE 6?

The effect acts nicely in Firefox, Safari, IE7 but not IE6. Why? Because IE6 only supports :hover for <a> element, which means #work li:hover would be skiped. We will need some fix to make it perform as well as expected on IE6 and that fix should be this JQuery-based javascript to hook IE6:

<!-- add hover class to #work li if the mouse over -->
<!--[if lte IE 7]>
<script type="text/javascript" src="jquery-1.2.3.min.js"></script>
<script type="text/javascript">$(function() {
		$('#work li').mouseover
			(function(){
			$(this).addClass('over');
		});
		$('#work li&').mouseout
			(function(){
			$(this).removeClass('over');
		});

});
</script>
<![endif]-->

In the script above, simply add a class over into every list item of #work if the mouse moves over it. I also wrap it in the conditional comment to ensure that the script only executes in IE 6 or older IE. What we need to do is adding the properties for #work li.over .hide to make it work in the same way as #work li:hover .hide . So the CSS part should be changed like this:

#work li:hover .hide, #work li.over .hide{
			cursor: pointer;
			height: 133px;
			padding:10px;
			width:215px;
		}
#work li:hover .show, #work li.over .show  {
		height: 0;
		overflow: hidden;
		}

Now everything seems to be solved.

Alternative solution for IE 6

There is an alternative solution to solve the :hover issue in IE6 by using this behavior script whatever:hover. If you want to get rid of javascript, this fix is very easy to use and sure to work perfectly, you only need to add the following code into your markup

<!--[if lt IE 7]>
<style type="text/css">
  #work li { behavior: url(hover.htc); }
</style>
<![endif]-->
Update: D7nh improved this technique with nice solution, the markup is semantic and effect works without Jquery or hover.htc fixes for IE6.

There have been 27 comments so far

Amit 19 Jun 2008

Hopefully one day soon IE6 will be forgotten. Not long for IE8 to come out I hope.

Good one Min! Lovely site and great work.

Min Tran 19 Jun 2008

There are some weird <br> in my source code, I guess the syntax highlighter’s parser causes this problem. I’m working on fixing it.

lekima 19 Jun 2008

Thanks for sharing the trick, I didn’t think it was as simple as that. Cool, man.

Min Tran 19 Jun 2008

@likima: glad to have you here. Thanks for your compliment!

dungiis 19 Jun 2008

Great tuts, Great site,

T 20 Jun 2008

How lovely!

flisterz 20 Jun 2008

Thanks! I’ve always wanted to know the simplest way to fix the :hover thing in IE6 :) nice tutorial

Andy 21 Jun 2008

Thats’ great!  Thanks for this post.  I’m loving everything on your site so far.  Keep it up!

Illustric 22 Jun 2008

Nice tutorial! I am using this for my hosting website. Thanks!

Nguyen Ngo-Huynh 24 Jun 2008

Nice idea!

Martin Möller 24 Jun 2008

Instead of jquery’s mouseover you can also use the hover method which is much more reliable and apropriate for this task.

$("#work li").hover(
function () {
$(this).addClass(’over’);
},
function () {
$(this).removeClass(’over’);
}
);

tmlog 25 Jun 2008

good work…
keep it up

Min Tran 25 Jun 2008

@Martin Möller: Thanks for the tip.

bart 04 Jul 2008

Very nice. Thanks for the tip. I’ve noticed that the third list item’s code is slightly different. In the first two you have LI > A class="show", but in the third you have LI > DIV class="show" > A. Was this done intentionally? Also, when the image is hovered over and the text comes up, the cursor indicates that the whole box is a link, but clicking on the box doesn’t take you anywhere...only the leading text is clickable since it’s a link. Another solution for IE6 (without need for JavaScript) would be to change DIV class="hide" to A class="hide" and replace the P since you can’t have a block-level element inside an inline element. It could look something like A class="hide" > STRONG Lensview Gallery Design >Description. Then you can make the whole box a link.

Just an idea. By the way, beautiful design on your website.

Min Tran 04 Jul 2008

@bart: it’s my mistake, both < div class="show < < a <
and < a class="show"> work fine. However I think remove the div is more semantic. The link doesn’t work because I added the empty uri to < a >

bart 05 Jul 2008

How about just A>IMG>STRONG>description. A:hover IMG {display:none;}. Almost like an image replacement technique.

Jalal 09 Jul 2008

Thank you Min. your blog is really likable, with this theme! :)

Rusti 30 Jul 2008

Any way to put the non-js fix into CSS rather than HTML?

Great tutorial by the way!

asbestos cancer 30 Jul 2008

Great article. I like that the “swap” image doesn’t have to be an image at all, great for minimizing JS and adding SEO’d link text!

examples 10 Aug 2008

CSS “Cascading Style Sheets” Lessons
css list style Properties and examples—http://css-lessons.ucoz.com/list-css-examples.htm

Vanhai Phung 13 Aug 2008

great for web design

Raj 14 Aug 2008

Great article :) Thanx a lot!

Rhett Butler 18 Aug 2008

nice blog. Your way of designing is impressive.

By the way, my father is from Quang Nam ,too.

9 to meet ya!

Toan 19 Sep 2008

uhm, why do you have to use display:inline, display:block in #working li ? float: left alone should do the trick, shouldn’t it?

TuVinhSoft .,JSC 01 Oct 2008

Great post.

Have you guys tried on Chrome?

Thanks
http://www.tuvinh.com

Min Tran 01 Oct 2008

@TuVinhSoft .,JSC: I created this before the release of Chrome. Didn’t test through.

B 07 Oct 2008

Thanks for the great code. However, I am having trouble getting the IE6 fixes to work. You mentioned that D7nh has an updated version, which will work in IE6, but I can’t seem to find it on his site. Can you please include a direct link to view his code?
Thanks!

Comment preview

Your name 06:43 PM
Your comment goes here

Leave a comment

  • Remember my personal information
  • Notify me of follow-up comments?
* is required fields. I do not collect nor use your information.