Ir al contenido

Skeleton

.skeleton muestra un bloque gris con un pulso suave en el lugar donde aparecerá el contenido. Un modificador indica qué reemplaza: texto, título, etiqueta, campo o imagen. No necesita JS: muéstralos mientras carga y cámbialos por el contenido al terminar.

skeleton--title y skeleton--text dejan una separación bajo cada línea (salvo la última). Para variar el largo de una línea, cambia --ds-skeleton-width.

<div class="skeleton skeleton--title" aria-hidden="true"></div>
<div class="skeleton skeleton--text" aria-hidden="true"></div>
<div class="skeleton skeleton--text" aria-hidden="true"></div>
<div class="skeleton skeleton--text" style="--ds-skeleton-width: 70%" aria-hidden="true"></div>

skeleton--label, skeleton--input y skeleton--textarea. El input y el textarea tienen el alto y el radio de form-input. Para un botón, usa skeleton--input con un ancho fijo.

<div class="form-field">
<div class="skeleton skeleton--label" aria-hidden="true"></div>
<div class="skeleton skeleton--input" aria-hidden="true"></div>
</div>
<div class="form-field">
<div class="skeleton skeleton--label" style="--ds-skeleton-width: 25%" aria-hidden="true"></div>
<div class="skeleton skeleton--textarea" aria-hidden="true"></div>
</div>

Sin tamaño, skeleton--image ocupa el ancho disponible con proporción 16:10 (como la imagen de una card). skeleton--sm, skeleton--md y skeleton--lg la hacen cuadrada de 50, 100 y 150 px.

<div class="skeleton skeleton--image skeleton--sm" aria-hidden="true"></div>
<div class="skeleton skeleton--image skeleton--md" aria-hidden="true"></div>
<div class="skeleton skeleton--image skeleton--lg" aria-hidden="true"></div>

Por defecto es un rectángulo. skeleton--rounded redondea las esquinas y skeleton--circle la hace un círculo (avatares).

<div class="skeleton skeleton--image skeleton--md" aria-hidden="true"></div>
<div class="skeleton skeleton--image skeleton--md skeleton--rounded" aria-hidden="true"></div>
<div class="skeleton skeleton--image skeleton--md skeleton--circle" aria-hidden="true"></div>

Los skeletons dentro de una card, junto a la misma card ya cargada.

<div class="card" aria-busy="true">
<span class="visually-hidden">Cargando…</span>
<div class="card__image">
<div class="skeleton skeleton--image" aria-hidden="true"></div>
</div>
<div class="card__body">
<div class="skeleton skeleton--title" aria-hidden="true"></div>
<div class="skeleton skeleton--text" aria-hidden="true"></div>
<div class="skeleton skeleton--text" style="--ds-skeleton-width: 70%" aria-hidden="true"></div>
</div>
</div>
<div class="card">
<div class="card__image">
<img src="/ejemplos/imagen-1.svg" alt="" width="800" height="500">
</div>
<div class="card__body">
<h3 class="card__title">Diseño web</h3>
<p class="card__description">Sitios rápidos, accesibles y fáciles de administrar.</p>
</div>
</div>

Cada ítem es una card con una fila (row): el avatar en column-auto y el texto en column.

<div aria-busy="true">
<span class="visually-hidden">Cargando contactos…</span>
<div class="row">
<div class="card">
<div class="card__body">
<div class="row row--align-center" style="--ds-row-gap-x: 1rem">
<div class="column-auto">
<div class="skeleton skeleton--image skeleton--sm skeleton--circle" aria-hidden="true"></div>
</div>
<div class="column">
<div class="skeleton skeleton--title" style="--ds-skeleton-width: 40%" aria-hidden="true"></div>
<div class="skeleton skeleton--text" aria-hidden="true"></div>
</div>
</div>
</div>
</div>
<div class="card">
<div class="card__body">
<div class="row row--align-center" style="--ds-row-gap-x: 1rem">
<div class="column-auto">
<div class="skeleton skeleton--image skeleton--sm skeleton--circle" aria-hidden="true"></div>
</div>
<div class="column">
<div class="skeleton skeleton--title" style="--ds-skeleton-width: 30%" aria-hidden="true"></div>
<div class="skeleton skeleton--text" style="--ds-skeleton-width: 80%" aria-hidden="true"></div>
</div>
</div>
</div>
</div>
<div class="card">
<div class="card__body">
<div class="row row--align-center" style="--ds-row-gap-x: 1rem">
<div class="column-auto">
<div class="skeleton skeleton--image skeleton--sm skeleton--circle" aria-hidden="true"></div>
</div>
<div class="column">
<div class="skeleton skeleton--title" style="--ds-skeleton-width: 45%" aria-hidden="true"></div>
<div class="skeleton skeleton--text" style="--ds-skeleton-width: 60%" aria-hidden="true"></div>
</div>
</div>
</div>
</div>
</div>
</div>

Los campos van en form-field, así mantienen la misma separación que el formulario real.

<div class="card" aria-busy="true">
<span class="visually-hidden">Cargando formulario…</span>
<div class="card__body">
<div class="row">
<div class="column-md-6">
<div class="form-field">
<div class="skeleton skeleton--label" aria-hidden="true"></div>
<div class="skeleton skeleton--input" aria-hidden="true"></div>
</div>
</div>
<div class="column-md-6">
<div class="form-field">
<div class="skeleton skeleton--label" style="--ds-skeleton-width: 30%" aria-hidden="true"></div>
<div class="skeleton skeleton--input" aria-hidden="true"></div>
</div>
</div>
</div>
<div class="form-field">
<div class="skeleton skeleton--label" style="--ds-skeleton-width: 20%" aria-hidden="true"></div>
<div class="skeleton skeleton--textarea" aria-hidden="true"></div>
</div>
<div class="skeleton skeleton--input" style="--ds-skeleton-width: 8rem" aria-hidden="true"></div>
</div>
</div>
  • Cada skeleton lleva aria-hidden="true": es decorativo y no se lee.
  • La zona que carga (la card, la lista o el formulario) lleva aria-busy="true" y un texto para lectores de pantalla, oculto a la vista con visually-hidden: <span class="visually-hidden">Cargando…</span>. Al terminar, quita aria-busy y el texto.
  • Si hay que anunciar la carga sin que el usuario navegue hasta ella, usa además un loader o una región role="status" fuera de la zona con aria-busy.
  • Con movimiento reducido (prefers-reduced-motion), el pulso se detiene.
Clase Uso
skeleton Base: bloque gris con pulso. Lleva aria-hidden="true".
skeleton--title Título (12 px de alto, 60 % de ancho).
skeleton--text Línea de texto (10 px de alto).
skeleton--label Etiqueta de un campo (15 px de alto, 40 % de ancho).
skeleton--input Campo de texto o botón, con el alto y el radio de form-input.
skeleton--textarea Área de texto, con el alto y el radio de un textarea form-input.
skeleton--image Imagen. Sin tamaño, ancho completo con proporción 16:10.
skeleton--sm, skeleton--md, skeleton--lg Cuadrado de 50, 100 o 150 px.
skeleton--rounded Esquinas redondeadas.
skeleton--circle Círculo.

El texto «Cargando…» usa la utilidad visually-hidden.

VariableValor por defectoUso
--ds-skeleton-bgcolor-mix(in srgb, var(--ds-color-text) 8%, var(--ds-color-surface))Color del bloque (gris calculado del texto sobre la superficie).
--ds-skeleton-duration1.4sDuración de un pulso.
--ds-skeleton-width100%Ancho. Cada tipo trae el suyo; cámbialo para variar el largo de las líneas.
--ds-skeleton-height1remAlto.
--ds-skeleton-aspect-ratioautoProporción cuando el alto es automático (imagen sin tamaño).
--ds-skeleton-radiusvar(--ds-radius-sm)Radio de las esquinas.
--ds-skeleton-spacingvar(--ds-space-2)Separación bajo títulos y líneas de texto.