O'Reilly

Fancy FAQs with MooTools Sliders: Version 2

By on  

A little over a year ago I authored a post titled Fancy FAQs with MooTools Sliders. My post detailed a method of taking boring FAQs and making them more robust using the world's best JavaScript framework: MooTools. I've taken some time to improve my original code for optimal performance and functionality.

The HTML

This is question 1

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae....

This is question 2

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae....

Our MooTools JavaScript will be reliant upon a simple HTML structure of H3s followed by DIVs.

The CSS

#faqs h3	{ cursor:pointer; }
#faqs h3.active	{ color:#d74646; }
#faqs div   {  }

You see I have very little CSS above -- just the bare necessities. It's up to you to make the content even more sexy. Maybe add some tweening on the content DIV when they show and hide.

The MooTools JavaScript

window.addEvent('domready',function() {
	$$('#faqs h3').each(function(header,i) {
		var state = false, answer = header.getNext('div');
		answer.slide('out');
		header.addEvent('click',function(e) {
			state = !state;
			answer.slide(state ? 'in' : 'out');
			if(state) {
				header.addClass('active');
			}
			else {
				header.removeClass('active');
			}
		});
	});
});

We start by grabbing all of the H3 tags within the designated parent element. We then:

  1. Cycle through each heading (the "question")
  2. Grab the next DIV and consider it our "content" container (the "answer")
  3. Slide the answer out of view
  4. Add a click event to the question which will toggle the display of the answer.

Another Take

The above code is accessible but sacrifices a clean effect during normal page load because you see a "flicker" of all of the answers displaying before JavaScript hides them. If accessibility is less of a concern and you want a smoother effect, consider adding the following CSS and JavaScript:

#faqs div	{ height:0; overflow:hidden; }

...and the JavaScript...

window.addEvent('domready',function() {
	$$('#faqs h3').each(function(header,i) {
		var state = false, answer = header.getNext('div');
		answer.slide('out');
		header.addEvent('click',function(e) {
			state = !state;
			answer.slide(state ? 'in' : 'out');
			header[(state ? 'add' : 'remove') + 'Class']('active');
		});
		answer.setStyles({
			overflow: '',
			height: 'auto'
		});
	});
});

This effect is much smoother.

So what do you think? Would you use this on a customer site?

O'Reilly Velocity Conference
Save 20% with discount code AFF20

Recent Features

  • 9 Mind-Blowing Canvas Demos

    The <canvas> element has been a revelation for the visual experts among our ranks.  Canvas provides the means for incredible and efficient animations with the added bonus of no Flash; these developers can flash their awesome JavaScript skills instead.  Here are nine unbelievable canvas demos that...

  • CSS Filters

    CSS filter support recently landed within WebKit nightlies. CSS filters provide a method for modifying the rendering of a basic DOM element, image, or video. CSS filters allow for blurring, warping, and modifying the color intensity of elements. Let's have...

Incredible Demos

  • Fullscreen API

    As we move toward more true web applications, our JavaScript APIs are doing their best to keep up.  One very simple but useful new JavaScript API is the Fullscreen API.  The Fullscreen API provides a programmatic way to request fullscreen display from the user, and exit...

  • Fade Images with MooTools LazyLoad

    I recently received an email from a MooTools developer asking a great question about my LazyLoad class: "I'm using your LazyLoad MooTools plugin (which is great, by the way). I have been trying to figure out how to modify it so that once an image scrolls into...

Discussion

  1. great example, I was using the Accordion to get this effect, but your effect seems to make more sense + it’s much cleaner imo..

    So I will sure be using this, I also like the effect version as I was having the same trouble like the accessible demo.

    One question tho, is the slide something new ? or have I just missed this functionality from the documentation..

  2. Fx.Slide has been around for years! :)

  3. Just a quick idea – wouldnt it be better (for sake of user) to add cursor: pointer with javacsript? Because then if JS is turned off, users wont think it doesnt work (since clicking in h3 would do nothing)

  4. @David Walsh: hahah, yeah I read your previous version after I commented, just a short-hand for Fx.slide in this version.. didn’t know about that!

  5. Alex

    Thanks very much for this David. I’m putting it into a client’s site today and am just experimenting with wrappers around the question/answer pair.

  6. Andreas
    if(state) {
    	header.addClass('active');
    } else {
    	header.removeClass('active');
    }
    

    could be much shorter

    header[(state ?'add' :'remove') +'Class']('active');
    
  7. @Adam Kiss: Yep, good idea.

    @Andress: I considered doing that but the code looks horrendous.

  8. To help with the “accessible” version, if you initially used answer.slide(‘hide’) instead of answer.slide(‘out’), the hiding would be instantaneous, instead of us watching the accordion collapse on load.

  9. @Sean McArthur: I considered that but you can still see a “flash” of the answers in the time before Moo is fully loaded and the domready event fires. I preferred the fold up effect to the “now it’s here…where the hell did they go?” feel.

  10. Thanks for the tutorial. I created a sliding FAQ for a project about six months ago, and my solution wasn’t quite as elegant as this one.

  11. Ed

    Hi David,

    For a long list of questions I wouldn’t think this would be that optimal for usability.
    I’ve found this jQuery FAQ version which would work better for a longer list of questions.

    http://www.bitrepository.com/demo/fancy-faq/

    Is it possible to do something like that with MooTools as well?

    The main usability problem I see is that you when you start fold out questions things can get confusing, it takes more time to scan through to find a question you’ve glanced over and want to check back again for it.

    With the above linked version you can scan through questions and answers much faster.

  12. Ed

    Just found this blog post. :)

    http://davidwalsh.name/smooth-scroll-mootools

    Myself not being a coder, is it difficult to have the light up effect as well applied to a div David?

    Like in the previous lined example?

    Thanks!

  13. ED – doesn’t do the highlight effect but I just put this together to simulate the jquery example you linked to:
    http://mooshell.net/a2ZMP/

  14. @Ed: I’m not big on that verison — there’s far to much down, then up, down, then up with the window. Dizzying for me.

  15. ….and of course exactly the same thing can be achieved with less code using FX.SmoothScroll as per your other demo that @Ed mentioned.

    Anyway, here is what I got to next: http://mooshell.net/gvY3V/
    Quite a lot less code (I posted my first attempt too soon) and does highlight the answer when it is scrolled to as requested by @Ed :)

  16. David, just tested this faq code (your one) with mootools version 1.2.4 and it fails :(
    The faq answers are not being hidden, they just stack up on top of each other.

    This is not the first problem I have encountered with this latest version. As a mootools developer, do you have any idea *why* it doesn’t work?

  17. answer.slide(state ? 'in' : 'out');
    if (state)  {
        header.addClass('active');
    } else  {
        header.removeClass('active');
    }
    

    how about

    answer.slide('toggle'');
    header.toggleClass('active');
    

    ;)

    And thx for using the .getNext() method, i didn’t know it it’s very useful sometimes!

  18. As usual I should investigate things before writing…
    Just found an interesting comment with the reason/solution in the mootools blog about this new version:
    http://mootools.net/blog/2009/10/19/mootools-1-2-4/#more-412
    (see comment by Barryvan)

    Basically this latest release requires you to set the overflow:hidden as per your second demo.
    So this css gets it working in version 1.2.4:
    #faqs div { overflow: hidden;}

    That explains all the probelms I was having yesterday which eventually revert to version 1.2.3 :(

  19. Ed

    @Chris Bolson:

    Thank you so much Chris! :)
    I couldn’t get the “To Top” function working at first, but then I noticed the “go_to_top” class was changed to “to_top” and it works great now!

  20. Ed

    @David Walsh:

    You’re sitting to close to the screen then. ;)

  21. Alex

    Any idea how to get this to work when the FAQ is initially hidden (by another mootools script). The height of the answers is initially ‘auto’ in this scenario (until the H3 is clicked twice).
    It’s not essential for my implementation, but it would be nice-to-have.

  22. Evan

    I have a little trick that I used in the past to solve the flicker problem and still keep the page accessible for users who don’t have JS.

    The flicker is because we wait for domready to fire before you can start to collapse the copy.

    What I do is place a class on my body tag .

    Then I place some script right after the body tag that immediately removes the no-script class from the body. Obviously if the user does not have JS the class will remain on the page.

    You can now style your page differently for users who don’t have JS.

    #faqs div { height:0; }
    .no-script #faqs div { height:auto; }
    

    Because you are removing the class before a load or domready event you can get the flicker to pretty much go away.

  23. I’ll us it on the mobile Mooshell version :D

  24. Here’s a jQuery version for those of us that prefer that framework :

    $(function() {
    	// 1. hide the faqs
    	$('#faqs h3').next().hide();
    	
    	// 2. show when clicked
    	$('#faqs h3').click(function() {
    		$(this).toggleClass('active').next().slideToggle();
    	});
    });
    
  25. Exactly what I was looking for. Excellent!

  26. I’ve rewritten a couple of lines to make the first div active, visible. This is what I came up with:

    	var i = 0;
    	$$('#faqs h3').each(function(header,i) {
    		var state = false, answer = header.getNext('div');
    		
    		if(i > 0){
    			answer.slide('out');
    		}else{
    			state = !state;
    			header.addClass('active');
    		}
    		
    		header.addEvent('click',function(e) {
    			state = !state;
    			answer.slide(state ? 'in' : 'out');
    			if(state) {
    				header.addClass('active');
    			}
    			else {
    				header.removeClass('active');
    			}
    		});
    		
    		answer.setStyles({
    			overflow: '',
    			height: 'auto'
    		});
    		
    		i++;		
    	});
    

    I’ll hope that this is useful for other readers!

  27. @Crispijn: Why not keep my “core” code the same but simply fireEvent(‘click’) on the first item?

  28. @David Walsh: Haven’t thought about that! That’s even better! Thanks

  29. Matt

    Hey guys,

    it’s been some time since i’ve been here but I wanted to know if I had a link within an email can I have this link to the page with the question already open?

  30. Hi David – or anybody here to help me?

    Is it possible:
    1. Turn the animation off?
    2. Click anywhere to close the open part(s)?

    I´m sitting here and can´t get it right…

    Thanks for help!!

    Martin

  31. Eliot Slevin

    i have no experience in js, but is it possible to have one question close when another is opened?

    thanks

  32. Vilius

    Is there a simple way to let only one item active ?

    • Tony Z

      Great stuff. A couple of things I would be interested in.
      1. Code to show all or hide all answers.
      2. Ability to restrict to only show 1 answer at a time (auto close when another question is selected).

      Any

  33. good idea and good work. thanks…

  34. Using this on my site with the following CSS for a nice show hide text change:


    #faqs h3:after { content: " - show"; }
    #faqs h3.active:after { content: " - hide"; }

    Nice one on this simple but powerful little script David! Thanks

    • rolandtom

      Dan, great addition!

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

Recently on David Walsh Blog

  • Prevent Chrome from Translating a Page

    A while back I shared my favorite Google Chrome extension:  Google Art Project.  I've enjoyed seeing beautiful art when I open a new tab -- it's brought genuine happiness to my day, however small that happiness may be.  About a week ago, however, the art presented had...

  • Create Any Type Of Website With These Multi-Purpose Themes

    We have selected what we believe are the very best multipurpose WordPress themes on the market today. Our list contains a number of best sellers, several newcomers that are proving to be highly popular, and a few themes that are ideal for creating the types of...

  • An Introduction to Static Site Generators

    Static site generators seem to have been becoming more and more popular recently, but they’re not one of those ephemeral novelty things that grow in popularity as quickly as they fall into oblivion shortly after. For over a decade, many different projects — 394 of...

  • Automated Tests for Visual Responsive Layouts

    Today it's all about testing. In 2015, many developers knows about TDD and I personally think that testing is one of the key for quality products. But what about testing in a Front-end environment? How do you guys write your tests for a responsive page or...

  • Getting Dicey With Flexbox

    What if you could build complex CSS layouts in minutes? Flexbox is a new CSS layout spec that makes it easy to construct dynamic layouts. With flexbox, vertical centering, same-height columns, reordering, and direction agnosticism are a piece of cake. There's a popular myth floating around that...