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?

Track.js Error Reporting

Recent Features

  • Convert XML to JSON with JavaScript

    If you follow me on Twitter, you know that I've been working on a super top secret mobile application using Appcelerator Titanium.  The experience has been great:  using JavaScript to create easy to write, easy to test, native mobile apps has been fun.  My...

  • Responsive Images: The Ultimate Guide

    Chances are that any Web designers using our Ghostlab browser testing app, which allows seamless testing across all devices simultaneously, will have worked with responsive design in some shape or form. And as today’s websites and devices become ever more varied, a plethora of responsive images...

Incredible Demos

  • Introducing MooTools LinkAlert

    One of my favorite Firefox plugins is called LinkAlert. LinkAlert shows the user an icon when they hover over a special link, like a link to a Microsoft Word DOC or a PDF file. I love that warning because I hate the surprise...

  • Sexy Album Art with MooTools or jQuery

    The way that album information displays is usually insanely boring. Music is supposed to be fun and moving, right? Luckily MooTools and jQuery allow us to communicate that creativity on the web. The XHTML A few structure DIVs and the album information. The CSS The CSS...

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

  • Chris Coyierâs Favorite CodePen Demos II

    Hey everyone! Before we get started, I just want to say it’s damn hard to pick this few favorites on CodePen. Not because, as a co-founder of CodePen, I feel like a dad picking which kid he likes best (RUDE). But because there is just so...

  • GSAP + SVG For Power Users: Motion Along A Path

    Now that the GreenSock API is picking up steam, there are many tutorials and Getting Started guides out there to provide good introductions to the library, not to mention GreenSock’s own Forum and Documentation. This article isn’t intended for beginners, but rather a...

  • Copy a Directory from Command Line

    Copying a directory for the sake of backup is something I do often, especially when I'm trying to figure out why something isn't working when I use an external library.  I'll copy the directory structure as a backup, mess around with the original source until I find a solution,...

  • Hotjar &#8211; All-in-one Analytics and Feedback

    Website analytics are a massive business -- the more data you can collect with regard to your users' behaviors on your site, the more you can increase and maximise conversion...and increased conversion is always good.  Sometimes increase conversion means more money, improved user experience, viewer retention,...

  • Crafting a 3D React Carousel

    There is something in me that is amazed but beautiful 3D interfaces. And it doesn’t matter whether they’re functional like Gyroscope features menu, technology demonstrators like the amazing periodic table demo from famous or they’re artistic representation pushing the limits of...