jQuery animations with only one callback
I'd say your approach is correct. Since your delay is less than the duration, you can't use a series approach, where one completed animation starts the next. So your setup is probably the simplest you can do.

To make it more readable, the simplest thing would be to split the code up a bit:

$(function () { // same as $(document).read(...)
  // declare some "constants"
  var animationDelay = 800,
      animationDuration = 1000;

  // setup all the animations
  var queue = $(".elm").each(function (i) {
    $(this).delay(i * animationDelay).animate({opacity: 0}, {duration: animationDuration});
  });

  // set up the callback for when they finish
  $.when(queue).then(function () {
    // all animations done
  });
});