Solución de problemas

Soluciones para las peculiaridades de iOS Safari, la reproducción de vídeo, la pantalla completa y la navegación con teclado.

iOS Safari

El viewport no llena la pantalla / franja negra abajo

La barra de direcciones plegable de Safari hace que 100vh sea más alto que el área visible. Usa 100dvh:

css
.slider-container {
  height: 100dvh; /* not 100vh */
}

Scroll horizontal / el contenido se desborda

En iOS, 100vw incluye el ancho de la barra de desplazamiento y empuja el contenido más allá del borde. Usa 100% y bloquea el desbordamiento horizontal:

css
html, body {
  overflow-x: hidden;
}

.slider-container {
  width: 100%; /* not 100vw */
}

Tirar para recargar / rebote elástico

El gesto de tirar para recargar y el rebote elástico de Safari compiten con los gestos verticales. No pongas overscroll-behavior: none en html, body: eso anula el scroll normal de la página. ReelPlayerOverlay, LightboxOverlay y StoriesPlayerOverlay ya lo resuelven en sus propios contenedores. En diseños propios, limítalo a un contenedor:

css
.slider-container {
  overscroll-behavior: none;
}

Caso límite de SwipeToClose hacia abajo. Cualquier SwipeToClose con direction="down" (lightbox, Stories Player, overlays propios) queda anulado en iOS Safari: el navegador lanza el tirar para recargar desde el documento antes de que el contenedor reciba el toque. El overlay bloquea el scroll del body, pero el navegador sigue controlando el desplazamiento vertical en la raíz. Aplica overscroll-behavior-y: contain en <html> solo mientras el overlay está abierto y restáuralo al cerrar:

tsx
useEffect(() => {
  if (!isOpen) return;
  const html = document.documentElement;
  const prev = html.style.overscrollBehaviorY;
  html.style.overscrollBehaviorY = 'contain';
  return () => {
    html.style.overscrollBehaviorY = prev;
  };
}, [isOpen]);

El zoom con los dedos interfiere con los gestos

Desactiva el zoom para que ni el pellizco ni el doble toque se disparen al deslizar:

html
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover" />

viewport-fit=cover extiende el diseño hasta la zona segura de la Dynamic Island o el notch.

El diseño se rompe al cerrar el teclado

A veces Safari deja el viewport comprimido después de cerrar el teclado. Fuerza un reajuste en el blur:

tsx
// React
<input
  onBlur={() => {
    window.scrollTo(0, 0);
    apiRef.current?.adjust();
  }}
/>

// Angular
(blur)="onInputBlur()"

onInputBlur() {
  window.scrollTo(0, 0);
  this.reelApi?.adjust();
}

General

Los slides se renderizan con tamaño 0×0

Sin la prop size, el slider lee las dimensiones de su contenedor con ResizeObserver. Un contenedor sin altura en el CSS mide 0×0, así que no se renderiza nada. Pasa size o da dimensiones al contenedor:

css
/* The parent must have a height for auto-sizing to work */
.slider-container {
  width: 100%;
  height: 100dvh;
}

Vídeo

El vídeo no se reproduce solo

Los navegadores bloquean la reproducción automática con sonido. ReelKit pone muted y playsInline en cada elemento de vídeo. Los vídeos empiezan en silencio y el usuario activa el sonido con el botón tras un toque. Comprueba que no sobrescribes estos atributos en un slide propio.

La miniatura o captura de fotograma del vídeo sale en blanco

La captura de fotogramas dibuja el vídeo en un <canvas>. Los vídeos de otro origen contaminan el canvas, así que el dibujo falla sin avisar. La CDN de tus vídeos debe devolver cabeceras CORS:

text
Access-Control-Allow-Origin: *

ReelKit pone crossOrigin="anonymous" por defecto. Si usas un elemento de vídeo propio, añádelo tú.

Pantalla completa

El botón de pantalla completa no hace nada en Safari

ReelKit desactiva la Fullscreen API en Safari. iOS Safari solo permite la pantalla completa en elementos <video>. Safari de escritorio rompe los overlays con position: fixed en pantalla completa: los elementos pierden su contexto de apilamiento o desaparecen. En Safari, requestFullscreen() se resuelve sin hacer nada.

Navegación con teclado

Las flechas no navegan después de pasar onNavKeyPress

onNavKeyPress sustituye la navegación con teclado por defecto. ReelKit deja de llamar a next()/prev() y te cede el control. Llámalos tú:

tsx
<Reel
  onNavKeyPress={(increment) => {
    // Your custom logic here
    console.log('Nav key:', increment);
    // You must trigger navigation yourself:
    apiRef.current?.[increment === 1 ? 'next' : 'prev']();
  }}
/>

La tecla Escape no cierra el overlay

El controlador de teclado solo gestiona las flechas. ReelPlayerOverlay y LightboxOverlay escuchan Escape por separado. Si creas un overlay propio, añade tu propio manejador de Escape en onClose.