CSS

28 mai, 2025

Elementos Fantasmas: O truque de UX para carregamentos mais rápidos!

Publicidade

Não tem nada pior para a experiência do usuário do que acessar um site e ter a tela vazia por vários segundos porque o conteúdo está sendo carregado.

É claro que há muitas situações em que mesmo com os nossos melhores esforços, o site vai demorar pra carregar. É o caso, por exemplo, de conexões rápidas.

O que fazer para nosso o usuário ter uma percepção de que o site está mais rápido mesmo para situações de lentidão?

É nestas situações que usamos o elementos fantasmas! (bu!) 👻

Neste artigo te explico passo a passo como você também pode implementar no seu site! É mais fácil do que parece 🙂

Elementos Fantasmas

Os elementos fantasmas nada mais são do que alguns placeholders com animação que substituem o verdadeiro conteúdo do site enquanto ele ainda não carregou.

Você já deve ter visto isso inúmeras vezes nas redes sociais, por exemplo:

Elementos fantasmas no LinkedIn

Essas estratégia é muito boa porque dá percepção pro seu usuário de que o site já está carregando uma série de informações, diferente do que acontece quando não mostramos nada ou simplesmente mostramos uma rodinha de loading. Cria uma percepção de carregamento mais rápido.

Felizmente o processo para criarmos este efeito é relativamente simples. Primeiramente, precisamos entender como é o nosso conteúdo carregado. Neste exemplo, farei este post aqui:

O código que corresponde a este post é este:

<!DOCTYPE html>
<html lang="pt-br">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link rel="stylesheet" href="styles.css" />
  <title>Ghost Elements</title>
</head>

<body>
  <div class="container">
    <template id="card-template">
      <a class="card" id="card-link" target="_blank">
        <!-- header -->
        <div class="card-header">
          <div>
            <img class="header-img" id="logo-img" alt="" />
          </div>
          <h3 class="card-header header-title" id="card-title">
          </h3>
        </div>

        <!-- body -->
        <div class="card-body">
          <div class="card-body body-text" id="card-details">
          </div>

          <div class="card-body body-img">
            <img alt="" id="cover-img" />
          </div>
        </div>
      </a>
    </template>
  </div>

  <script src="script.js"></script>
</body>

</html>

Como desejamos este conteúdo dinamicamente, vamos codar o nosso JavaScript:

document.addEventListener('DOMContentLoaded', () => {
  const QTD_POSTS = 1;
  const container = document.querySelector(".container");
  const cardTemplate = document.querySelector("#card-template");
  for (let i = 0; i < QTD_POSTS; i++) {
    container.append(cardTemplate.content.cloneNode(true));
  }

  fetch("data.json")
    .then((response) => response.json())
    .then((posts) => {
      container.innerHTML = "";
      posts.forEach((post) => {
        const { title, details, coverImage, logoImage, link } = post;

        const div = cardTemplate.content.cloneNode(true);
        div.querySelector("#card-link").href = link;
        div.querySelector("#logo-img").src = logoImage;
        div.querySelector("#card-title").textContent = title;
        div.querySelector("#card-details").textContent = details;
        div.querySelector("#cover-img").src = coverImage;
        container.append(div);
      });
    });
})

Se rodarmos o site localmente do jeito como está, é quase imperceptível o tempo de carregamento. Para ter uma melhor ideia da experiência do usuário, precisamos usar acessar a aba de Network e alterar o tipo de conexão. Usarei 3G.

A experiência atual é meio esquisita. Temos uma caixa vazia por um tempo e do nada o elemento do site é carregado. Não está bom assim. Vamos adicionar alguns elementos fantasmas para melhorar essa experiência.

Vamos começar pensar nos elementos fantasmas que desejamos inserir com base no resultado final que teremos. Para este post, eu identifiquei quatro fantasminhas:

Elementos fantasmas que substituem os elementos reais

Dentro do nosso HTML, vamos adicionar alguns destes elementos:

<!DOCTYPE html>
<html lang="pt-br">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link rel="stylesheet" href="styles.css" />
  <title>Ghost Elements</title>
</head>

<body>
  <div class="container">
    <template id="card-template">
      <a class="card" id="card-link" target="_blank">
        <!-- header -->
        <div class="card-header">
          <div>
            <img class="header-img ghost" id="logo-img" alt="" />
          </div>
          <h3 class="card-header header-title" id="card-title">
            <div class="ghost ghost-text"></div>
            <div class="ghost ghost-text"></div>
          </h3>
        </div>

        <!-- body -->
        <div class="card-body">
          <div class="card-body body-text" id="card-details">
            <div class="ghost ghost-text ghost-text-body"></div>
          </div>

          <div class="card-body body-img">
            <img class="ghost" alt="" id="cover-img" />
          </div>
        </div>
      </a>
    </template>
  </div>

  <script src="script.js"></script>
</body>

</html>

Repare em todos os lugares em que adicionar as classes ghost.

Vamos partir para o CSS:

.ghost {
  animation: ghost-loading 1s linear infinite alternate;
}

@keyframes ghost-loading {
  0% {
    background-color: #c2cfd6;
  }

  100% {
    background-color: #f0f3f5;
  }
}

.ghost-text {
  width: 100%;
  height: 0.7rem;
  margin-bottom: 0.5rem;
  border-radius: 0.25rem;
}

.ghost-text-body {
  width: 75%;
}

img[alt] {
  text-indent: -10000px;
}

Ao rodar o site em uma conexão lenta, agora teremos outra experiência:

Elemento fantasma em ação

O segredo está na animação ghost-loading. Esta animação na caixinha onde o conteúdo será carregado chama a atenção do usuário e faz com que a percepção de tempo de carregamento seja menor!

Repositório

https://github.com/Professor-DiegoPinho/ghost-elements-loader

Agradecimentos

Gostou deste conteúdo? Então curta, compartilhe e se inscreva na publicação para não perder nada! 👏

Versão em vídeo

Confira a versão em vídeo desse artigo!

Bu!