Treehouse

Fancy FAQs with jQuery Sliders

By on  
jQuery

Frequently asked questions can be super boring, right? They don't have to be! I've already shown you how to create fancy FAQs with MooTools -- here's how to create the same effect using jQuery.

The HTML

<h3>This is question 1?</h3>
<div>
	<p>This is the answer to question #1.  Pellentesque habitant morbi....</p>
</div>
<h3>This is question 2?</h3>
<div>
	<p>This is the answer to question #2.  Pellentesque habitant morbi....</p>
</div>
<!-- more... -->

Simply a series of H3s and DIVs wrapper in one container DIV. Simple, simple, simple.

The CSS

#faqs { position:relative; }
#faqs h3	{ cursor:pointer; }
#faqs h3.active	{ color:#d74646; }
#faqs div   { position:relative; }
#faqs div p	{ padding:0; margin-bottom:15px; }

Nothing out of the ordinary above -- format the elements as though there wont be a jQuery component.

The jQuery JavaScript

$(document).ready(function() {
	$('#faqs h3').each(function() {
		var tis = $(this), state = false, answer = tis.next('div').slideUp();
		tis.click(function() {
			state = !state;
			answer.slideToggle(state);
			tis.toggleClass('active',state);
		});
	});
});

Start by collecting and recursing through all of the H3 elements. Grab the DIV that follows, slide it in, and add click handlers to slide them in and out!

A More Elegant Effect

The above method is the more accessible version. If effects are you priority, the following CSS and jQuery JavaScript variants will make for a more elegant effect by preventing the initial slide in:

#faqs h3	{ cursor:pointer; }
#faqs h3.active	{ color:#d74646; }
#faqs div { height:0; overflow:hidden; position:relative; }
#faqs div p	{ padding:0; margin-bottom:15px; }
$(document).ready(function() {
	$('#faqs h3').each(function() {
		var tis = $(this), state = false, answer = tis.next('div').hide().css('height','auto').slideUp();
		tis.click(function() {
			state = !state;
			answer.slideToggle(state);
			tis.toggleClass('active',state);
		});
	});
});

There you have it. Have fun with your FAQs!

ydkjs-6.png

Recent Features

  • Send Text Messages with PHP

    Kids these days, I tell ya.  All they care about is the technology.  The video games.  The bottled water.  Oh, and the texting, always the texting.  Back in my day, all we had was...OK, I had all of these things too.  But I still don't get...

  • 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...

Incredible Demos

Discussion

  1. It jumps a little at the end of the transition when you expand the answer div, can you use easing or similar to improve this?

  2. I did notice that Alex. It seems to me it’s a jQuery thing, as MooTools doesn’t jump. It’s to do with the P tag having margin or padding — anyone know the preferred jQuery hack for this?

    • Armin Medić

      u can handle that jump with tag instead tag, it works fine

    • Armin Medić

      with instead sorry for the upper reply hah

    • Armin Medić

      woooot!!!! i mean BR tag insted P tag damit

  3. I’m sure I had a similar issue with jumping on a clients site once, I fixed it with fixed height container ( in this example) but with variable length faq answers its not ideal.

  4. I’d put it in a DL if I was you, but nice simple tutorial, and I’d make only one visibile at the time maybe ?

  5. Use padding instead of margin on the P’s and see if that works (that’s what your Moo version does). Although the preferred hack is to only use .slideToggle stuff on element which don’t have margin or padding (and put the padding on things inside of that.

    Also, all the jQuery people out there always go OMG??!! you used the $(this) selector more than ONCE in a function, you should cache that with $el = $(this) and then use the cached version. So:

    OMG??!! you used the $(this) selector more than ONCE in a function, you should cache that with $el = $(this) and then use the cached version.

  6. @Chris Coyier: The problem was happening with P’s as well.

  7. @All: Updated to prevent @Chris Coyier’s OMG-ness.

  8. Guido

    It’s not really smooth, i like spry accordion tabs more.

  9. well done,but only one things: $(this)['slide' + (state ? 'remove' : 'add') + 'Class']('active'); gave me an error.

  10. @xeon: Make sure it isn’t the stupid WordPress quotes around the word “active” — make sure they’re regular single quotes.

  11. @David Walsh: It’s all because of height. If you set the height of each P tag, that won’t happen. Something like

    $('p').each(function(){ $(this).height($(this).height()) });

    should fix.

    @Mohamed Jama: Me too. It’s more semantic.

  12. @David Walsh: this is the error:
    $(this)[“slide” + (state ? “remove” : “add”) + “Class”] is not a function

    @http://davidwalsh.name/dw-content/fancy-faqs-jquery.php?version=effect (line 122)

  13. @xeon: Use the updated code above — picture perfect.

  14. Nice post…

    I would have used / elements though – the html would have been more semantically correct…

  15. lol, oops – let’s clarify that :) dd and dt elements would have been more semantically correct…

    Putting a whole bunch of /’s in might be therapeutic to some, but kinda pointless to most :)

  16. Rob Simpkins

    Nice effect, and the height bug is annoying; however isn’t this reinventing the wheel somewhat… jQueryui has the accordion plugin already.

    Just a thought.

  17. Hey David. A couple simple things I would change.

    First, the jumping bug: Add position:relative to your #faqs div, and it will start working as you expect.

    Second, use slideToggle and toggleClass instead of the (clever) ternary operator stuff. Most of the toggle type functions in jQuery take an optional boolean to specify which to run.

    state = !state; 
    answer.slideToggle( state );
    tis.toggleClass( 'active', state );
    
  18. Mike McBrien

    In google chrome dev edition.. version 5.0.317.2 the HTML code does not show in your example html/code blocks.

  19. Also, make sure you apply display:"none" to the inner divs. That will get rid of the jump while the page is loading, then set it back to display:"block" with jQuery after you set the height to zero.

    Example:

    $(".answer").css({ height:0, display: "block"});

    You can also wrap the inner html in the answer div with another div and give the new div the padding.

    Check this screencast out: http://jqueryfordesigners.com/slidedown-animation-jump-revisited/ It solves all your problems.

    Regardless, you have a great blog man! It is basically carved in my RSS reader.

    Cheers,

  20. ALEX

    hmmmm I prefer the mootools effect

  21. daniele

    Hi, maybe you can fix the problem with div height this way (sometimes it works)

    $('#faq div').each(function() {$(this).hide().height($(this).height()); });
    
  22. Why even have a MooTools version? Surely jQuery is so much better for everything?! /troll

  23. That margin jump in jQuery is particularly annoying here. Firefox 3.6.

    It even happens on the jQuery homepage demo D:

  24. @Darkimmortal It does indeed! I contacted Ralph Whitbek about it, and he opened this ticket: http://dev.jquery.com/ticket/6078 It should be fixed at some point soon.

  25. @Douglas Neiner: It’s all fixed.

  26. @Ralph Whitbeck: nope, it’s still here :)

  27. @Zy @Ralph Whitbek Its fixed for me in Safari 4 and Firefox 3.5 (whereas it was broken before with the jump) Caching maybe?

  28. @Zy It’s fixed on the jQuery homepage, but still broken on this demo.

  29. This is very a good tutorial. Thanks for posting! By the way there is a problem with the height as some people posted before, but other than that its pretty good.

  30. Nice! jQuery is a great framework, it’s cross browser compatible and lends itself to progressive enhancement very well!

  31. Nicely done. I didn’t experience any issue with the height.

  32. The fix for jQuery’s animation jump can be found on jQuery for designers: http://jqueryfordesigners.com/slidedown-animation-jump-revisited

    It worked for me on a previous project.

  33. Great stuff – I’m building my site as we speak and this will definitely be included in it – I was just checking your pages and BooM dunk. Anyhow, I have a question for ya. When I was selecting tutorial to copy it and read it later (off-line) I noticed that on copied text or whatever you select – your cute LOGO shows up – that probably takes you somewhere to “explain selected field” if I understand correctly coz I couldn’t open that page (maybe it’s a bug problem). I was thinkin CAN YOU PLEASE GAVE US TUTORIAL ON THAT TRICK???? Please

  34. Great stuff – I’m building my site as we speak and this will definitely be included in it – I was just checking your pages and BooM dunk. Anyhow, I have a question for ya. When I was selecting tutorial to copy it and read it later (off-line) I noticed that on copied text or whatever you select – your cute LOGO shows up – that probably takes you somewhere to “explain selected field” if I understand correctly coz I couldn’t open that page (maybe it’s a bug problem).

    I was thinking – CAN YOU PLEASE GAVE US TUTORIAL ON THAT TRICK???? Please and thanks a lot for great stuff as always!

  35. Geler

    @David Walsh: this happen when you slide on a tag with padding or margin. to avoid this you must add a tag. put your p insde a div, slide the div and margin/padding on the p

  36. O ;) nice – lol – sorry. Can you repeat that but in plain English so i could understand something. Please understand. Thanks@Geler:

  37. Here is my stab at FAQs.

    I used definition list for markup

    http://ranjandatta.com/jquery/dlToggle/

  38. Hey, David,

    Any objection to me using the jQuery to showcase another way to use it? I’ll of course give you credit for it. All I did was play with the CSS to see how it could be used as another tool and came up with something potentially handy. Objections? If you could email me, I’d appreciate it, so I can know whether to write up the post & demo on my site.

    Cheers ;)

    Fred

  39. Hey, David,

    Well, I posted it anyway: http://www.skyrocketlabs.com/articles/jquery-social-dropdown-menu.php

    Thanks for the inspiration!

  40. thanks guys, both of ypu. great designers:)

  41. thans guys anyway, at least some of you could tell me “I don’t know “or anything, but anyhow thanks for good lesson learned.

  42. Thanks again David, you nailed it. I am adding a photo gallery and text togglers to one page of a site, the javascripts weren’t cooperating with each other. Once again I turned to your blog for a jQuery alternative and found a better version than what I was using originally. Thanks.

  43. Kenn

    Love it! Exactly what I wanted… and great for my meager skill level. Thanks!

    Ummm… do we know why we can click the white space to the right of the links and have them open? It would be great if that would not be a link over there.

    Any thoughts?

  44. @Kenn: If you’re using h3/h* tags, the white-space is showing that “pointer” cursor because H tags are blocks. Change their display property to “display:inline;”, add a “>br /<” tag after if, and you’ll be set.

  45. Kenn

    Thanks for the fast reply David. Awesome!

    I shoulda thought of that block vs. inline thing!

    Things stopped working when I did as you suggested… but I am sure I did it too fast. Going to work on it again tomorrow when I have time again. Thanks so much.

  46. Brenen

    Is there any way to make the window scroll to the top of the clicked element? I modified your mootools version to do it on an old site and I was looking to change it to jquery. With mootools I added this:

    onComplete:function(){
     var target = el;
     if (!this.wrapper['offset' + this.layout.capitalize()] == 0) new Fx.Scroll(window).toElement(target);
     }
    

    How would you do that with jquery?

  47. Olof

    Is there a way to get rid of not only the white space that is clickable, as Kenn asked about, but everything “to the right”. If you append background color or a frame to the div (or add another div around each Q) this will expand to be as wide as the screen. I want it to behave as a normal div where I can set a min-width and then let it expand depending on the with of the objects in the div. Is there a way to do this?

  48. Matt

    Hey just wanted to know if I can link to a specific FAQ from an email and have that particular FAQ be expanded when page loads? is there anything I can put on the link to tell the script open this FAQ?

    Thanks guys

    • Bruce

      Does anyone have a solution for this, so an external link can anchor to a specific question and expand it automatically?

    • Matt

      I’m guessing this can be done by passing some variable in the url? I don’t know exactly. I asked this question June 2010.

  49. Thanks for this. I am using the Elegant code, but why does it jump? Also, in IE8, the h4 tag collapses so there is no spacing after clicking on one of the questions.

    http://www.onlinemathgrade12345.teachmewell.com/faq.asp

  50. I’ve updated the effect to no longer “jump”. The key is this CSS:

    #faqs { position:relative; }

    Problem solved!

  51. Cintia

    Hi David,

    I never comment, but I love your website!

    I am having problems with my FAQ list. It has more than 17 questions, when I add the 18th, the page goes blank, it doesn’t show any of the previous questions that were in there. Is there a problem with using more than one within a ? This is a WordPress website BTW.

    Any ideas why this is happening?

    Thanks!

  52. Cintia

    I have to fix my comment, the tags aren’t showing up. I meant:
    I am having problems with my FAQ list. It has more than 17 questions, when I add the 18th, the page goes blank, it doesn’t show any of the previous questions that were in there. Is there a problem with using more than one within a
    ? This is a WordPress website BTW.

    Any ideas why this is happening?

    Thanks!

  53. Cintia

    More than one P tag within a DIV…….

    • More than one P element shouldn’t cause any problems.

  54. zef

    how do you make it so that only one answer shows up at any given time?

  55. Is the effect slightly jerky for anyone using FF as opposed to IE or Chrome? It is for me at least. See the bottom of page with FAQ: here and a another implementation: here

  56. Cintia

    I’m again using your fantastic code (thanks), but I’m having a compatibility problem. I have a slider going on in a separate page, and the script for this slider is:

    $(document).ready(
          function(){
              	$('ul#portfolio').innerfade({
                  speed: 1000,
                  timeout: 5000,
                  type: 'sequence',
                  containerheight: 	'130px',
                  slide_timer_on: 	'yes',
                  slide_ui_parent: 	'portfolio',
                  slide_ui_text:		'portfolio-desc',
                 	pause_button_id: 	'pause_button',
                 	slide_nav_id:		'slide_nav'
              	});
              	$.setOptionsButtonEvent();
              
                  
             		$("#pause_button").click(function() {
             			$.pause();
                  });
                  $("#next_button").click(function() {
              		$.next();
                  });
                  
                  $("#prev_button").click(function() {
                  	$.prev();
                  });
                  
              	$("#first_button").click(function() {
                  	$.first();
                  });
                  
              	$("#last_button").click(function() {
                  	$.last();
                  });
    
    });
    

    When I disable this script, the FAQ slider works perfectly. If it’s enable, the FAQ won’t work. Any ideas why?
    Thank you!

  57. Wonderful code!!

    How can I make the script collapse all FAQs before opening the demanded one. I want one to be visible at any one time!

    Thanks! :)

  58. Have answered my own question:

    $(document).ready(function() {
    	$('#faqs h3').each(function() {
    		var tis = $(this), 
    		state = false, 
    		answerNext = tis.next('div').hide().css('height','auto').slideUp();
    		answerAll = $('#faqs').children('div').hide().css('height','auto').slideUp();
    		tis.click(function() {
    			state = !state;
    			answerAll.slideUp(state);
    			$('#faqs').children('h3').removeClass('active');
    			answerNext.slideToggle(state);
    			tis.addClass('active',state);
    		});
    	});
    });
    
    • This is all fantastic – as a complete noob it’s like magic to me ;-)

      However… with your new version, Harry, it does a strange thing if you click on the FAQ’s title that is currently showing – ie, it hides the FAQ and then immediately shows it again, which looks a little odd.

      Do you know how to make sure that the FAQ stays hidden?

      Cheers

    • Thomas Blaye

      Hi Harry Fear,
      I was struggling with the same question as you: close 1 FAQ when opening another. Thanks for finding & sharing the answer!

      There seems to be one thing overlooked in your code though: you can’t close the active FAQ…
      Any ideas?

  59. Bobby

    Any solution yet on IE8 bug? When a question is clicked, all the padding or margins below it are gone, like Jason S above have said.

  60. Phil

    Great tutorial. Like Harry Fear, I’m trying to make it so that only one FAQ shows at a time. I tried his code, but as PeterV commented, if you click the one that is already opens, it just re-opens it. Any ideas on how to fix this?

  61. Joseph

    Hey… I know there’s probably a more elegant way to do this but I added a little tag before the FAQ to override the hight and overflow properties to display content when JavaScript is disabled:

    #faqs div {height:auto;overflow:visible}
    
  62. How can I use this in my WordPress site?
    When I create a new page, I can paste the following text in my page editor in html view –
    This is question 1?
    This is the answer to question #1.
    This is question 2?
    This is the answer to question #2.

    But where to put that javascript code?
    When I tried putting it in the same page in html view, it is simply discarded by WP editor, when the page is published.

  63. Denis Lam

    Hello, the codes seems to work for jQuery 1.4.1 but it doesn’t work for 1.6.1. Does anyone else experience this? Is there any updated code compatible with 1.6.1?

  64. Is this site dumb…
    Why don’t you answer, since long I had put one comment….
    Since then no reply….
    Please help…

  65. Nice script! I’ve been experiencing problems with the jagged animation on my page and finally came to realize that it was due to ‘box-shadow’ element on my page container. I still haven’t found a fix for it, but simply removing it makes it smooth like in the demo.

  66. eddieA

    Hi David,

    Could you use the FAQs in an unordered list? Would the sliders still work?

  67. How would one go about adding “expand all” “collapse all” buttons to the mix?

    Thanks in advance!

  68. Livid

    Thanks for this! Sorry for the newbie question, this works great, but how would I create a hover effect on this as well? So when you hover over the faq it is color:#d74646; as well as when its active?

  69. Hi,

    nice – but I have one big problem with it: Searching on the page using the browser’s search function does not work.
    Collapsed items are invisible to the search. Only if you expand a text box everything is fine.
    This renders that nice idea nearly useless….

    Does anybody have an idea how to change this?

    Cheers
    Andreas

  70. Hello, I am not a developer or a person that understands all of the code speak in this site! :) Are there instructions on how to install this on my WordPress blog for dummies? And believe me, I am the dumbest of them all!

  71. Gary Wayne

    How can I create the click effect without the user click. i.e. I want to open an answer based on a passed URL argument.

  72. Justin N

    I have the same problem as Gary Wayne, Is it possible to open an answer based on the url?

  73. Jacob H

    Got this excellent code working! But, when I try to put each FAQ in a MySQL database, the ‘pull downs’ don’t expose the answer to the question…

    Any thoughts??

    Thanks!

  74. […] I am using the fancy FAQ code found here (the “elegant” version at the bottom to be precise); davidwalsh.name/jquery-sliders […]

  75. Matt

    Hi there. For some reason I am still experiencing the jump effect after the code has been updated to copensate for this? http://justbusiness.pixelblvd.com/faq.php

  76. Hi David, just wanted to say thanks for such as simple and functional piece of code, it helped me a lot.

  77. Amy

    Thanks for this code – it works great. I would love to add a font awesome icon and swap it out when open or closed (or rotate it).

    For example, a right arrow next to the title when it is collapsed that rotates to a down arrow when expanded.

    Thanks!

  78. Awesome, or as my kids would say ‘epic’ coding, thanks for the share. Will be attempting to try and use this a bit later.

  79. Vanessa King

    Love the script, but I’m having the same trouble Dennis Lam is: it only works with jquery 1.4. Any plans on an update? Thanks again for a very useful script!

  80. Vanessa King

    PS, I got rid of that jump that people have had trouble with by putting the CSS in my stylesheet.

    • Vanessa King

      PSS, Sorry, scratch the above! I’d taken the bottom margin out in the document head, but it was still in my style sheet… It turns out it was removing, or even making 0, the bottom margin after all.

  81. Terry

    Hey,

    Great piece of code, quick question, how do I go about speeding up the slide? I’ve tried everything from adding 500 to the slide toggle function to adjusting css easing but nothing seems to make it quicker!

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