A few days ago someone mailed me how I made the ‘search’ and ‘about’ tabs that appear on every page on solutoire.com. In this post I’ll explain some techniques like ‘height transitions’ and ‘class toggles’. Sounds pretty hard but you’ll see it’s quite easy. You can see the result at example page 2.

Height transitions

An height transition is an effect that dynamically changes the height of an element. Most of the times such transitions are used to hide or show an element. As you can see I used height transitions for the ‘search’ and ‘about’ tabs. They look pretty flashy but don’t overuse it. It’s annoying for visitors to click everything before they can read/see an elements’ content. Only hide content which isn’t the main aim of a specific page.

Getting started

To get this example working you need at least Moo.js, Utility.js, Function.js, Array.js, String.js, Function.js, Event.js, Element.js, Common.js, Dom.js, Fx.Base.js, Fx.CSS and Fx.Style.js.

Let’s start with a (html)skeleton for the tabs and content elements. We need two ‘(tab)buttons’ to trigger the transition. When a button is clicked we want to show an element. In this example each button needs a content element. To see the skeleton, go to example page 1. The skeleton code will look like this:

<div id=\"contentWrapper\">
	<div id=\"contentElement1\" style=\"display:none\">You pressed button1<br/></div>
	<div id=\"contentElement2\" style=\"display:none\">You pressed button2<br/></div>
</div>
<div id=\"button1\" class=\"button1\">Button 1</div>
<div id=\"button2\" class=\"button2\">Button 2</div>

There’s one important thing that I have to mention right now. The inline style declaration 'display:none' avoids flickering when the page loads. When the 'display:none' is set within a stylesheet the content of the contentElements will show for a millisecond. This is because the browser renders the html and once an element is rendered the browser applies the CSS to it with a small delay. In the next step we’ll add some javascript that sets the style back to 'display:block' when the page loads.
You might also have noticed that the buttons have class and ID declaration. The ID’s are used to select the button elements. The classes are declared to add some CSS magic. I’ll explain this later in the article.

Adding the javascript

This is the javascript we’re adding to have a flashy height-transition -tab-menu-thing:

//select the first button
var button1 = $('button1');
//select the second button
var button2 = $('button2');
//select the first content element
var content1 = $('contentElement1');
//select the second content element
var content2 = $('contentElement2');

//The height transition we attach to 'contentElement1'
var b1Toggle = new Fx.Style('contentElement1', 'height',{duration: 500});
//The height transition we attach to 'contentElement2'
var b2Toggle = new Fx.Style('contentElement2', 'height',{duration: 500});

//add an onclick event listener to button1
button1.addEvent('click', function(){
  //toggle height transition (hide-show)
  if(content1.getStyle('height').toInt() > 0){
    //hide
  b1Toggle.start(0);
  }else{
    //show
    b1Toggle.start(c1Height);
  }
  //toggle classname button1 <-> button1 button1_
  button1.toggleClass('button1_');
  return false;
});

//add an onclick event listener to button2
button2.addEvent('click', function(){
  //toggle height transition (hide-show)
  if(content2.getStyle('height').toInt() > 0){
    //hide
    b2Toggle.start(0);
  }else{
    //show
    b2Toggle.start(c2Height);
  }
  //toggle classname button2 <-> button2 button2_
  button2.toggleClass('button2_');
  return false;
});

//set css display:block for the contentElements
content1.setStyle('display','block');
content2.setStyle('display','block');

//get the scrollSize of the contentElements
var c1Height = content1.getSize().scrollSize.y;
var c2Height = content2.getSize().scrollSize.y;

To see it working you can go to example page 2. Make sure you check out the CSS, it helps a lot.

I think I covered most things in the comments. The height transitions have only one option set and that the duration (set to 500ms). One function I’d like to elaborate on is the toggleClass function. When button1 is clicked 'toggleClass' looks in the element with ID ‘button1′ if the className button1_ exists. When the elements’ className already contains button1_ the className is removed and otherwise it’s added to the class attribute. For example, when contentElement1 is open (or shown) the className of button1 will be ‘button1 button1_’. When the contentElement is hidden again the className of button1 is changed to ‘button1′. In this way you can add different styles to buttons when its’ contentElement is shown or hidden.

I hope you now understand height transitions a bit more and otherwise you can just copy paste the code from the example pages. If you still have questions just drop a comment and I’ll help you out, no problem.