0

I'm trying to make my FAQ container(s) be dynamic/responsive but am having some trouble getting it to work just right.

At the moment, I can open the container but it doesn't retract (or close) if clicked again. Here is what I have:

JS:

$('.faq_container').on('click', function() {
  $(this).find('.faq_up-arrow, .faq_down-arrow').toggle();
  $(this).animate({
    height: $('.faq_container').get(0).scrollHeight
  }, 250, function() {
    $(this).height('auto');
  });
});

Here is a FULL DEMO of above snippet...

An alternative approach I've tried is this:

$('.faq_container').on('click', function () {
    $(this).find('.faq_up-arrow, .faq_down-arrow').toggle();
    if ( $(this).height() != 40) {
        $(this).animate( { height : 40 }, 250);
    } else {
        $(this).animate( { height : 400 }, 250);
    }
});

However, as you can see here, this is based on a "fixed" height rather than setting it to a more dynamic/responsive way...

Here is a DEMO for this other alternative

I'd like to use the first approach if possible, but can't seem to get the div to close back up...

Any help on this would be greatly appreciated!

This Guy
  • 1,666
  • 2
  • 14
  • 21
  • 1
    You're using jQuery so why not use jQuery UI accordions? https://jqueryui.com/accordion/ or Bootstrap collapse https://v4-alpha.getbootstrap.com/components/collapse/#example – gforce301 Apr 21 '17 at 15:54

4 Answers4

0

Use jQuery each() to iterate over the containers. Check if the container is closed using height(). If it is open it, if not set it back to the original height.

fiddle

$('.faq_container').each(function() {
  $(this).on('click', function(e) {

    if ($(this).height() < 41) {

      $(this).find('.faq_up-arrow, .faq_down-arrow').toggle();

      $(this).animate({
        height: $(this).scrollHeight
      }, 250, function() {
        $(this).height('auto');
      });
    } else {

      $(this).find('.faq_up-arrow, .faq_down-arrow').toggle();

      $(this).animate({
        height: $(this).scrollHeight
      }, 250, function() {
        $(this).height('40px');
      });
    }
  });
});
.faqs_container_wrapper {
  width: calc(100% - 40px);
  padding: 0 0 20px 0;
  margin: 20px 20px 0 20px;
  background: #F1F1F1;
  box-shadow: inset 0 1px #FFF;
  border: 1px solid rgba(0, 0, 0, 0.1);
  float: left;
}

.faq_container {
  width: calc(100% - 40px);
  height: 40px;
  padding: 0;
  margin: 20px 20px 0 20px;
  background: #DDD;
  border-radius: 3px 3px 0 0;
  float: left;
  position: relative;
  overflow: hidden;
}

.faq_down-arrow {
  width: 40px;
  height: 40px;
  padding: 0;
  margin: 0;
  background: red;
  position: absolute;
  top: 0;
  right: 0;
  cursor: pointer;
}

.faq_up-arrow {
  width: 40px;
  height: 40px;
  padding: 0;
  margin: 0;
  background: blue;
  display: none;
  position: absolute;
  top: 0;
  right: 0;
  cursor: pointer;
  -moz-transform: rotate(180deg);
  -webkit-transform: rotate(180deg);
  -ms-transform: rotate(180deg);
  -o-transform: rotate(180deg);
  transform: rotate(180deg);
}

.faq_container h3 {
  width: 100%;
  height: 40px;
  padding: 0 5px;
  margin: 0;
  background: #D1D1D1;
  box-shadow: 0 1px #E1E1E1;
  border-bottom: 1px solid #333;
  border-radius: 3px 3px 0 0;
  float: left;
  color: #333;
  line-height: 40px;
  cursor: pointer;
}

.faq_container:nth-of-type(2n) h3 {
  background: #C1C1C1;
}

.faq_container h3 span {
  width: 30px;
  height: 30px;
  padding: 0;
  margin: 5px;
  background: linear-gradient(#E67E22, #D35400);
  box-shadow: inset 0 1px #F39C12;
  border: 1px solid #E67E22;
  border-radius: 50%;
  float: left;
  color: #FFF;
  line-height: 29px;
  text-align: center;
  text-shadow: -1px -1px rgba(0, 0, 0, 0.1);
}

.faq_container p {
  width: 100%;
  padding: 0 20px;
  margin: 20px 0 0 0;
  float: left;
}

.faq_container p:last-of-type {
  padding: 0 20px 20px 20px;
}

.faq_container p a,
.faq_container a {
  color: #C0392B;
}

.faq_container p a:hover,
.faq_container a:hover {
  color: #E74C3C;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="faqs_container_wrapper">

  <div class="faq_container">

    <div class="faq_down-arrow"></div>
    <div class="faq_up-arrow"></div>

    <h3><span title="Question">Q</span> Post question here</h3>
    <p><b><i>Answer</i>:</b> Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer
      here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here.
    </p>
    <p>Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here.
      Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here. Post answer here.
    </p>

  </div>

  <div class="faq_container">

    <div class="faq_down-arrow"></div>
    <div class="faq_up-arrow"></div>

    <h3><span title="Question">Q</span> Post question here</h3>
    <p><b><i>Answer</i>:</b> Post answer here</p>

  </div>

  <div class="faq_container">

    <div class="faq_down-arrow"></div>
    <div class="faq_up-arrow"></div>

    <h3><span title="Question">Q</span> Post question here</h3>
    <p><b><i>Answer</i>:</b> Post answer here <a href="#">Test</a></p>

  </div>

  <div class="faq_container">

    <div class="faq_down-arrow"></div>
    <div class="faq_up-arrow"></div>

    <h3><span title="Question">Q</span> Post question here</h3>
    <p><b><i>Answer</i>:</b> Post answer here</p>

  </div>

  <div class="faq_container">

    <div class="faq_down-arrow"></div>
    <div class="faq_up-arrow"></div>

    <h3><span title="Question">Q</span> Post question here</h3>
    <p><b><i>Answer</i>:</b> Post answer here</p>

  </div>

</div>
sol
  • 22,311
  • 6
  • 42
  • 59
0

First of all, try using .slideToggle().

Then wrap your answer container with <div class="answer">. The rest, check my fiddle here.

nauval
  • 169
  • 1
  • 4
  • 13
  • This solution works on jsfiddle but not in localhost for some odd reason...And no errors are being thrown - Any ideas? – This Guy Apr 21 '17 at 16:35
  • what does 'not working` mean? (don't forget to add `.answer` class to your css) – nauval Apr 21 '17 at 17:55
  • The faq container(s) wouldn't open/close at all - However, I found out why, you took the "fixed" starting height out of the class `.faq_container` - After taking the height out for that class, things started to work. With that said, thanks for the help! – This Guy Apr 21 '17 at 18:40
0

On my website I have some tabs that use the just CSS selectors to show and hide the content, It should be possible to do what you are doing the same way (and has the advantage of not requiring js to work).

HTML:

<div class="collapsable">
 <input type="checkbox" id="faq1" />
 <label for="faq1">FAQ1</label>
 <div>
  Your FAQ goes here!
 </div>
 <input type="checkbox" id="faq2" />
 <label for="faq2">FAQ2</label>
 <div>
  Have fun with it!
 </div>
</div>

CSS:

.collapsable input { display: none }
.collapsable input + label + div { display: none }
.collapsable input:checked + label + div{ display: block; }

.collapsable label {
 cursor: pointer;
 display:block;
}

Fiddle: https://jsfiddle.net/8zstf5ge/27/

A Hettinger
  • 448
  • 2
  • 11
0

Perhaps this.

https://jsfiddle.net/auunkszm/5/

I've added a function that gets the target height, borrowed from this similar SO post. It quickly calculates what the "auto" height should be.

var openClass = 'faq--open';
$('.faqs').on('click', '.faq_header', function() {
  var el = $(this).closest('.faq').toggleClass(openClass),
      content = el.find('.faq_content'),
      shouldOpen = el.hasClass(openClass);
  content.animate({ height: getTargetHeight(content, shouldOpen) }, 250);
});

function getTargetHeight(el, shouldOpen) {
  if (shouldOpen) {
    var currentHeight = el.height(),
        autoHeight = el.css('height', 'auto').height();
    el.height(currentHeight);
    return autoHeight;
  }
  return 0;
}

I've also changed your HTML markup to be easier to work with. Try to avoid float.

<div class="faq">
  <div class="faq_header">
    <h3><span title="Question">Q</span> What the what?</h3>
    <div class="faq_arrow"></div>
  </div>
  <div class="faq_content">
    <p><!-- content --></p>
  </div>
</div>
Community
  • 1
  • 1
savinger
  • 6,544
  • 9
  • 40
  • 57