Logo
Comenzar Iniciar sesión
EN | ES

Cómo hacer un popup en HTML

Publicado en: 21 Ago 2025

No hace falta un framework para crear un buen popup. Con HTML semántico, un poco de CSS moderno y JavaScript puro podés construir una ventana modal rápida, accesible y lista para convertir tanto en escritorio como en móvil. En esta guía vas a programar un componente reutilizable, elegir disparadores y tiempos efectivos, y optimizarlo para usuarios reales.

Si necesitás contexto estratégico, repasá estas mejores prácticas de ventanas emergentes y elegí momentos inteligentes como se explica en cuándo mostrar una ventana emergente. Si recién empezás, este resumen de qué es una ventana emergente te ubica rápidamente.

Lo que vas a construir

Una modal que:

  • Se abre con un botón y puede dispararse por tiempo o por scroll.

  • Bloquea el scroll mientras está visible y lo restaura al cerrar.

  • Atrae el foco del teclado, lo mantiene dentro, permite cerrar con Esc y admite cerrar al tocar el overlay.

  • Anima entrada y salida sin tirones.

  • Es fácil de personalizar y reutilizar.

Si preferís un camino guiado mientras practicás, guardá la Academia de I Love PopUps y clases como cómo crear popups sin programar o cómo analizar los datos de tus popups.

Paso 1. HTML semántico

Empezá con un botón disparador y el contenedor del diálogo. Usá role="dialog" y aria-modal="true". Ocultalo con hidden para que no aparezca en el árbol de accesibilidad.

<button id="openPopup" class="btn">Open offer</button>

<div id="popup" class="popup" role="dialog" aria-modal="true" aria-labelledby="popupTitle" aria-describedby="popupDesc" hidden>
  <div class="popup__overlay" data-close></div>

  <div class="popup__content" role="document">
    <button class="popup__close" aria-label="Close popup" data-close>&times;</button>

    <h2 id="popupTitle">Get 10% off your first order</h2>
    <p id="popupDesc">Join our list for tips, deals, and updates. Unsubscribe anytime.</p>

    <form class="popup__form" action="#" method="post" novalidate>
      <label for="email">Email</label>
      <input id="email" type="email" required placeholder="you@example.com" autocomplete="email">
      <button type="submit" class="btn btn--primary">Subscribe</button>
      <small class="form-hint">No spam. One-click opt out.</small>
    </form>
  </div>
</div>

Para ideas de diseño y microcopys que realmente convierten, mirá estas buenas prácticas para crear popups que convierten.

Paso 2. CSS claro y adaptable

Variables para tematizar, transiciones suaves con opacity y transform, y un overlay que cubre toda la pantalla. Evitá animaciones exageradas.

:root {
  --popup-bg: #ffffff;
  --overlay-bg: rgba(0, 0, 0, 0.5);
  --radius: 12px;
  --max-w: 520px;
  --gap: 16px;
}

.popup[hidden] { display: none; }

.popup__overlay {
  position: fixed; inset: 0; background: var(--overlay-bg);
  opacity: 0; transition: opacity 200ms ease;
}

.popup__content {
  position: fixed; inset: 0; display: grid; place-items: center;
  padding: 24px;
}

.popup__content > * {
  width: min(var(--max-w), calc(100vw - 32px));
  background: var(--popup-bg);
  border-radius: var(--radius);
  box-shadow: 0 10px 30px rgba(0,0,0,.15);
  padding: 24px;
  transform: translateY(20px) scale(.98);
  opacity: 0;
  transition: transform 220ms ease, opacity 220ms ease;
}

.popup.open .popup__overlay { opacity: 1; }
.popup.open .popup__content > * {
  transform: translateY(0) scale(1);
  opacity: 1;
}

.popup__close {
  position: absolute; top: 10px; right: 12px;
  background: transparent; border: 0; font-size: 24px; cursor: pointer;
}

.popup__form { display: grid; gap: var(--gap); margin-top: 8px; }
.btn { cursor: pointer; padding: 10px 16px; border: 1px solid #111; background: #fff; }
.btn--primary { background: #111; color: #fff; border-color: #111; }

Paso 3. JavaScript para abrir, cerrar y atrapar el foco

El script:

  • Alterna hidden y la clase .abierto.

  • Recuerda qué elemento tenía el foco y lo restaura al cerrar.

  • Atrapa el foco dentro del diálogo.

  • Cierra con overlay o con Esc.

<script>
  (() => {
    const popup = document.getElementById('popup');
    const openBtn = document.getElementById('openPopup');
    const overlay = popup.querySelector('.popup__overlay');
    const closeEls = popup.querySelectorAll('[data-close]');
    let lastFocus = null;

    function getFocusable(container) {
      return [...container.querySelectorAll(
        'a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex="-1"])'
      )].filter(el => el.offsetParent !== null);
    }

    function openPopup() {
      lastFocus = document.activeElement;
      popup.hidden = false;
      popup.classList.add('open');
      document.documentElement.style.overflow = 'hidden';
      const focusables = getFocusable(popup);
      if (focusables.length) focusables[0].focus();
      document.addEventListener('keydown', onKeydown);
      popup.addEventListener('keydown', trapFocus);
    }

    function closePopup() {
      popup.classList.remove('open');
      popup.hidden = true;
      document.documentElement.style.overflow = '';
      document.removeEventListener('keydown', onKeydown);
      popup.removeEventListener('keydown', trapFocus);
      if (lastFocus) lastFocus.focus();
    }

    function onKeydown(e) {
      if (e.key === 'Escape') closePopup();
    }

    function trapFocus(e) {
      if (e.key !== 'Tab') return;
      const f = getFocusable(popup);
      if (!f.length) return;
      const first = f[0], last = f[f.length - 1];
      if (e.shiftKey && document.activeElement === first) {
        last.focus(); e.preventDefault();
      } else if (!e.shiftKey && document.activeElement === last) {
        first.focus(); e.preventDefault();
      }
    }

    openBtn.addEventListener('click', openPopup);
    overlay.addEventListener('click', closePopup);
    closeEls.forEach(el => el.addEventListener('click', closePopup));

    // Optional triggers
    // 1) Timed trigger after 10 seconds
    setTimeout(() => { /* openPopup(); */ }, 10000);

    // 2) Scroll trigger at 50%
    const onScroll = () => {
      const scrolled = (window.scrollY + window.innerHeight) / document.documentElement.scrollHeight;
      if (scrolled > 0.5) {
        // openPopup();
        window.removeEventListener('scroll', onScroll);
      }
    };
    window.addEventListener('scroll', onScroll, { passive: true });
  })();
</script>

Para decidir el momento exacto, apoyate en cómo utilizar ventanas emergentes en tu web y en el análisis del impacto de un popup en tu sitio web.

Accesibilidad que ayuda a convertir

  • Roles y labels correctos: role="dialog" aria-modal="true" con aria-labelledby y aria-describedby.

  • Soporte de teclado completo: mover el foco al abrir, atraparlo y devolverlo al cerrar. Esc debe cerrar.

  • Foco visible: no elimines outlines sin reemplazarlos por un estilo claro.

  • Botón de cierre accesible y grande.

  • Preferencias de movimiento: considerá @media (prefers-reduced-motion: reduce) para reducir animaciones.

Para más hábitos que elevan usabilidad y resultados, mirá cómo aprovechar al máximo I Love PopUps.

UX y contenido que generan resultados

  • Beneficio concreto y específico. Incentivos claros suelen ganar.

  • Formularios cortos. Pedir solo email suele rendir más.

  • Timing contextual. En páginas informativas, suele funcionar mejor un disparador por scroll o salida. Ver ejemplos en cuándo mostrar una ventana emergente.

  • Cierre fácil. Botón visible y overlay que acepta clic.

  • No apiles modales.

  • Móvil primero. Objetivos táctiles grandes, espaciado generoso y texto legible.

  • Coherencia visual con la marca. Para ideas prácticas, repasá estas mejores prácticas de ventanas emergentes.

Recetas de disparadores habituales

Intención de salida en escritorio

(function() {
  let fired = false;
  function exitIntent(e) {
    if (fired) return;
    if (e.clientY <= 0) {
      // openPopup();
      fired = true;
      window.removeEventListener('mouseout', exitIntent);
    }
  }
  window.addEventListener('mouseout', exitIntent);
})();

Mostrar después de cierta interacción

let interactions = 0;
function maybeShow() {
  interactions += 1;
  if (interactions === 2) {
    // openPopup();
    document.removeEventListener('click', maybeShow);
    document.removeEventListener('scroll', maybeShow);
  }
}
document.addEventListener('click', maybeShow, { passive: true });
document.addEventListener('scroll', maybeShow, { passive: true });

Una sola vez por sesión

if (!sessionStorage.getItem('nl-popup')) {
  setTimeout(() => {
    // openPopup();
    sessionStorage.setItem('nl-popup', '1');
  }, 8000);
}

Medir y mejorar con A/B testing

Cambios pequeños en el título, imagen o timing pueden mover mucho la aguja. La forma más rápida de aprender es hacer test A/B en tus popups. Probá una variable por vez, corré el test el tiempo suficiente y quedate con el ganador para luego iterar.

Cuando tengas datos, practicá cómo analizar los datos de tus popups: mirá vistas, CTR, envíos del formulario y resultados posteriores como compras o registros.

Integrarlo en tu sitio

Si tu sitio usa un constructor o plantillas, podés insertar el HTML en el layout y cargar el script global. Si preferís pegar un único snippet, esta guía sobre cómo instalar un script en tu sitio web te ayuda a ubicar el código sin romper el renderizado inicial.

Errores comunes a evitar

  • Ocultar o minimizar demasiado el botón de cierre.

  • Repetir el mismo popup varias veces en la misma sesión.

  • Disparar demasiado pronto cuando la persona aún se orienta.

  • Validaciones que bloquean la navegación por teclado.

  • Animaciones excesivas que ignoran prefers-reduced-motion.

Para profundizar

Publicá tu primera versión, juntá datos una semana y volvé a iterar. Los popups funcionan cuando se sienten oportunos, relevantes y respetuosos.

Signature

I Love PopUps Staff

Este artículo fue escrito por el equipo de I Love PopUps, una plataforma pensada para facilitar la creación y gestión de banners y popups sin complicaciones técnicas. Nuestro objetivo es ayudar a agencias y dueños de tiendas online a captar más atención y mejorar sus conversiones con herramientas simples, efectivas y fáciles de implementar.