Search code examples
knockout.jscss-transitionsjquery-masonrymasonrytransitionend

masonry.js - layout items with transition effect on them


I am using knockout.js and masonry.js in my project. so as documentation of masonry suggest I use reloaditems method to apply changes of the DOM to masonry. it worked fine until I add a hover transition effect to my items. here is the code.

as you can see after pressing "load more!" button the masonry seems to reload twice!

after some debug I found out that "transitionend" event make the masonry.js reload again!

can anyone give me a tip to solve the problem?

thank you

var dataRand = [
  "Lorem ipsum dolor sit amet, mel ad ubique iriure petentium, voluptatum interpretaris his no. Solum voluptatum appellantur cum no",
  "Lorem ipsum dolor sit amet, mel ad ubique iriure petentium, voluptatum interpretaris his no. Solum voluptatum appellantur cum no, fugit denique assentior vel ei, porro antiopam tractatos vim no. Affert oporteat qui cu, quo nostro possim aperiri cu. Ex vide inermis vix, quod veniam volutpat mea ad.",
  "Lorem ipsum dolor sit amet, mel ad ubique iriure petentium, voluptatum interpretaris his no. Solum voluptatum appellantur cum no, fugit denique assentior vel ei, porro antiopam tractatos vim no. Affert oporteat qui cu, quo nostro possim aperiri cu. Ex vide inermis vix, quod veniam volutpat mea ad.Et qui modo soleat aperiri. Quo at probo labore integre, nam te modo iudicabit. Ea mutat inermis eos, ei usu soleat scripta repudiandae. Nec ea natum semper, cetero admodum eos eu. Placerat percipit reformidans an eam, vis in ridens ornatus efficiendi, elit labitur nam ne. Eum nonumy noster verear et, ex detracto electram eloquentiam mei."
];
function masonryExampleViewModel() {
  var that = this;
  this.results = ko.observableArray([]);
  this.loadmore = function() {
    for (var i = 0; i <= 5; i++) {
      that.results.push(dataRand[Math.floor(Math.random() * 3)]);
    }
    $("#masonryContainer").masonry("reloadItems");
    $("#masonryContainer").masonry("layout");
  };
}
ko.applyBindings(new masonryExampleViewModel(), $("#masonryExampleWrapper")[0]);
$("#masonryContainer").masonry({
  itemSelector: ".masonry-item",
  columnWidth: ".grid-sizer",
  percentPosition: true,
  isOriginLeft: false,
  gutter: ".gutter_sizer"
});
.grid-sizer,
.masonry-item {
  width: 32%;
  margin-bottom: 2%;
  padding: 10px;
}

.gutter_sizer {
  width: 2%;
}

* {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

.masonry-item {
  border: 1px solid #DDD;
  -webkit-transition: -webkit-transform 300ms, box-shadow 300ms, opacity 300ms;
  -moz-transition: -webkit-transform 300ms, box-shadow 300ms, opacity 300ms;
  -ms-transition: -webkit-transform 300ms, box-shadow 300ms, opacity 300ms;
  -o-transition: -webkit-transform 300ms, box-shadow 300ms, opacity 300ms;
}

.masonry-item:hover {
  -webkit-transform: translateY(-6px);
  -moz-transform: translateY(-6px);
  transform: translateY(-6px);
  box-shadow: 0 20px 20px rgba(0, 0, 0, 0.3);
  -moz-box-shadow: 0 20px 20px rgba(0, 0, 0, 0.3);
  -webkit-box-shadow: 0 20px 20px rgba(0, 0, 0, 0.3);
}

.loadmoreBtn {
  display: block;
  text-align: center;
  padding: 10px;
  background-color: rebeccapurple;
  color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/masonry.pkgd.min.js"></script>
<div id="masonryExampleWrapper">
  <div id="masonryContainer">
    <div class="grid-sizer"></div>
    <div class="gutter_sizer"></div>
    <div class="masonry-item">
      <span class="data-container">Lorem ipsum dolor sit amet, mel ad ubique iriure petentium, voluptatum interpretaris his no. Solum voluptatum appellantur cum no</span>
    </div>
    <div class="masonry-item">
      <span class="data-container">Lorem ipsum dolor sit amet, mel ad ubique iriure petentium, voluptatum interpretaris his no. Solum voluptatum appellantur cum no, fugit denique assentior vel ei, porro antiopam tractatos vim no. Affert oporteat qui cu, quo nostro possim aperiri cu. Ex vide inermis vix, quod veniam volutpat mea ad.</span>
    </div>
    <div class="masonry-item">
      <span class="data-container">Lorem ipsum dolor sit amet, mel ad ubique iriure petentium, voluptatum interpretaris his no. Solum voluptatum appellantur cum no, fugit denique assentior vel ei, porro antiopam tractatos vim no. Affert oporteat qui cu, quo nostro possim aperiri cu. Ex vide inermis vix, quod veniam volutpat mea ad.Et qui modo soleat aperiri. Quo at probo labore integre, nam te modo iudicabit. Ea mutat inermis eos, ei usu soleat scripta repudiandae. Nec ea natum semper, cetero admodum eos eu. Placerat percipit reformidans an eam, vis in ridens ornatus efficiendi, elit labitur nam ne. Eum nonumy noster verear et, ex detracto electram eloquentiam mei.</span>
    </div>
    <!-- ko foreach :  results -->
    <div class="masonry-item">
      <span class="data-container" data-bind="text : $data"></span>
    </div>
    <!-- /ko -->
  </div>
  <a href="#" class="loadmoreBtn" data-bind="click : loadmore">load more!</a>
</div>


Solution

  • desandro answered me on github:

    Masonry uses CSS transitions for updating layout. If your own CSS has transitions for opacity, top/left or transform, they could conflict with Masonry. One solution is to use separate element for transition effects

    <div class="masonry-item">
       <div class="hover-card">
    

    See demo