Google Extension Effect with CSS or jQuery or MooTools JavaScript

By  on  

Both of the two great browser vendors, Google and Mozilla, have Extensions pages that utilize simple but classy animation effects to enhance the page. One of the extensions used by Google is a basic margin-top animation to switch between two panes: a graphic pane and a detail pane. I've taken a few moments to duplicate that effect with just CSS, and another enhanced version with jQuery and MooTools.

The Base HTML and CSS

I'm using minimal elements within this code since, theoretically, there would be many of these on a given page and large DOM trees can drastically effect page performance:

<div class="item">
	<a href="/angry-birds">
		<div class="item-billboard">
			<img src="angrybirds.jpg" />
			<h3>Angry Birds</h3>
		</div>
		<div class="item-detail">
			<p>There's more detail about the item inside this DIV!</p>
		</div>
	</a>
</div>

Remember that HTML5 says we can wrap block-level elements with A tags, so don't hate on me!

There's a fair amount of base CSS we need too:

.item {
	position: relative;
	width: 240px;
	overflow: hidden;
	border: 1px solid #ccc;
}
	.item {
		height: 200px;
	}
	
	.item a {
		text-decoration: none;
		color: #000;
	}
	
	.item-billboard, .item-detail {
		padding: 10px;
		height: 180px;
	}
	
	.item-billboard {
		margin-top: 0;
		background: #fff;
	}
		.item-billboard h3 {
			font-size: 13px;
			font-weight: bold;
			color: #262626;
			font-family: "Open Sans", arial, sans-serif;
		}
	
	.item-detail {
		background: #ececec;
	}

The only restriction with the CSS above is that we're explicitly setting a lesser height for the billboard and detail blocks because we're adding padding to them. We could use the full 200px height of the parent for each of those blocks, and wrap the content for each in an additional DIV, allowing for animating margin-top to 100%, but that would add 2 extra nodes per block.

The CSS-Only Method

Much like my Google Photo Stack post, the CSS-only version gets us 90% there. Browser-powered CSS animations give us the ability to animate to the second pane...

.item-billboard {
	margin-top: 0;
	background: #fff;
	
	/* add animations! */
	transition-property: margin-top;
	transition-duration: .5s;
}

/* animate on hover */
.itemCss:hover .item-billboard {
	margin-top: -200px;
}

Since the CSS transition settings are on the .billboard elements, the margin will animate both on hover and then back to its original state during mouseleave. Unfortunately you're out of luck if the client doesn't support CSS transitions. That's where we can use MooTools or jQuery to make it happen!

The jQuery and MooTools JavaScript

Overriding the CSS animation with a bit of JavaScript will allow the same animation in older browsers. We can jQuery or MooTools to make that happen:

// MooTools
window.addEvent("domready", function() {
	$$(".itemJs").addEvents({
		mouseenter: function() {
			var billboard = this.retrieve("billboardElement");
			if(!billboard) {
				billboard = this.getElements(".item-billboard")[0];
				this.store("billboardElement", billboard);
			}
			billboard.tween("margin-top", "-200px");
		},
		mouseleave: function() {
			this.retrieve("billboardElement").tween("margin-top", 0);
		}
	});
});

// jQuery
jQuery(document).ready(function() {
	jQuery(".itemJQuery").bind({
		mouseenter: function() {
			var self = jQuery(this), billboard = self.data("billboardElement");
			if(!billboard) {
				billboard = jQuery(jQuery(".item-billboard", this)[0]);
				self.data("billboardElement", billboard);
			}
			jQuery(billboard).stop().animate({
				"margin-top": "-200px"
			});
		},
		mouseleave: function() {
			jQuery(this).data("billboardElement").stop().animate({
				"margin-top": 0
			});
		}
	});
});

In each case, we lazy-find billboard elements when they're hovered over and animate them just as the CSS does. Simple!

I love the design of these blocks by Google. They provide a beautiful default view and allow for more detail when the user shows interest. I can see this strategy and effect being useful in many situations, as behind it is brilliant. A business that sells records could use the same sort of effect, for example. Well done to Google!

Recent Features

  • By
    How to Create a Twitter Card

    One of my favorite social APIs was the Open Graph API adopted by Facebook.  Adding just a few META tags to each page allowed links to my article to be styled and presented the way I wanted them to, giving me a bit of control...

  • By
    CSS Gradients

    With CSS border-radius, I showed you how CSS can bridge the gap between design and development by adding rounded corners to elements.  CSS gradients are another step in that direction.  Now that CSS gradients are supported in Internet Explorer 8+, Firefox, Safari, and Chrome...

Incredible Demos

  • By
    Send Email Notifications for Broken Images Using MooTools AJAX

    One of the little known JavaScript events is the image onError event. This event is triggered when an image 404's out because it doesn't exist. Broken images can make your website look unprofessional and it's important to fix broken images as soon as possible.

  • By
    WebKit Marquee CSS:  Bringin&#8217; Sexy Back

    We all joke about the days of Web yesteryear.  You remember them:  stupid animated GIFs (flames and "coming soon" images, most notably), lame counters, guestbooks, applets, etc.  Another "feature" we thought we had gotten rid of was the marquee.  The marquee was a rudimentary, javascript-like...

Discussion

  1. Alelo

    MT version is the smoothest for me(feeling – Chrome) CSS and jQ are a little bit too fast and dont know, doesnt feel right
    CSS : fasted + “laggy”
    jQ: fast (a little bit too fast)
    MT: perfect(slow and smooth)

    for me

    • Nelson

      I agree with you.
      MooTools has the smoothest experience.

  2. Ah I see you added in stop() to prevent animation queuing! Beat me to it… ;)

    However, can I ask why you have used $.data? Why is there a need to store the element?

    • The alternative is using a query to find the billboard element every time the parent is hovered.

  3. webbeloz

    is an interesting point to make a hidden form .. but the class “item-detail” should stop (fidex) when fully open .. . itemCss: hover. billboard-item {
    margin-top:-200px;
    }

  4. Alex

    For some reason my firefox v11 tab on windows 7 lags somewhat more with mootools than jquery…

  5. A small changes in the example of css:
    A bit more semantic markup, some negative delay with “ease” and another item with “ease-in-out”
    http://jsfiddle.net/kseso/XETSY/2/embedded/result/

  6. I also want to try this effect but i dont have enough knowledge to work with JS and Mootools. Please tell me how and where do i insert the JS code. Please do reply

  7. This works great David, thank you.
    I have implemented it on http://international.anahuacmayab.mx but for some reason on Chrome 21 works buggy (overlapping, blurred text, etc.). The problem seems to happen only when I go to the next billboard before the previous animation ends.
    The Chrome web store actually doesn’t overlap animations, it waits until a billboard’s animation ends before trigger the next one.
    My MooTools skills are very basic. Is possible to delay the billboard’s animation until previous animations ends?
    Thank you in advance.

    • In case someone’s experimenting the same issue, the fix was actually pretty easy. Just added the pseudo :pause(500) to the mouseover event.

      The complete code is like this:

      	$$(".item").addEvent('mouseenter:pause(510)', function(e) {
      		  var billboard = this.retrieve("billboardElement");
      		  if(!billboard) {
      			billboard = this.getElements(".item-billboard")[0];
      			this.store("billboardElement", billboard);
      		  }
      		  billboard.tween("margin-top", "-200px");
      		}
      	);
      	
      	$$(".item").addEvent('mouseleave', function(e) {
      		  this.retrieve("billboardElement").tween("margin-top", 0);
      		}
      	);
      

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!