Treehouse

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!

ydkjs-1.png

Recent Features

Incredible Demos

  • Animated AJAX Record Deletion Using&nbsp;jQuery

    I'm a huge fan of WordPress' method of individual article deletion. You click the delete link, the menu item animates red, and the item disappears. Here's how to achieve that functionality with jQuery JavaScript. The PHP - Content & Header The following snippet goes at the...

  • WordPress-Style Comment Controls Using MooTools or&nbsp;jQuery

    WordPress has a nice little effect on the Admin Dashboard where it shows and hides the comment control links when you mouseover and mouseout of the record's container. Here's how to achieve that effect using MooTools or jQuery. The XHTML Notice that we place the links into...

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!