jQuery / Fazer elementos aparecerem em ordem

.delay(index * gap).fadeIn(duration) escalona os inícios. Se a duração supera o intervalo, os efeitos se sobrepõem. Para esperar a conclusão completa, inicie o próximo elemento pelo callback de conclusão anterior.

Intervalo de início e ordem de conclusão

.delay() espera na fila de cada elemento, não em uma fila compartilhada. Mesmo atraso começa aproximadamente junto; index cria escalonamento. Não bloqueia todo JavaScript.

Intervalo 200ms e .fadeIn() 400ms permitem Beta iniciar antes de Alpha terminar. Em série espera a conclusão e mais 200ms. São metas de agendamento, não tempos exatos garantidos.

.each() segue a coleção, aqui Alpha, Beta e Gamma diretos de #items. Ordenação e CSS podem diferir da leitura visual; defina a ordem apropriada.

Exemplo completo de comparação

Salve UTF-8 appearance-demo.html e abra. A Internet carrega a versão completa oficial 4.0.0. Efeitos temporizados precisam de effects, não Slim. Não precisa de servidor nem pacotes. Ordem, reinício e repetição foram conferidos no Edge para Windows com 3.7.1 e 4.0.0.

HTML começa visível e o script pronto oculta. Falha de carregamento não deixa conteúdo oculto permanentemente por CSS. A saída vem após inicialização.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Staggered versus strictly sequential appearance</title>
  <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
  <style>
    body { font: 16px/1.6 sans-serif; max-width: 760px; margin: 20px; }
    button, select { font: inherit; margin: 4px; }
    .item { border: 2px solid teal; padding: 12px; margin: 12px 0; background: #e7f5f1; }
    pre { white-space: pre-wrap; overflow-wrap: anywhere; }
  </style>
</head>
<body>
  <label>Mode <select id="mode"><option value="stagger">Staggered starts</option><option value="serial">Wait for completion</option></select></label>
  <button type="button" id="start">Start</button>
  <button type="button" id="reset">Reset</button>
  <div id="items"><div class="item" id="alpha">Alpha</div><div class="item" id="beta">Beta</div><div class="item" id="gamma">Gamma</div></div>
  <pre id="result" aria-live="polite"></pre>
  <pre id="events"></pre>
  <script>
    jQuery(function ($) {
      const $items = $("#items > .item"), gap = 200, duration = 400;
      let generation = 0, busy = false, state = "ready", completed = [], events = [];
      function report() {
        $("#result").text(`mode=${$("#mode").val()}\nstate=${state}\nvisible=${$items.filter(":visible").length}/${$items.length}\ncompleted=${completed.join(",") || "(none)"}`);
        $("#events").text(events.join("\n") || "(none)");
      }
      function reset() {
        generation++; // Invalidate callbacks before settling old effects.
        $items.stop(true, true).hide();
        busy = false; state = "ready"; completed = []; events = [];
        $("#start").prop("disabled", false); report();
      }
      function start() {
        if (busy) return;
        reset(); busy = true; state = "running"; $("#start").prop("disabled", true);
        const run = generation, mode = $("#mode").val();
        const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
        if (reduce) {
          $items.show(); completed = $items.map(function () { return this.id; }).get();
          events = ["Reduced motion: shown immediately"];
          busy = false; state = "done"; $("#start").prop("disabled", false); report(); return;
        }
        function reveal(index, wait) {
          const $item = $items.eq(index), id = $item[0].id;
          $item.delay(wait).queue(function (next) {
            if (run !== generation) return;
            events.push("start " + id); next(); report();
          }).fadeIn(duration, function () {
            if (run !== generation) return;
            completed.push(id); events.push("done " + id);
            if (completed.length === $items.length) {
              busy = false; state = "done"; $("#start").prop("disabled", false);
            } else if (mode === "serial") reveal(index + 1, gap);
            report();
          });
        }
        if (!$items.length) { busy = false; state = "done"; $("#start").prop("disabled", false); report(); return; }
        if (mode === "stagger") $items.each(function (index) { reveal(index, index * gap); });
        else reveal(0, 0);
        report();
      }
      $("#start").on("click", start);
      $("#reset").on("click", reset);
      $("#mode").on("change", reset);
      reset();
    });
  </script>
</body>
</html>

Inicialmente zero visíveis e nenhum concluído.

mode=stagger
state=ready
visible=0/3
completed=(none)
  1. Start em Staggered starts: start beta pode vir antes de done alpha.
  2. Final: state=done, visible=3/3 e completed=alpha,beta,gamma. Start volta a habilitar.
  3. Wait for completion reinicia. Depois start alpha → done alpha → start beta → done beta → start gamma → done gamma.
  4. Reset durante execução restaura oculto. Esperar não deve reviver efeitos antigos. Inicie novamente.
  5. Com movimento reduzido no sistema ou ferramentas, tudo aparece imediatamente e Reduced motion: shown immediately.

Cliques múltiplos e reinício

Start é desabilitado e a função confere busy. Chamadas programadas também não empilham sequências. Conclusões são contadas por elemento; um callback não conclui a coleção inteira.

.stop(true, true) limpa espera e leva o efeito atual ao fim. Reset muda primeiro generation para invalidar callbacks antigos, depois conclui e oculta. jumpToEnd pode chamar conclusão: não o faça antes de invalidar.

Evita estados e filas residuais na repetição. clearQueue sozinho não para o efeito ativo. setTimeout separados precisariam de cancelamento próprio; aqui delay usa fx.

.queue() registra e chama next() para continuar ao fadeIn. Sem next(), a fila para. Em série, só a conclusão inicia o próximo índice.

Preferências e layout real

prefers-reduced-motion reduce pula espera e fade, estabelecendo o final imediatamente. Afeta apenas o exemplo, não efeitos globais. Decoração não deve atrasar informação importante.

Mostrar de display:none cria espaço e move conteúdo posterior. Reserve espaço ou escolha outra técnica para estabilidade. Controles ocultos também exigem planejamento de teclado e foco.

Com adições dinâmicas, redefina coleção e contagem de conclusões. $items mantém os três iniciais sem novos automaticamente. Decida repetir tudo ou animar novos e ajuste filas e reinício.