Cool Flash Effect Without Flash

Sample color slide.

I promise this is something you haven’t seen with Mootools yet, maybe not even JavaScript. My goal was to emulate an effect that you can see over at alician blue. Notice how the blue slides in when you hover over the navigation links. That’s pretty simple, right? Mimicking with Mootools was actually pretty simple too.

First we start off with a standard navigation list:


Here’s the CSS:

#nav {
  margin:1em;
  list-style:none;
}
#nav a {
  font-size:24px;
  font-weight:bold;
  color:#f60;
  text-decoration:none;
}
#nav a span.hover {
  color:#06f;
  position:absolute;
  cursor:pointer;
}

Rather than styling the :hover state of the link, we style a span class, ‘hover’ in this case. It needs to be absolutely positioned because it’s going to be placed on top of the original link. We’ll also set the cursor to pointer for good measure.

Now we have two choices: (1) Just wrap the span in a div and adjust the width of that, or (2) use the clip property. At first, I chose number one, but the effect only slides from left to right, which would achieve the desired result, but why stop there when I can do more? So two it is. Using the clip property will allow us to start the slide from the middle outwards. But there’s a problem. Mootools effects don’t support the clip syntax which looks something like this: clip: rect(20, 100, 100, 20). For more info on using the clip property, try this thumbnail tutorial. Luckily, while searching the Mootools forums, I came across Fx.CSS.Clip. Here’s how I implemented it:

Fx.CSS.select = function(property, to){
  if (property.test(/color/i)) return this.Color;
  if (property.test(/^clip$/i)) return this.Clip;	// this is the line that needs to be added
  var type = $type(to);
  if ((type == 'array') || (type == 'string' && to.contains(' '))) return this.Multi;
  return this.Single;
};

Fx.CSS.Clip = {
  parse: function(value){
    if (value.push) return value;
    var res = value.match(/rect\((\d+)px[,]?[ ]+(\d+)px[,]?[ ]+(\d+)px[,]?[ ]+(\d+)px\)/i);
    if (!res) return [0,100,100,0]; // Anything to give the developer feedback something's wrong
    return [parseInt(res[1]), parseInt(res[2]), parseInt(res[3]), parseInt(res[4])];
  },

  getNow: function(from, to, fx){
    var now = [];
    for (var i = 0; i < from.length; i++) now[i] = Math.round(fx.compute(from[i], to[i]));
    return now;
  },

  getValue: function(value){
    var ret = [];
    for (var i=0; i 0) ret += " ";
      ret += value[i] + "px";
    }
    return 'rect(' + ret + ')';
  }
};

In order for this to work, the creator actually modified the Mootools function Fx.CSS.select. I simply overwrote it in this case because I’d rather not hack the library. Now that we can animate the clip propterty, let’s get started.

window.addEvent('load', function () {
  $$('#nav a').each( function (el) {
    var height = el.offsetHeight;
    var width = el.offsetWidth;
    var mid = Math.round(width / 2)
    var hover = new Element('span', {
      'class':'hover',
      'styles': {
      	'top': el.getTop(),
      	'left': el.getLeft(),
      	'clip': 'rect(0px '+ mid +'px '+ height +'px '+ mid +'px)'
      }
    }).setText(el.getText()).injectInside(el);
    var fx = hover.effect('clip', {'wait': false, 'duration':600, 'transition':Fx.Transitions.Quint.easeOut});
    el.addEvents({
      'mouseover': function () {
        fx.start([0,width,height,0]);
      },
      'mouseout': function () {
        fx.start([0,mid,height,mid]);
      }
    });
  });
});

Let’s get our links with a css selector and loop through each of them. Then we’ll save the values that we’ll be using a lot in some variables. Next we’ll create the overlay span, give it a class, set some styles to place it over the original link and hide it, set its text to the same as the link, and inject it inside the link. Easy peasy.

After that, we create an effect that will alter the clip property values of our overlay span. Almost done now. To start the effect, we just add mouseover and mousout events that adjust the clip appropriately. By changing the clip values, you could have the color slide in from any direction. See it in action below:

15 Responses to “Cool Flash Effect Without Flash”

  1. Ryan

    Wow, that looks impressive Chris. I’d have to say it looks better than the original site, as yours quits changing colors when you hover over it and reverts back. On the other site it completes the color transformation.

  2. Chris

    Yeah, their implementation is actually a little buggy, too. But I’ve seen the effect elsewhere. That’s just the only site I remembered off-hand.

  3. chris

    Nice work, I do like this. Looks nice and runs well and has good compatibility.

  4. Steve

    Can this be implemented inside layers?

  5. Chris

    Steve: Sorry, I don’t understand your question.

  6. gro

    Hi, this is really great effect. Unfortunately I cant get it work with mootools 1.2 (it took me few hours but no effect ;/). I’ve tried to use mootools 1.2 + compatibility script (there is one on mootools.net blog) – it almost worked (no javascript errors in FF), but insted of animation effect I had a lot of javscript warning “parsing error for ‘clip’ property, declaration omitted” (its translated message as I dont use english ang FF).

    Of course I could use mootools 1.11, but then “fade” function from 1.2 doesnt work (doesnt even exists). Unfortunately I need that one.

    Please help if you have a little time to update your great script.

  7. Chris

    gro, I posted the updated script here: http://www.chromasynthetic.com/blog/archive/143

  8. Bill Bartmann

    Excellent site, keep up the good work

  9. Rob S

    Cool effect. Only looks weird when text is selected first then you perform the mouseover while the selection is on.
    Depending on where you selected and stopped (like from the middle of the line above down to the middle of the 3rd “highlight” line) the mouseover effect either highlights or selects text.

    BTW
    I think Steve was asking it this process applies within a div layer. Seems that it wouldn’t work as expected if it uses absolute postitioning.

  1. chromaSYNTHETIC Journal » Blog Archive » Mootools Demo Redux
    Pingback on August 9th, 2007 at 4:02 pm
  2. chromaSYNTHETIC Journal » Blog Archive » Six Flash Effects for JavaScript
    Pingback on September 25th, 2007 at 9:28 am
  3. chromaSYNTHETIC Journal » Blog Archive » What’s New in Mootools 1.2
    Pingback on October 24th, 2007 at 11:21 am
  4. chromaSYNTHETIC Journal » Blog Archive » Mootools 1.2 beta 1
    Pingback on November 16th, 2007 at 9:05 am
  5. [XILED] » Blog Archive » links for 2008-05-20
    Pingback on May 19th, 2008 at 9:35 pm
  6. chromaSYNTHETIC Journal » Blog Archive » Flash without Flash: Color Slide
    Pingback on July 7th, 2008 at 11:10 am