Skeleton Loading con CSS: Dominando el selector :empty

Skeleton Loading con CSS: Dominando el selector :empty

¿Alguna vez has notado cómo sitios como LinkedIn o YouTube muestran una estructura gris antes de cargar el contenido real? Esta técnica se conoce como Skeleton Screen y es fundamental para mejorar la percepción de velocidad y evitar saltos de diseño (CLS).

En este artículo, vamos a crear un componente de carga reutilizable utilizando CSS puro, aprovechando la potencia del pseudo-selector :empty y las Custom Properties.

¿Qué es el selector :empty?

El selector :empty es una herramienta muy útil que permite aplicar estilos a un elemento solo cuando no tiene hijos (ni elementos HTML, ni texto, ni siquiera espacios en blanco).

Esto lo hace perfecto para estados de carga:

  1. Si el contenedor está vacío -> Muestra el Skeleton.
  2. En cuanto inyectas contenido (vía JS/API) -> El Skeleton desaparece automáticamente y se muestran los estilos normales.

Dibujando con CSS Gradients

Para evitar ensuciar el HTML con divs vacíos para simular las barras y círculos, usaremos background-image con múltiples gradientes.

He diseñado este ejemplo para que sea altamente configurable mediante Variables CSS:

  • --color: El color base del esqueleto.
  • --height-rectangle: Altura del bloque principal (imagen destacada).
  • --height-line: Altura de las líneas de texto/avatar.

La magia ocurre combinando 4 capas de fondo:

  1. Brillo: Un gradiente lineal con transparencia para simular profundidad o brillo.
  2. Rectángulo principal: Simula una imagen o banner.
  3. Círculo: Un radial-gradient para simular un avatar.
  4. Línea de texto: Un bloque rectangular junto al círculo.

Aquí tienes el código completo:

.card__content:empty {
  --color: rgb(199, 199, 199);
  --width: 100%;
  --width-line: 250px;
  --height-rectangle: 150px;
  --height-line: 24px;
  --gutter: 10px;
  --computed-circle-rad: calc(var(--height-line) * 0.5);
  --computed-height: calc(var(--height-rectangle) + var(--gutter) + var(--height-line) + calc(1.5 * var(--gutter))
  );
  height: var(--computed-height);
  background-image:
    linear-gradient(0.9turn, #fff, transparent),
    linear-gradient(var(--color), var(--color)),
    radial-gradient(var(--height-line) circle at var(--computed-circle-rad) var(--computed-circle-rad), var(--color) 50%, transparent 50%),
    linear-gradient(var(--color), var(--color));
  background-size:
    var(--width) var(--computed-height),
    var(--width) var(--height-rectangle),
    var(--height-line) var(--height-line),
    var(--width-line) var(--height-line);
  background-position:
    var(--width) 0,
    0 0,
    0px calc(var(--height-rectangle) + var(--gutter)),
    calc(var(--height-line) + var(--gutter)) calc(var(--height-rectangle) + var(--gutter));
  background-repeat: no-repeat;
}

Ver el Pen Skeleton Loading con CSS: Dominando el selector :empty por Iván Albizu (@ivan_albizu) en CodePen.

En este repositorio puede verse el código del placehoder con CSS para selector :empty