Cómo poner una animación transparente sobre el contenido
Por el equipo de Charmotion · Actualizado el

Para superponer una animación con fondo transparente sobre el contenido, usa un formato con alfa real (un canvas de Rive o un par de HEVC .mov y VP9 WebM), colócala en una capa con posición absoluta sobre el contenido, define pointer-events: none para que los clics la atraviesen y dale tamaño con aspect-ratio para que escale sin provocar layout shift.
Puntos clave
- Rive dibuja sobre un canvas transparente, así que todo lo que queda fuera del arte deja ver lo que hay detrás. El video necesita HEVC con alfa para Safari y VP9 con alfa para los demás navegadores.
- Superpón con un contenedor posicionado y
pointer-events: none; en nativo, usa.allowsHitTesting(false)en SwiftUI. - Dale tamaño a la capa con
aspect-ratioy un ancho limitado para que escale con la pantalla. - Pausa los overlays que estén fuera de pantalla y mantén varias instancias de Rive en un contexto WebGL compartido.
¿Ya tienes un personaje o logo? Mira tu personaje en pantallas reales de una app: pantallas de splash, onboarding, carga y estado vacío. Es gratis, funciona en tu navegador y no sube nada.
¿Qué formatos conservan el fondo transparente?
| Formato | Alfa | Notas |
|---|---|---|
| Rive (.riv) | Yes | Vectorial, se dibuja en un canvas con fondo transparente salvo que el artboard tenga relleno. Archivos pequeños, interactivo. |
| VP9 WebM con alfa | Sí en Chrome, Edge y Firefox | Safari reproduce WebM, pero descarta el canal alfa. |
| HEVC .mov con alfa | Sí en Safari | Solo dispositivos Apple. Archivos más pesados. |
| MP4 (H.264) | No | Siempre opaco. |
| GIF | Un bit | Bordes dentados, 256 colores. |
En video, necesitas los dos archivos. El marcado probado de Jake Archibald pone primero la fuente HEVC, porque Safari puede reproducir VP9 pero no su transparencia, y de lo contrario elegiría el WebM y mostraría un recuadro opaco (Jake Archibald). En su prueba, el mismo clip pesaba 1.1 MB en VP9 y 3.4 MB en HEVC.
Un archivo Rive evita la división en dos archivos y suele pesar mucho menos, pero necesita el runtime de Rive. Usa video cuando la animación esté prerrenderizada (3D, partículas, imagen real) y Rive cuando sea un personaje que deba reaccionar. Los detalles de codificación están en la guía de video con fondo transparente.

¿Cómo superponer una animación sobre una página con CSS?
Convierte el contenedor del contenido en el contexto de posicionamiento y coloca la animación en un hijo con posición absoluta encima:
<div class="stage">
<img src="/product.jpg" alt="The Acme backpack in green" width="1200" height="800">
<video class="overlay" autoplay muted loop playsinline aria-hidden="true">
<source src="/sparkle.mov" type='video/quicktime; codecs="hvc1"'>
<source src="/sparkle.webm" type="video/webm">
</video>
</div>
<style>
.stage { position: relative; isolation: isolate; }
.stage img { display: block; width: 100%; height: auto; }
.overlay {
position: absolute;
inset: auto 4% 4% auto; /* bottom-right corner */
width: clamp(96px, 22%, 240px);
aspect-ratio: 1;
z-index: 1;
pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
.overlay { display: none; }
}
</style>
isolation: isolate crea un contexto de apilamiento, así que el z-index del overlay solo compite con sus hermanos dentro de .stage y nunca termina por encima del header de tu sitio ni de los modales. Para un overlay de Rive, reemplaza el video por un <canvas class="overlay"> y crea en él la instancia de Rive; el canvas es transparente en todas las zonas donde no se dibuja el arte.
Un video inline solo puede reproducirse automáticamente en Safari para iOS cuando está silenciado y tiene playsinline (WebKit). Un overlay en loop que dura más de cinco segundos junto al contenido también necesita una forma de pausarlo u ocultarlo según WCAG 2.2.2, o debería detenerse tras unos cuantos ciclos.
¿Cómo evitar que el overlay bloquee toques y clics?
En la web, pointer-events: none en el overlay permite que los clics, toques y hovers pasen a lo que haya debajo. Sin esto, un canvas o video transparente sigue capturando cada clic dentro de su rectángulo, incluso donde no se ve nada, y ese es el error más común con los overlays.
Dos advertencias:
- Los listeners de Rive dejan de funcionar. Si la máquina de estados reacciona al hover o a los clics mediante listeners de Rive, estos necesitan eventos de puntero en el canvas. Mantén
pointer-events: autoen un canvas pequeño que solo cubra al personaje, o controla las reacciones desde el código con triggers. - Mantenlo fuera del árbol de accesibilidad. Agrega
aria-hidden="true"a los overlays decorativos para que los lectores de pantalla los omitan.
SwiftUI usa .overlay o un ZStack, y .allowsHitTesting(false) deja pasar los toques:
ContentView()
.overlay(alignment: .bottomTrailing) {
mascot.view()
.frame(width: 120, height: 120)
.allowsHitTesting(false)
.accessibilityHidden(true)
.padding()
}
Jetpack Compose usa un Box con el overlay dibujado al final. Un composable sin modificadores de pointer input no consume toques, así que estos llegan al contenido de debajo. Si el reproductor es una View insertada mediante AndroidView, comprueba que no intercepte los toques.
Box(Modifier.fillMaxSize()) {
Content()
Mascot(Modifier.align(Alignment.BottomEnd).padding(16.dp).size(120.dp))
}¿Cómo dar tamaño y posición responsivos al overlay?
- Usa unidades relativas con límites.
width: clamp(96px, 22%, 240px)crece con el contenedor, pero nunca queda diminuto en teléfonos ni enorme en pantallas anchas. - Fija la forma.
aspect-ratio: 1(o la proporción del clip) reserva la altura correcta antes de que cargue el archivo, así nada salta. - Ánclalo a una esquina o un borde. Los valores de
inseten porcentajes mantienen al personaje en el mismo punto relativo en cualquier tamaño de pantalla. - Ajusta, no recortes. En video usa
object-fit: contain; en Rive define el ajuste del layout en contain para que el artboard nunca quede cortado. - Ajusta el tamaño de la superficie de dibujo de Rive. Llama a
resizeDrawingSurfaceToCanvas()al cargar y cada vez que cambie el tamaño del canvas, para que los bordes vectoriales se vean nítidos según la densidad de píxeles del dispositivo (Rive).
En pantallas pequeñas, pregúntate si el overlay sigue justificando el espacio que ocupa. Si taparía texto o botones en el ancho de un teléfono, muévelo debajo del contenido u ocúltalo en ese breakpoint.

¿Cómo mantener accesible un overlay transparente?
Los overlays se colocan sobre contenido que las personas necesitan leer y usar, así que implican más riesgos de accesibilidad que una animación dentro de su propio contenedor.
- Nunca tapes texto ni controles. Revisa cada breakpoint. Un overlay que oculta parte de un título o de un botón en algún ancho es un bug, aunque tenga activado el paso de clics.
- Mantén el contraste. Si el overlay pasa por detrás de un texto, ese texto debe seguir siendo legible en todos los fotogramas, no solo en el primero.
- Oculta la decoración a las tecnologías de asistencia. Usa
aria-hidden="true"en la web y.accessibilityHidden(true)en SwiftUI. Si la animación transmite un significado, como un estado de éxito, exprésalo también con texto real. - Respeta el movimiento reducido. Con
prefers-reduced-motion: reduce, oculta el overlay o muestra un fotograma fijo (MDN). - Limita los loops. El criterio de éxito 2.2.2 de WCAG 2.2 exige una forma de pausar, detener u ocultar el movimiento automático que dure más de cinco segundos junto a otro contenido (W3C). Detén el loop tras unos pocos ciclos u ofrece un control de pausa visible.
Evita efectos de destellos rápidos en los overlays, como chispas o relámpagos: WCAG limita el contenido a un máximo de tres destellos por segundo. Consulta animación accesible y movimiento reducido para ver la lista de verificación completa.
¿Cómo evitar que los overlays hagan más lenta la página?
- Anima solo con transform y opacity. Si animas la posición del overlay con CSS, usa
transformen lugar detopoleft; web.dev señala que transform y opacity se procesan en el compositor (web.dev). - Pausa lo que está fuera de la pantalla. Usa un
IntersectionObserverpara llamar avideo.pause()o alpause()de la instancia de Rive cuando el overlay salga de la vista con el scroll, y reanúdalo cuando vuelva. - Comparte el contexto WebGL. Los navegadores limitan la cantidad de contextos WebGL por página. Si tienes varios overlays de Rive en una página con
@rive-app/webgl2, defineuseOffscreenRenderer: truepara que compartan un solo contexto (Rive). - Libera recursos. Llama a
cleanup()en las instancias de Rive que elimines, sobre todo en aplicaciones de una sola página que montan y desmontan vistas. - Vigila el peso del video. Los archivos HEVC con canal alfa pesan bastante más que sus equivalentes en VP9, así que mantén los clips transparentes cortos y con el tamaño justo del espacio donde se muestran.
En todos los planes de pago, Charmotion entrega el mismo personaje en las dos formas: un solo .riv para overlays interactivos y archivos WebM y MOV transparentes, exportados bajo demanda desde el mismo set, para los prerenderizados, así que puedes elegir según cada ubicación.
Cómo poner una animación transparente sobre el contenido
- Elige un formato transparente. Usa un archivo de Rive para personajes interactivos, o un par formado por un .mov HEVC con alfa y un WebM VP9 con alfa para animación prerrenderizada.
- Crea el contexto de apilamiento. Aplica
position: relativeeisolation: isolateal contenedor que aloja el contenido. - Posiciona el overlay. Define el canvas o el video como
position: absolute, fíjalo coninsety asígnale unz-indexdentro del contenedor. - Deja pasar la interacción. Agrega
pointer-events: noneyaria-hidden="true"en la web, o.allowsHitTesting(false)en SwiftUI. - Ajusta el tamaño de forma responsiva. Usa un ancho limitado con clamp y
aspect-ratio, y ajusta el tamaño de la superficie de dibujo de Rive al cargar. - Ajusta el rendimiento y el movimiento. Pausa los overlays fuera de la pantalla, comparte el contexto WebGL entre instancias de Rive y oculta o congela el overlay con movimiento reducido.
Preguntas frecuentes
¿Por qué mi WebM transparente muestra un recuadro negro en Safari?
Safari reproduce WebM pero descarta el canal alfa de VP9, así que las zonas transparentes se ven opacas. Agrega un .mov HEVC con alfa como primera fuente dentro del elemento video: Safari lo elige, mientras que Chrome, Edge y Firefox lo omiten y usan el WebM.
¿Un canvas de Rive es transparente por defecto?
Sí. El canvas solo dibuja el arte del artboard, así que las zonas sin relleno dejan ver la página que hay detrás. Si ves un fondo sólido, es porque el propio artboard tiene un relleno en el archivo de origen o porque hay un color de fondo CSS definido en el elemento canvas o en su contenedor.
¿Cómo hago que los clics atraviesen un overlay de animación?
Aplica pointer-events: none al elemento del overlay en CSS. En SwiftUI usa .allowsHitTesting(false). Ten en cuenta que esto también desactiva los listeners de puntero propios de Rive, así que, si el personaje necesita reaccionar, contrólalo con triggers desde el código. Mantén cualquier parte interactiva en un elemento separado y más pequeño.
¿Puedo superponer una animación transparente sobre un video?
Sí. Coloca ambos en un contenedor posicionado y pon la animación transparente por encima del video de fondo con un canvas o un segundo elemento video con posición absoluta. Mantén el overlay sin sonido y decorativo, y pausa ambos cuando salgan del viewport para ahorrar batería y CPU.
Respuestas rápidas de esta guía
Fuentes
- Video with alpha transparency on the web, Jake Archibald
- New video policies for iOS, WebKit
- How to create high-performance CSS animations, web.dev
- Web (JS) runtime, Rive
- Canvas vs WebGL, Rive
- Understanding SC 2.2.2: Pause, Stop, Hide, W3C WAI
- Understanding SC 2.3.1: Three Flashes or Below Threshold, W3C WAI
- prefers-reduced-motion, MDN Web Docs