6

I have a situation where I have for example little boxes which follow each other one after each other and I want users to be able to toggle the show/hide of these elements, I have got them working like I want, but when the respective box is collapsed/hidden the content below it doesn't collapse upwards as well.

I understand why this is however, it's because using transform it still allocates the space for the element that you transformed out of it's original position; however I couldn't work out another way to do it in the same fashion as using a negative margin-top for some reason didn't animate smoothly like transform does.

CodePen: http://codepen.io/gutterboy/pen/GqRoJY

CodePen (margin-top version): http://codepen.io/gutterboy/pen/WxNGVG

HTML:

<div class="foo">
    <header>
        Header
        <a href="#" class="toggle" data-content-id="1">Toggle</a>
    </header>
    <div class="content-wrap">
        <div id="content-1" class="content">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cur id non ita fit? Et ille ridens: Video, inquit, quid agas; Quorum altera prosunt, nocent altera. Nulla erit controversia. Neutrum vero, inquit ille. Quis non odit sordidos, vanos, leves, futtiles?
            Duo Reges: constructio interrete. Quare ad ea primum, si videtur;
        </div>
    </div>
</div>
<div class="foo">
    <header>
        Header
        <a href="#" class="toggle" data-content-id="2">Toggle</a>
    </header>
    <div class="content-wrap">
        <div id="content-2" class="content">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cur id non ita fit? Et ille ridens: Video, inquit, quid agas; Quorum altera prosunt, nocent altera. Nulla erit controversia. Neutrum vero, inquit ille. Quis non odit sordidos, vanos, leves, futtiles?
            Duo Reges: constructio interrete. Quare ad ea primum, si videtur;
        </div>
    </div>
</div>
<div class="foo">
    <header>
        Header
        <a href="#" class="toggle" data-content-id="3">Toggle</a>
    </header>
    <div class="content-wrap">
        <div id="content-3" class="content">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cur id non ita fit? Et ille ridens: Video, inquit, quid agas; Quorum altera prosunt, nocent altera. Nulla erit controversia. Neutrum vero, inquit ille. Quis non odit sordidos, vanos, leves, futtiles?
            Duo Reges: constructio interrete. Quare ad ea primum, si videtur;
        </div>
    </div>
</div>

CSS (SCSS):

.foo {
    margin: 10px;
    width: 400px;

    header {
        padding: 10px;
        border: 1px solid #000;
        border-bottom: 2px solid #000;
    }

    .content-wrap {
        overflow-y: hidden;
        transform-style: preserve-3d;
    }

    .content {
        padding: 10px;
        background-color: gray;
        transform: translateY(0);
        border: 1px solid #000;
        border-top: none;
        transition: 1s;

        &.closed {
            transform: translateY(-100%);
        }

    }

}

JS (jQuery):

$(document).ready(function() {

    $('.toggle').on('click', function(e) {

        e.preventDefault();

        var content_id = $(this).data('content-id');

        $('#content-' + content_id).toggleClass('closed');

    });

});

Is there anyway to get the boxes below to collapse smoothly at the same time the proceeding box does?

Also note that the boxes are variable height and hence we can't use height, want to avoid hacky solutions like using a really high max-height and preferably avoid using any JS for the animation.

Brett
  • 19,449
  • 54
  • 157
  • 290
  • What browser are you using? Second version worked perfectly smoothly for me. (Latest Chrome) – IdeaMan May 28 '16 at 07:57
  • I assume that moving all the div's correlated to the collapsing one could cause some lag. If this is the problem then not much could be done about it. – IdeaMan May 28 '16 at 08:06
  • @IdeaMan FireFox. However I tried it in Chrome and it was the same. It transforms up much faster than down and when you click to show it again there seems to be some form of delay before it starts. – Brett May 28 '16 at 08:29

1 Answers1

1

Your problem, delay at starting due to margin : -100% and the div is still not visible at margin : -40%

and

CSS transition do not animate when you add or remove class, It will only animate when you change the CSS properties. And You are directly adding and removing classes.

Here is another way to get this by jQuery :

$('.toggle').on('click', function(e) {
  var content_id = $(this).data('content-id');
  $('#content-' + content_id).slideToggle('slow');
});

Updated Codepen

Madan Bhandari
  • 2,094
  • 2
  • 26
  • 46
  • Isn't `linear` just the *easing* to use? Such as you can use `ease`, which I believe is the default as well as `ease-in`, `ease-out` etc? – Brett May 28 '16 at 16:44
  • @Brett yes, you are right for ease is default value but linear isn't like ease it's opposite to ease. you can read more here http://stackoverflow.com/questions/9629346/difference-between-css3-transitions-ease-in-and-ease-out . And I hope it's working properly as you need. – Madan Bhandari May 28 '16 at 16:53
  • Well I tested it out and the issues still exist. – Brett May 28 '16 at 16:57
  • Just tested in Chrome and also had someone else test and both still indicate the small delay when re-opening the content. – Brett May 28 '16 at 17:17
  • 2
    The main cause of the delay is that margin: -100% is relative to the ancestor, and so is bigger than it needs to be (more or less the same problem that stating a max-height bigger than needed) – vals May 28 '16 at 18:10
  • @vals you are right, now I have updated the answer and I hope this solves the problem – Madan Bhandari May 28 '16 at 18:47
  • I'm very aware of jQuery's `slideToggle` but as indicated in my question I wanted to do this in CSS. :) – Brett May 28 '16 at 19:42
  • at first it's not possible with margin-top, and if you can't use height or max-height then you have to use JS, because css transition can not animate display property – Madan Bhandari May 28 '16 at 20:00