Using only opacity and transform can be frustrating
// Get the first position.
var first = el.getBoundingClientRect();
// Move it to the end.
el.classList.add('totes-at-the-end');
// Get the last position.
var last = el.getBoundingClientRect();
// Invert.
var invert = first.top - last.top;
// Go from the inverted position to last.
var player = el.animate([
  { transform: 'translateY(' + invert + 'px)' },
  { transform: 'translateY(0)' }
], {
  duration: 300,
  easing: 'cubic-bezier(0,0,0.32,1)',
});
// Do any tidy up at the end of the animation.
player.addEventListener('finish', tidyUpAnimations);
          
        You told us it's not performant to produce a Layout change. But you did one !
import React from 'react'
import FlipMove from 'react-flip-move'
const ArticleList = ({articles}) => (
  <FlipMove>
    { articles.map( article => <Article key={article.id} {...article} /> ) }
  </FlipMove>
);
          
        Freelance Front-end
React.js • Mobile First • Hybrid & Progressive Web Apps