Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS3 animate or transition elements into position after removal of an element above

What is the best way of achieving this without any visible flickering and any wierdness?

The fiddle to start out: http://jsfiddle.net/35qec14b/2/

$('.element').on('click', function(e){
  this.remove();
});
.element {
  position:relative;
  width: 200px;
  margin:5px;
  padding:20px;
  cursor:pointer;
  background: rgb(150,200,250);
  transition:1s linear;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
(click to remove)
<div class="element">Element 1</div>
<div class="element">Element 2<br>Second line</div>
<div class="element">Element 3</div>
<div class="element">Element 4<br>Second line</div>
<div class="element">Element 5</div>

Note: the removed element must disappear instantly in this case, as it would appear in another location and we don't want it to be visible in two places simultaneously.

Ideas so far:

  • transform:translateY for ALL elements below the removed one (probably performance intensive for large lists)
  • Animate/transform margin of the first element below, from removed element's height to 0 (leveraging chained animations? step-start?)
  • Replace the removed element with a transparent placeholder and animate it's own height to 0
like image 715
Slava Avatar asked Feb 05 '23 06:02

Slava


2 Answers

The best that comes to mind is to hide it, clone it for its new location (not showed here), and then animate its height

When one animate both margins, paddings and height, it becomes not so smooth, so I added an extra inner wrapper for the content so the animation only animates the height

$('.element').on('click', function(e) {
  this.style.height = $(this).height()+ 'px';
  this.classList.add('hide-me');
  (function(el) {
    setTimeout(function() {
      el.remove();
    }, 500);
  })(this);
});
.element {
  position: relative;
  width: 200px;
  overflow: hidden;
}
.element > div {
  margin: 5px;
  padding: 20px;
  background: rgb(150, 200, 250);
}

.element.hide-me {
  animation: hideme .5s forwards;
  opacity: 0;
}
@keyframes hideme {
  100% {
    height: 0;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
(click to remove)
<div class="element">
  <div>
    Element 1
  </div>
</div>
<div class="element">
  <div>
    Element 2
    <br>Second line
  </div>
</div>
<div class="element">
  <div>
    Element 3
  </div>
</div>
<div class="element">
  <div>
    Element 4
    <br>Second line
  </div>
</div>
<div class="element">
  <div>
    Element 5
  </div>
</div>
like image 167
Asons Avatar answered Feb 08 '23 17:02

Asons


Here's the jQuery approach using .animate()

$('.element').on('click', function(e){
  var $this = $(this), $next = $this.next();
  $next.css({
    marginTop: $this.outerHeight(true)
  }).animate({
    marginTop: 5
  }, 200);
  $this.remove();
});
.element {
  position:relative;
  width: 200px;
  margin:5px;
  padding:20px;
  cursor:pointer;
  background: rgb(150,200,250);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
(click to remove)
<div class="element">Element 1</div>
<div class="element">Element 2<br>Second line</div>
<div class="element">Element 3</div>
<div class="element">Element 4<br>Second line</div>
<div class="element">Element 5</div>

And here is a CSS transition approach

$('.element').on('click', function(e){
  var $this = $(this), $next = $this.next();
  $next.css({
    marginTop: $this.outerHeight(true)
  });
  setTimeout(()=>{
    $next.addClass('hide');
    setTimeout(()=>{
      $next.css({marginTop: ''}).removeClass('hide');
    }, 250)
  }, 20);
  $this.remove();
});
.element {
  position:relative;
  width: 200px;
  margin:5px;
  padding:20px;
  cursor:pointer;
  background: rgb(150,200,250);
}

.element.hide {
  transition: margin-top 0.25s linear;
  margin-top: 5px !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
(click to remove)
<div class="element">Element 1</div>
<div class="element">Element 2<br>Second line</div>
<div class="element">Element 3</div>
<div class="element">Element 4<br>Second line</div>
<div class="element">Element 5</div>
like image 32
Joseph Marikle Avatar answered Feb 08 '23 15:02

Joseph Marikle