adding animation to flex-wrap

10,803

Solution 1

I had a similar need and created a simple utility to achieve it.
- Demo at CodePen: https://codepen.io/hideya/pen/Jamabx
- GH gist: https://gist.github.com/hideya/16ed168a42f74eb5d2162b4e743940ff

The implementation is a bit wild and pretty much assumes no change in flex items except xy coords. You may need to adjust z-index, as it switches item's 'position' to 'absolute'. Hope this helps.

window.addEventListener('load', function(event) {
  var targetClassName = 'flex-wrap-anim';
  var defaultDuration = '0.3s';

  var dummyList = [];
  function addDummy(item, duration) {
    var top = item.offsetTop;
    var left = item.offsetLeft;
    setTimeout(function() {
      item.style.position = 'absolute';
      item.style.top = top + 'px';
      item.style.left = left + 'px';

      var dummyDiv = document.createElement('div');
      dummyDiv.classList.add(targetClassName + '-dummy');
      var rect = item.getBoundingClientRect();
      dummyDiv.style.width = rect.width + 'px';
      dummyDiv.style.height = rect.height + 'px';
      dummyDiv.style.visibility = 'hidden';
      dummyDiv['__' + targetClassName + '_pair'] = item;
      dummyDiv['__' + targetClassName + '_duration'] = duration;
      item.parentNode.appendChild(dummyDiv);
      dummyList.push(dummyDiv);
    }, 0);
  }

  var conts = document.getElementsByClassName(targetClassName);
  for (var i = 0, max = conts.length; i < max; i++) {
    var cont = conts[i];
    cont.style.positoin = 'relative';
    var duration = cont.getAttribute('data-duration')
      || defaultDuration;
    var items = cont.getElementsByTagName('div');
    for (var i = 0, max = items.length; i < max; i++) {
      addDummy(items[i], duration);
    }
  }

  window.addEventListener('resize', function(event) {
    dummyList.forEach(function(dummyDiv) {
      var item = dummyDiv['__' + targetClassName + '_pair'];
      var duration = dummyDiv['__' + targetClassName + '_duration'];
      if (item.offsetTop != dummyDiv.offsetTop) {
        item.style.transition = 'all ' + duration;
        item.style.top = dummyDiv.offsetTop + 'px';
        item.style.left = dummyDiv.offsetLeft + 'px';
      } else {
        item.style.transition = '';
        item.style.left = dummyDiv.offsetLeft + 'px';
      }
    });
  });
});

Solution 2

While this cannot be done with CSS alone, you can accomplish this using JQuery. When looking at a flexbox using rows, the flexbox will change height if a new row is created or removed. Knowing this, we can add a .resize() function to the page to test if a window resize has altered the height of the flexbox. If it has, you can then execute an animation. I have created an example JFiddle here.

Here is the code that makes this work:

$(document).ready(function() {
 var height = $('.container').css('height');
 var id;
 $(window).resize(function() {
  clearTimeout(id);
  id = setTimeout(doneResizing, 500);
 });
 function doneResizing() {
        var newheight = $('.container').css('height');
    if (newheight != height) {
        $('.item').fadeOut();
      $('.item').fadeIn();
      height = newheight;
    }
    }
});

Now with a flexbox using columns, we need to detect when a change in width occurs. This is slightly more difficult as the flexbox width will take up the maximum allotted width as it is a block style element by default. So to accomplish this, you either need to set it as an inline flexbox using display: inline-flex, or set a maximum width for the flexbox equal to the width of its contents at its largest. Once you have set one of those, you can use the same code as above, except tweaking it to detect changes in width as opposed to height.

These changes applied an animation to all elements on resize. What if you want to only apply it to the element whose row/column changes? This would take more effort but is do-able. You would need to write many if-statements in your javascript/jquery code to catch which flex-item to apply the animation to based on width/height.

Share:
10,803

Related videos on Youtube

Mohammad Javidi
Author by

Mohammad Javidi

I'm an ambitious self-learner programmer, eager to learn new languages and longing to put it into practice. I'm experienced in web development and mobile apps .

Updated on September 15, 2022

Comments

  • Mohammad Javidi
    Mohammad Javidi over 1 year

    when it comes to wrap point how can we add animation?

    maybe this can help:

    we have a header and inside of that header we have container with flex attr and the direction is column when we resize our browser from bottom to top or when we changing height of browser those items suddenly reshape , I just want to add animation to this event.thx

    <header>
            <div class="container">
                <div class="item1 item"></div>
                <div class="item2 item"></div>
                <div class="item3 item"></div></div></header>
    
    
    header {
            width: 200vw;
            max-height: 100vh ;
        }
    
    
    .container{
            display: flex;
            max-height:100vh;
            flex-direction: column;
            flex-wrap: wrap;
            align-content:flex-start;
    }
    
    
    
    .item1 {
        background-color: red;
        height: 200px;
        flex: 1 0 150px;
    }
    
    
    .item2 { 
        background-color: blue;
        height: 200px;
        flex: 1 0 150px;
    
    }
    
    
    .item3 { 
        background-color: orange;
        height: 200px;
        flex: 1 0 150px;
    
    }
    
    • Paulie_D
      Paulie_D over 8 years
      No...flex-wrap is not animatable. Wrapping behaviour isn't animatable now and flexbox isn't going to change that.
  • Mohammad Javidi
    Mohammad Javidi over 8 years
    good Idea but your JFiddle needs more work , its not working correctly
  • Chris G
    Chris G over 8 years
    @mehrdad I would be happy to fix any errors but can you explain what in the JSFiddle is not working correctly? Every time the items in the flexbox reshape, the boxes fade out and then fade back in. You can see a screencast of this working here: take.ms/k7wyR - please let me know.
  • Mohammad Javidi
    Mohammad Javidi over 8 years
    I think you misunderstood the question I need something like animation for breakpoint like in this site css-tricks.com/animated-media-queries but now we have flex-wrap instead of media-queries
  • Chris G
    Chris G over 8 years
    I see what you mean! You want the element to animate to its next row/column as it transitions. You can also do this with JQuery. I have made you an example here: jsfiddle.net/0Ltfddem/3. I only took the time to make it for the black square to transition from first row to second row and vice versa. As I'm sure you can tell - this code starts to get pretty complex. To implement this for many flex items will get hectic - but let me know if you need help with it!