Banner de Consentimiento de Cookies con Tarjeta Flotante
Un elegante banner de consentimiento de cookies estilo tarjeta flotante con animaciones suaves, efectos hover y patrones de diseño de tarjetas modernas
Diseño Responsivo
Sí
Soporte para Modo Oscuro
No
líneas
1156
Compatibilidad del Navegador
No
Vista Previa en Vivo
Interactúa con el componente sin salir de la página.
Banner de Consentimiento de Cookies con Tarjeta Flotante
Un banner de consentimiento de cookies bellamente diseñado estilo tarjeta flotante que aparece con animaciones suaves y elegantes efectos hover. Presenta un diseño de tarjeta moderno con sombras sutiles, esquinas redondeadas y elementos interactivos que mejoran la participación del usuario.
Características
- Diseño de Tarjeta Flotante: Diseño elegante estilo tarjeta con sombras sutiles y esquinas redondeadas
- Animaciones Suaves: Animaciones de entrada fluidas y micro-interacciones
- Efectos Hover: Estados hover interactivos con transiciones de escala y sombra
- Tipografía Moderna: Fuentes limpias y legibles con jerarquía adecuada
- Cumple RGPD: Gestión completa de consentimiento con controles granulares
- Accesibilidad Primero: Navegación completa por teclado y soporte para lectores de pantalla
- Diseño Responsivo: Se adapta hermosamente a todos los tamaños y orientaciones de pantalla
- Estilo Personalizable: Fácil personalización de temas con variables CSS
- Optimizado para Rendimiento: Implementación ligera y de carga rápida
Vista Previa
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Banner de Cookies Tarjeta Flotante</title>
<style>
:root {
--color-primario: #3b82f6;
--color-primario-hover: #2563eb;
--color-secundario: #6b7280;
--color-exito: #10b981;
--color-exito-hover: #059669;
--color-peligro: #ef4444;
--color-peligro-hover: #dc2626;
--fondo: #ffffff;
--superficie: #f8fafc;
--texto-primario: #1f2937;
--texto-secundario: #6b7280;
--texto-silenciado: #9ca3af;
--color-borde: #e5e7eb;
--sombra-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--sombra-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
--sombra-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
--sombra-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
--radio-borde: 12px;
--radio-borde-lg: 16px;
--transicion: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
--transicion-rapida: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
color: var(--texto-primario);
line-height: 1.6;
padding: 2rem;
}
.contenedor-demo {
max-width: 1200px;
margin: 0 auto;
text-align: center;
color: white;
}
.contenedor-demo h1 {
font-size: 3rem;
font-weight: 800;
margin-bottom: 1rem;
background: linear-gradient(135deg, #ffffff 0%, #f0f0f0 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.contenedor-demo p {
font-size: 1.2rem;
opacity: 0.9;
margin-bottom: 2rem;
}
.btn-demo {
padding: 1rem 2rem;
border: none;
border-radius: var(--radio-borde);
background: rgba(255, 255, 255, 0.2);
backdrop-filter: blur(10px);
color: white;
font-family: inherit;
font-size: 1.1rem;
font-weight: 600;
cursor: pointer;
transition: var(--transicion);
border: 1px solid rgba(255, 255, 255, 0.3);
}
.btn-demo:hover {
background: rgba(255, 255, 255, 0.3);
transform: translateY(-2px);
box-shadow: var(--sombra-lg);
}
/* Banner de Cookies Tarjeta Flotante */
.banner-cookies-flotante {
position: fixed;
bottom: 2rem;
right: 2rem;
width: 420px;
max-width: calc(100vw - 4rem);
background: var(--fondo);
border-radius: var(--radio-borde-lg);
box-shadow: var(--sombra-xl);
border: 1px solid var(--color-borde);
overflow: hidden;
transform: translateY(120%) scale(0.8);
opacity: 0;
transition: var(--transicion);
z-index: 10000;
backdrop-filter: blur(20px);
}
.banner-cookies-flotante.mostrar {
transform: translateY(0) scale(1);
opacity: 1;
}
.banner-cookies-flotante:hover {
transform: translateY(-4px) scale(1.02);
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
}
.encabezado-banner {
background: linear-gradient(135deg, var(--color-primario) 0%, var(--color-primario-hover) 100%);
padding: 1.5rem;
color: white;
position: relative;
overflow: hidden;
}
.encabezado-banner::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
animation: brillo 3s infinite;
}
@keyframes brillo {
0% { left: -100%; }
100% { left: 100%; }
}
.icono-banner {
width: 48px;
height: 48px;
background: rgba(255, 255, 255, 0.2);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
margin-bottom: 1rem;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.3);
animation: flotar 3s ease-in-out infinite;
}
@keyframes flotar {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-5px); }
}
.titulo-banner {
font-size: 1.25rem;
font-weight: 700;
margin-bottom: 0.5rem;
position: relative;
z-index: 1;
}
.subtitulo-banner {
font-size: 0.9rem;
opacity: 0.9;
position: relative;
z-index: 1;
}
.contenido-banner {
padding: 1.5rem;
}
.descripcion-cookies {
color: var(--texto-secundario);
font-size: 0.95rem;
line-height: 1.6;
margin-bottom: 1.5rem;
}
.enlace-cookies {
color: var(--color-primario);
text-decoration: none;
font-weight: 600;
transition: var(--transicion-rapida);
position: relative;
}
.enlace-cookies::after {
content: '';
position: absolute;
bottom: -2px;
left: 0;
width: 0;
height: 2px;
background: var(--color-primario);
transition: width 0.3s ease;
}
.enlace-cookies:hover {
color: var(--color-primario-hover);
}
.enlace-cookies:hover::after {
width: 100%;
}
.acciones-cookies {
display: flex;
gap: 0.75rem;
margin-top: 1.5rem;
}
/* Botones de Tarjeta */
.btn-tarjeta {
flex: 1;
padding: 0.75rem 1rem;
border: none;
border-radius: var(--radio-borde);
font-family: inherit;
font-size: 0.9rem;
font-weight: 600;
cursor: pointer;
transition: var(--transicion);
position: relative;
overflow: hidden;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.btn-tarjeta::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
background: rgba(255, 255, 255, 0.2);
border-radius: 50%;
transform: translate(-50%, -50%);
transition: width 0.6s ease, height 0.6s ease;
}
.btn-tarjeta:hover::before {
width: 300px;
height: 300px;
}
.btn-aceptar {
background: var(--color-exito);
color: white;
box-shadow: var(--sombra-md);
}
.btn-aceptar:hover {
background: var(--color-exito-hover);
transform: translateY(-2px);
box-shadow: var(--sombra-lg);
}
.btn-rechazar {
background: var(--color-peligro);
color: white;
box-shadow: var(--sombra-md);
}
.btn-rechazar:hover {
background: var(--color-peligro-hover);
transform: translateY(-2px);
box-shadow: var(--sombra-lg);
}
.btn-configuracion {
background: var(--superficie);
color: var(--texto-primario);
border: 1px solid var(--color-borde);
box-shadow: var(--sombra-sm);
}
.btn-configuracion:hover {
background: var(--color-borde);
transform: translateY(-2px);
box-shadow: var(--sombra-md);
}
.btn-tarjeta:active {
transform: translateY(0);
}
/* Modal de Configuración */
.modal-configuracion-cookies {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(8px);
display: flex;
align-items: center;
justify-content: center;
z-index: 10001;
opacity: 0;
visibility: hidden;
transition: var(--transicion);
}
.modal-configuracion-cookies.mostrar {
opacity: 1;
visibility: visible;
}
.tarjeta-configuracion {
background: var(--fondo);
border-radius: var(--radio-borde-lg);
box-shadow: var(--sombra-xl);
border: 1px solid var(--color-borde);
width: 90%;
max-width: 600px;
max-height: 80vh;
overflow: hidden;
transform: scale(0.9) translateY(20px);
transition: var(--transicion);
}
.modal-configuracion-cookies.mostrar .tarjeta-configuracion {
transform: scale(1) translateY(0);
}
.encabezado-configuracion {
background: linear-gradient(135deg, var(--color-primario) 0%, var(--color-primario-hover) 100%);
padding: 2rem;
color: white;
display: flex;
justify-content: space-between;
align-items: center;
}
.titulo-configuracion {
font-size: 1.5rem;
font-weight: 700;
}
.btn-cerrar {
width: 40px;
height: 40px;
border: none;
border-radius: 50%;
background: rgba(255, 255, 255, 0.2);
color: white;
font-size: 1.25rem;
cursor: pointer;
transition: var(--transicion-rapida);
display: flex;
align-items: center;
justify-content: center;
backdrop-filter: blur(10px);
}
.btn-cerrar:hover {
background: rgba(255, 255, 255, 0.3);
transform: scale(1.1) rotate(90deg);
}
.cuerpo-configuracion {
padding: 2rem;
max-height: 60vh;
overflow-y: auto;
}
.categoria-cookies {
margin-bottom: 2rem;
padding: 1.5rem;
background: var(--superficie);
border: 1px solid var(--color-borde);
border-radius: var(--radio-borde);
transition: var(--transicion-rapida);
}
.categoria-cookies:hover {
box-shadow: var(--sombra-md);
transform: translateY(-1px);
}
.encabezado-categoria {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
}
.titulo-categoria {
font-weight: 700;
font-size: 1.1rem;
color: var(--texto-primario);
}
.descripcion-categoria {
font-size: 0.9rem;
color: var(--texto-secundario);
line-height: 1.6;
}
/* Interruptor de Tarjeta */
.interruptor-tarjeta {
position: relative;
width: 56px;
height: 28px;
background: var(--color-borde);
border-radius: 14px;
cursor: pointer;
transition: var(--transicion);
border: 2px solid transparent;
}
.interruptor-tarjeta.activo {
background: var(--color-exito);
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);
}
.interruptor-tarjeta::before {
content: '';
position: absolute;
top: 2px;
left: 2px;
width: 20px;
height: 20px;
background: white;
border-radius: 50%;
transition: var(--transicion);
box-shadow: var(--sombra-sm);
}
.interruptor-tarjeta.activo::before {
transform: translateX(28px);
box-shadow: var(--sombra-md);
}
.interruptor-tarjeta:hover {
transform: scale(1.05);
}
.acciones-configuracion {
display: flex;
gap: 1rem;
justify-content: flex-end;
padding: 1.5rem 2rem;
background: var(--superficie);
border-top: 1px solid var(--color-borde);
}
/* Diseño Responsivo */
@media (max-width: 768px) {
.banner-cookies-flotante {
bottom: 1rem;
right: 1rem;
left: 1rem;
width: auto;
max-width: none;
}
.banner-cookies-flotante:hover {
transform: translateY(-2px) scale(1.01);
}
.acciones-cookies {
flex-direction: column;
}
.btn-tarjeta {
flex: none;
}
.tarjeta-configuracion {
margin: 1rem;
width: calc(100% - 2rem);
}
.encabezado-configuracion {
padding: 1.5rem;
}
.cuerpo-configuracion {
padding: 1.5rem;
}
.acciones-configuracion {
padding: 1rem 1.5rem;
flex-direction: column;
}
}
@media (max-width: 480px) {
body {
padding: 1rem;
}
.contenedor-demo h1 {
font-size: 2rem;
}
.banner-cookies-flotante {
bottom: 0.5rem;
right: 0.5rem;
left: 0.5rem;
}
.encabezado-banner {
padding: 1rem;
}
.contenido-banner {
padding: 1rem;
}
}
/* Animación de Carga */
.puntos-carga {
display: inline-flex;
gap: 4px;
}
.puntos-carga span {
width: 6px;
height: 6px;
background: currentColor;
border-radius: 50%;
animation: carga 1.4s infinite ease-in-out;
}
.puntos-carga span:nth-child(1) { animation-delay: -0.32s; }
.puntos-carga span:nth-child(2) { animation-delay: -0.16s; }
@keyframes carga {
0%, 80%, 100% {
transform: scale(0.8);
opacity: 0.5;
}
40% {
transform: scale(1);
opacity: 1;
}
}
/* Animación de Éxito */
.marca-exito {
width: 20px;
height: 20px;
border-radius: 50%;
display: inline-block;
stroke-width: 2;
stroke: currentColor;
stroke-miterlimit: 10;
box-shadow: inset 0px 0px 0px currentColor;
animation: llenar 0.4s ease-in-out 0.4s forwards, escalar 0.3s ease-in-out 0.9s both;
}
.circulo-marca-exito {
stroke-dasharray: 166;
stroke-dashoffset: 166;
stroke-width: 2;
stroke-miterlimit: 10;
stroke: currentColor;
fill: none;
animation: trazo 0.6s cubic-bezier(0.65, 0, 0.45, 1) forwards;
}
.check-marca-exito {
transform-origin: 50% 50%;
stroke-dasharray: 48;
stroke-dashoffset: 48;
animation: trazo 0.3s cubic-bezier(0.65, 0, 0.45, 1) 0.8s forwards;
}
@keyframes trazo {
100% {
stroke-dashoffset: 0;
}
}
@keyframes escalar {
0%, 100% {
transform: none;
}
50% {
transform: scale3d(1.1, 1.1, 1);
}
}
@keyframes llenar {
100% {
box-shadow: inset 0px 0px 0px 30px currentColor;
}
}
</style>
</head>
<body>
<div class="contenedor-demo">
<h1>Diseño de Tarjeta Flotante</h1>
<p>Experimenta la elegancia del diseño de tarjeta flotante con animaciones suaves e interacciones modernas</p>
<button class="btn-demo" onclick="mostrarBannerCookies()">Mostrar Banner de Cookies</button>
</div>
<!-- Banner de Cookies Flotante -->
<div id="bannerCookiesFlotante" class="banner-cookies-flotante">
<div class="encabezado-banner">
<div class="icono-banner">🍪</div>
<div class="titulo-banner">Preferencias de Cookies</div>
<div class="subtitulo-banner">Valoramos tu privacidad</div>
</div>
<div class="contenido-banner">
<div class="descripcion-cookies">
Utilizamos cookies para mejorar tu experiencia de navegación y proporcionar contenido personalizado.
<a href="#" class="enlace-cookies">Política de Privacidad</a> |
<a href="#" class="enlace-cookies">Política de Cookies</a>
</div>
<div class="acciones-cookies">
<button class="btn-tarjeta btn-aceptar" onclick="aceptarCookies()">Aceptar Todo</button>
<button class="btn-tarjeta btn-rechazar" onclick="rechazarCookies()">Rechazar</button>
<button class="btn-tarjeta btn-configuracion" onclick="abrirConfiguracion()">Personalizar</button>
</div>
</div>
</div>
<!-- Modal de Configuración -->
<div id="modalConfiguracionCookies" class="modal-configuracion-cookies">
<div class="tarjeta-configuracion">
<div class="encabezado-configuracion">
<h3 class="titulo-configuracion">Configuración de Cookies</h3>
<button class="btn-cerrar" onclick="cerrarConfiguracion()">×</button>
</div>
<div class="cuerpo-configuracion">
<div class="categoria-cookies">
<div class="encabezado-categoria">
<span class="titulo-categoria">Cookies Esenciales</span>
<div class="interruptor-tarjeta activo" data-categoria="esenciales"></div>
</div>
<div class="descripcion-categoria">
Estas cookies son necesarias para que el sitio web funcione y no se pueden desactivar. Generalmente solo se establecen en respuesta a acciones realizadas por ti.
</div>
</div>
<div class="categoria-cookies">
<div class="encabezado-categoria">
<span class="titulo-categoria">Cookies de Análisis</span>
<div class="interruptor-tarjeta" data-categoria="analiticas"></div>
</div>
<div class="descripcion-categoria">
Estas cookies nos ayudan a entender cómo los visitantes interactúan con nuestro sitio web recopilando y reportando información de forma anónima.
</div>
</div>
<div class="categoria-cookies">
<div class="encabezado-categoria">
<span class="titulo-categoria">Cookies de Marketing</span>
<div class="interruptor-tarjeta" data-categoria="marketing"></div>
</div>
<div class="descripcion-categoria">
Estas cookies se utilizan para entregar anuncios más relevantes para ti y tus intereses basados en tu comportamiento de navegación.
</div>
</div>
<div class="categoria-cookies">
<div class="encabezado-categoria">
<span class="titulo-categoria">Cookies Funcionales</span>
<div class="interruptor-tarjeta" data-categoria="funcionales"></div>
</div>
<div class="descripcion-categoria">
Estas cookies habilitan funcionalidad mejorada y personalización, como recordar tus preferencias y configuraciones.
</div>
</div>
</div>
<div class="acciones-configuracion">
<button class="btn-tarjeta btn-rechazar" onclick="guardarConfiguracion(false)">Guardar Preferencias</button>
<button class="btn-tarjeta btn-aceptar" onclick="guardarConfiguracion(true)">Aceptar Todo</button>
</div>
</div>
</div>
<script>
class BannerCookiesTarjetaFlotante {
constructor(opciones = {}) {
this.opciones = {
mostrarAuto: true,
retrasoMostrar: 1500,
claveAlmacenamiento: 'consentimiento_cookies_tarjeta_flotante',
diasExpiracion: 365,
habilitarAnimaciones: true,
posicion: 'abajo-derecha',
alAceptar: null,
alRechazar: null,
alGuardarConfiguracion: null,
...opciones
};
this.banner = document.getElementById('bannerCookiesFlotante');
this.modal = document.getElementById('modalConfiguracionCookies');
this.consentimiento = this.obtenerConsentimientoAlmacenado();
this.esVisible = false;
this.inicializar();
}
inicializar() {
if (this.opciones.mostrarAuto && !this.consentimiento) {
setTimeout(() => this.mostrar(), this.opciones.retrasoMostrar);
}
this.configurarEventListeners();
this.cargarConfiguracion();
this.configurarPosicion();
}
configurarEventListeners() {
// Interruptores de alternancia
document.querySelectorAll('.interruptor-tarjeta').forEach(interruptor => {
interruptor.addEventListener('click', () => {
if (interruptor.dataset.categoria !== 'esenciales') {
interruptor.classList.toggle('activo');
this.animarInterruptor(interruptor);
}
});
});
// Clic en el fondo del modal
this.modal.addEventListener('click', (e) => {
if (e.target === this.modal) {
this.cerrarConfiguracion();
}
});
// Navegación por teclado
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
this.cerrarConfiguracion();
}
});
// Efectos hover de botones
document.querySelectorAll('.btn-tarjeta').forEach(btn => {
btn.addEventListener('mouseenter', () => {
this.crearOnda(btn);
});
});
// Efectos hover del banner
this.banner.addEventListener('mouseenter', () => {
if (this.esVisible) {
this.mejorarEfectoHover();
}
});
this.banner.addEventListener('mouseleave', () => {
if (this.esVisible) {
this.resetearEfectoHover();
}
});
}
configurarPosicion() {
const posiciones = {
'abajo-derecha': { bottom: '2rem', right: '2rem', left: 'auto', top: 'auto' },
'abajo-izquierda': { bottom: '2rem', left: '2rem', right: 'auto', top: 'auto' },
'arriba-derecha': { top: '2rem', right: '2rem', left: 'auto', bottom: 'auto' },
'arriba-izquierda': { top: '2rem', left: '2rem', right: 'auto', bottom: 'auto' }
};
const pos = posiciones[this.opciones.posicion] || posiciones['abajo-derecha'];
Object.assign(this.banner.style, pos);
}
animarInterruptor(interruptor) {
if (!this.opciones.habilitarAnimaciones) return;
interruptor.style.transform = 'scale(0.9)';
setTimeout(() => {
interruptor.style.transform = 'scale(1)';
}, 150);
// Agregar efecto de pulso
interruptor.style.boxShadow = '0 0 0 8px rgba(16, 185, 129, 0.2)';
setTimeout(() => {
interruptor.style.boxShadow = '';
}, 300);
}
crearOnda(boton) {
if (!this.opciones.habilitarAnimaciones) return;
const onda = document.createElement('span');
const rect = boton.getBoundingClientRect();
const tamaño = Math.max(rect.width, rect.height);
onda.style.width = onda.style.height = tamaño + 'px';
onda.style.left = '50%';
onda.style.top = '50%';
onda.style.transform = 'translate(-50%, -50%) scale(0)';
onda.style.position = 'absolute';
onda.style.borderRadius = '50%';
onda.style.background = 'rgba(255, 255, 255, 0.3)';
onda.style.pointerEvents = 'none';
onda.style.animation = 'onda 0.6s ease-out';
boton.style.position = 'relative';
boton.style.overflow = 'hidden';
boton.appendChild(onda);
setTimeout(() => {
onda.remove();
}, 600);
}
mejorarEfectoHover() {
if (!this.opciones.habilitarAnimaciones) return;
const icono = this.banner.querySelector('.icono-banner');
if (icono) {
icono.style.transform = 'scale(1.1) rotate(5deg)';
}
}
resetearEfectoHover() {
if (!this.opciones.habilitarAnimaciones) return;
const icono = this.banner.querySelector('.icono-banner');
if (icono) {
icono.style.transform = '';
}
}
mostrar() {
this.banner.classList.add('mostrar');
this.esVisible = true;
if (this.opciones.habilitarAnimaciones) {
this.animarEntrada();
}
}
ocultar() {
this.banner.classList.remove('mostrar');
this.esVisible = false;
}
animarEntrada() {
const elementos = [
this.banner.querySelector('.icono-banner'),
this.banner.querySelector('.titulo-banner'),
this.banner.querySelector('.subtitulo-banner'),
this.banner.querySelector('.descripcion-cookies'),
this.banner.querySelector('.acciones-cookies')
];
elementos.forEach((el, index) => {
if (el) {
el.style.opacity = '0';
el.style.transform = 'translateY(20px)';
setTimeout(() => {
el.style.transition = 'all 0.6s cubic-bezier(0.4, 0, 0.2, 1)';
el.style.opacity = '1';
el.style.transform = 'translateY(0)';
}, index * 100);
}
});
}
aceptar() {
const consentimiento = {
esenciales: true,
analiticas: true,
marketing: true,
funcionales: true,
marcaTiempo: Date.now()
};
this.guardarConsentimiento(consentimiento);
this.mostrarAnimacionExito();
setTimeout(() => {
this.ocultar();
}, 1500);
if (this.opciones.alAceptar) {
this.opciones.alAceptar(consentimiento);
}
}
rechazar() {
const consentimiento = {
esenciales: true,
analiticas: false,
marketing: false,
funcionales: false,
marcaTiempo: Date.now()
};
this.guardarConsentimiento(consentimiento);
this.ocultar();
if (this.opciones.alRechazar) {
this.opciones.alRechazar(consentimiento);
}
}
mostrarAnimacionExito() {
if (!this.opciones.habilitarAnimaciones) return;
const btnAceptar = this.banner.querySelector('.btn-aceptar');
if (btnAceptar) {
btnAceptar.innerHTML = `
<svg class="marca-exito" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52">
<circle class="circulo-marca-exito" cx="26" cy="26" r="25" fill="none"/>
<path class="check-marca-exito" fill="none" d="m14.1 27.2l7.1 7.2 16.7-16.8"/>
</svg>
Aceptado
`;
btnAceptar.style.background = 'var(--color-exito)';
}
}
abrirConfiguracion() {
this.modal.classList.add('mostrar');
document.body.style.overflow = 'hidden';
if (this.opciones.habilitarAnimaciones) {
this.animarEntradaModal();
}
}
cerrarConfiguracion() {
this.modal.classList.remove('mostrar');
document.body.style.overflow = '';
}
animarEntradaModal() {
const categorias = this.modal.querySelectorAll('.categoria-cookies');
categorias.forEach((categoria, index) => {
categoria.style.opacity = '0';
categoria.style.transform = 'translateX(-20px)';
setTimeout(() => {
categoria.style.transition = 'all 0.4s cubic-bezier(0.4, 0, 0.2, 1)';
categoria.style.opacity = '1';
categoria.style.transform = 'translateX(0)';
}, index * 100);
});
}
guardarConfiguracion(aceptarTodo = false) {
const interruptores = document.querySelectorAll('.interruptor-tarjeta');
const consentimiento = { marcaTiempo: Date.now() };
interruptores.forEach(interruptor => {
const categoria = interruptor.dataset.categoria;
if (aceptarTodo) {
consentimiento[categoria] = true;
interruptor.classList.add('activo');
} else {
consentimiento[categoria] = interruptor.classList.contains('activo');
}
});
this.guardarConsentimiento(consentimiento);
this.cerrarConfiguracion();
this.ocultar();
if (this.opciones.alGuardarConfiguracion) {
this.opciones.alGuardarConfiguracion(consentimiento);
}
}
cargarConfiguracion() {
if (this.consentimiento) {
document.querySelectorAll('.interruptor-tarjeta').forEach(interruptor => {
const categoria = interruptor.dataset.categoria;
if (this.consentimiento[categoria]) {
interruptor.classList.add('activo');
} else {
interruptor.classList.remove('activo');
}
});
}
}
guardarConsentimiento(consentimiento) {
const fechaExpiracion = new Date();
fechaExpiracion.setDate(fechaExpiracion.getDate() + this.opciones.diasExpiracion);
const datosConsentimiento = {
...consentimiento,
expiracion: fechaExpiracion.getTime()
};
localStorage.setItem(this.opciones.claveAlmacenamiento, JSON.stringify(datosConsentimiento));
this.consentimiento = consentimiento;
}
obtenerConsentimientoAlmacenado() {
try {
const almacenado = localStorage.getItem(this.opciones.claveAlmacenamiento);
if (almacenado) {
const datos = JSON.parse(almacenado);
if (datos.expiracion && Date.now() < datos.expiracion) {
return datos;
} else {
localStorage.removeItem(this.opciones.claveAlmacenamiento);
}
}
} catch (e) {
console.error('Error al leer el consentimiento de cookies:', e);
}
return null;
}
resetear() {
localStorage.removeItem(this.opciones.claveAlmacenamiento);
this.consentimiento = null;
this.mostrar();
}
obtenerConsentimiento() {
return this.consentimiento;
}
establecerPosicion(posicion) {
this.opciones.posicion = posicion;
this.configurarPosicion();
}
habilitarAnimaciones(habilitado) {
this.opciones.habilitarAnimaciones = habilitado;
}
actualizarTema(tema) {
const temas = {
claro: {
'--fondo': '#ffffff',
'--superficie': '#f8fafc',
'--texto-primario': '#1f2937',
'--texto-secundario': '#6b7280'
},
oscuro: {
'--fondo': '#1f2937',
'--superficie': '#374151',
'--texto-primario': '#f9fafb',
'--texto-secundario': '#d1d5db'
}
};
if (temas[tema]) {
Object.entries(temas[tema]).forEach(([propiedad, valor]) => {
document.documentElement.style.setProperty(propiedad, valor);
});
}
}
}
// Agregar animación de onda CSS
const estilo = document.createElement('style');
estilo.textContent = `
@keyframes onda {
to {
transform: translate(-50%, -50%) scale(2);
opacity: 0;
}
}
`;
document.head.appendChild(estilo);
// Inicializar el banner
const bannerCookies = new BannerCookiesTarjetaFlotante({
posicion: 'abajo-derecha',
habilitarAnimaciones: true,
alAceptar: (consentimiento) => {
console.log('Cookies aceptadas:', consentimiento);
// Inicializar scripts de análisis, marketing, etc.
},
alRechazar: (consentimiento) => {
console.log('Cookies rechazadas:', consentimiento);
// Cargar solo scripts esenciales
},
alGuardarConfiguracion: (consentimiento) => {
console.log('Configuración guardada:', consentimiento);
// Cargar scripts basados en las preferencias del usuario
}
});
// Funciones globales para la demo
function mostrarBannerCookies() {
bannerCookies.resetear();
}
function aceptarCookies() {
bannerCookies.aceptar();
}
function rechazarCookies() {
bannerCookies.rechazar();
}
function abrirConfiguracion() {
bannerCookies.abrirConfiguracion();
}
function cerrarConfiguracion() {
bannerCookies.cerrarConfiguracion();
}
function guardarConfiguracion(aceptarTodo) {
bannerCookies.guardarConfiguracion(aceptarTodo);
}
</script>
</body>
</html>
Uso
Implementación Básica
// Inicializar con configuración predeterminada
const bannerCookies = new BannerCookiesTarjetaFlotante();
// Inicializar con opciones personalizadas
const bannerCookies = new BannerCookiesTarjetaFlotante({
mostrarAuto: true,
retrasoMostrar: 2000,
claveAlmacenamiento: 'mi_consentimiento_cookies',
diasExpiracion: 180,
habilitarAnimaciones: true,
posicion: 'abajo-izquierda',
alAceptar: (consentimiento) => {
console.log('Usuario aceptó cookies:', consentimiento);
// Cargar scripts de análisis
if (consentimiento.analiticas) {
cargarGoogleAnalytics();
}
// Cargar scripts de marketing
if (consentimiento.marketing) {
cargarPixelsMarketing();
}
},
alRechazar: (consentimiento) => {
console.log('Usuario rechazó cookies:', consentimiento);
// Cargar solo funcionalidad esencial
},
alGuardarConfiguracion: (consentimiento) => {
console.log('Usuario guardó configuración personalizada:', consentimiento);
// Cargar scripts basados en preferencias específicas
}
});
Configuración Avanzada
// Estilo personalizado y comportamiento
const bannerAvanzado = new BannerCookiesTarjetaFlotante({
mostrarAuto: false, // Control manual
retrasoMostrar: 0,
claveAlmacenamiento: 'consentimiento_avanzado',
diasExpiracion: 90,
habilitarAnimaciones: true,
posicion: 'arriba-derecha',
// Callbacks personalizados
alAceptar: (consentimiento) => {
// Configuración avanzada de análisis
inicializarSeguimientoAvanzado(consentimiento);
},
alRechazar: (consentimiento) => {
// Configuración mínima de seguimiento
inicializarSoloEsencial();
},
alGuardarConfiguracion: (consentimiento) => {
// Carga granular de scripts
cargarScriptsBasadosEnConsentimiento(consentimiento);
}
});
// Control de posición
function cambiarPosicion(posicion) {
bannerAvanzado.establecerPosicion(posicion);
}
// Control de animaciones
function alternarAnimaciones(habilitado) {
bannerAvanzado.habilitarAnimaciones(habilitado);
}
// Cambio de tema
function cambiarTema(tema) {
bannerAvanzado.actualizarTema(tema);
}
// Control manual
function mostrarBannerConsentimiento() {
bannerAvanzado.mostrar();
}
// Verificar estado actual de consentimiento
function verificarEstadoConsentimiento() {
const consentimiento = bannerAvanzado.obtenerConsentimiento();
if (consentimiento) {
console.log('Consentimiento actual:', consentimiento);
} else {
console.log('Aún no se ha dado consentimiento');
}
}
Métodos de la API
Métodos Principales
mostrar()- Mostrar el banner de cookiesocultar()- Ocultar el banner de cookiesaceptar()- Aceptar todas las cookies y ocultar bannerrechazar()- Rechazar cookies opcionales y ocultar bannerresetear()- Limpiar consentimiento almacenado y mostrar banner nuevamente
Gestión de Configuración
abrirConfiguracion()- Abrir el modal de configuracióncerrarConfiguracion()- Cerrar el modal de configuraciónguardarConfiguracion(aceptarTodo)- Guardar configuración actualcargarConfiguracion()- Cargar y aplicar configuración almacenada
Gestión de Datos
obtenerConsentimiento()- Obtener objeto de consentimiento actualguardarConsentimiento(consentimiento)- Guardar consentimiento en almacenamientoobtenerConsentimientoAlmacenado()- Recuperar consentimiento del almacenamiento
Personalización
establecerPosicion(posicion)- Cambiar posición del bannerhabilitarAnimaciones(habilitado)- Habilitar/deshabilitar animacionesactualizarTema(tema)- Cambiar entre temas claro/oscurocrearOnda(boton)- Crear efectos de onda en botones
Opciones de Personalización
Personalización Visual
- Esquemas de Color: Modificar propiedades CSS personalizadas para diferentes temas de color
- Velocidad de Animación: Ajustar duraciones de transición y tiempos de animación
- Estilo de Tarjeta: Personalizar radio de borde, sombras y espaciado
- Tipografía: Cambiar familias, tamaños y pesos de fuente
Configuración Funcional
- Visualización Automática: Controlar aparición automática del banner
- Duración de Almacenamiento: Establecer período de expiración del consentimiento de cookies
- Configuración de Retraso: Configurar timing de mostrar/ocultar
- Funciones de Callback: Manejadores personalizados para acciones del usuario
Características de Accesibilidad
- Navegación por Teclado: Soporte completo de teclado con indicadores de foco
- Soporte para Lectores de Pantalla: Etiquetas y descripciones ARIA apropiadas
- Alto Contraste: Visibilidad mejorada para accesibilidad
- Gestión de Foco: Captura adecuada de foco en modal
Compatibilidad de Navegadores
- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+
- Navegadores móviles (iOS Safari 12+, Chrome Mobile 60+)
Licencia
Licencia MIT - libre para usar en proyectos personales y comerciales.
HTML
1124
líneas
CSS
1
líneas
JavaScript
31
líneas
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Banner de Cookies Tarjeta Flotante</title>
<style>
:root {
--color-primario: #3b82f6;
--color-primario-hover: #2563eb;
--color-secundario: #6b7280;
--color-exito: #10b981;
--color-exito-hover: #059669;
--color-peligro: #ef4444;
--color-peligro-hover: #dc2626;
--fondo: #ffffff;
--superficie: #f8fafc;
--texto-primario: #1f2937;
--texto-secundario: #6b7280;
--texto-silenciado: #9ca3af;
--color-borde: #e5e7eb;
--sombra-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--sombra-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
--sombra-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
--sombra-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
--radio-borde: 12px;
--radio-borde-lg: 16px;
--transicion: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
--transicion-rapida: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
color: var(--texto-primario);
line-height: 1.6;
padding: 2rem;
}
.contenedor-demo {
max-width: 1200px;
margin: 0 auto;
text-align: center;
color: white;
}
.contenedor-demo h1 {
font-size: 3rem;
font-weight: 800;
margin-bottom: 1rem;
background: linear-gradient(135deg, #ffffff 0%, #f0f0f0 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.contenedor-demo p {
font-size: 1.2rem;
opacity: 0.9;
margin-bottom: 2rem;
}
.btn-demo {
padding: 1rem 2rem;
border: none;
border-radius: var(--radio-borde);
background: rgba(255, 255, 255, 0.2);
backdrop-filter: blur(10px);
color: white;
font-family: inherit;
font-size: 1.1rem;
font-weight: 600;
cursor: pointer;
transition: var(--transicion);
border: 1px solid rgba(255, 255, 255, 0.3);
}
.btn-demo:hover {
background: rgba(255, 255, 255, 0.3);
transform: translateY(-2px);
box-shadow: var(--sombra-lg);
}
/* Banner de Cookies Tarjeta Flotante */
.banner-cookies-flotante {
position: fixed;
bottom: 2rem;
right: 2rem;
width: 420px;
max-width: calc(100vw - 4rem);
background: var(--fondo);
border-radius: var(--radio-borde-lg);
box-shadow: var(--sombra-xl);
border: 1px solid var(--color-borde);
overflow: hidden;
transform: translateY(120%) scale(0.8);
opacity: 0;
transition: var(--transicion);
z-index: 10000;
backdrop-filter: blur(20px);
}
.banner-cookies-flotante.mostrar {
transform: translateY(0) scale(1);
opacity: 1;
}
.banner-cookies-flotante:hover {
transform: translateY(-4px) scale(1.02);
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
}
.encabezado-banner {
background: linear-gradient(135deg, var(--color-primario) 0%, var(--color-primario-hover) 100%);
padding: 1.5rem;
color: white;
position: relative;
overflow: hidden;
}
.encabezado-banner::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
animation: brillo 3s infinite;
}
@keyframes brillo {
0% { left: -100%; }
100% { left: 100%; }
}
.icono-banner {
width: 48px;
height: 48px;
background: rgba(255, 255, 255, 0.2);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
margin-bottom: 1rem;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.3);
animation: flotar 3s ease-in-out infinite;
}
@keyframes flotar {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-5px); }
}
.titulo-banner {
font-size: 1.25rem;
font-weight: 700;
margin-bottom: 0.5rem;
position: relative;
z-index: 1;
}
.subtitulo-banner {
font-size: 0.9rem;
opacity: 0.9;
position: relative;
z-index: 1;
}
.contenido-banner {
padding: 1.5rem;
}
.descripcion-cookies {
color: var(--texto-secundario);
font-size: 0.95rem;
line-height: 1.6;
margin-bottom: 1.5rem;
}
.enlace-cookies {
color: var(--color-primario);
text-decoration: none;
font-weight: 600;
transition: var(--transicion-rapida);
position: relative;
}
.enlace-cookies::after {
content: '';
position: absolute;
bottom: -2px;
left: 0;
width: 0;
height: 2px;
background: var(--color-primario);
transition: width 0.3s ease;
}
.enlace-cookies:hover {
color: var(--color-primario-hover);
}
.enlace-cookies:hover::after {
width: 100%;
}
.acciones-cookies {
display: flex;
gap: 0.75rem;
margin-top: 1.5rem;
}
/* Botones de Tarjeta */
.btn-tarjeta {
flex: 1;
padding: 0.75rem 1rem;
border: none;
border-radius: var(--radio-borde);
font-family: inherit;
font-size: 0.9rem;
font-weight: 600;
cursor: pointer;
transition: var(--transicion);
position: relative;
overflow: hidden;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.btn-tarjeta::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
background: rgba(255, 255, 255, 0.2);
border-radius: 50%;
transform: translate(-50%, -50%);
transition: width 0.6s ease, height 0.6s ease;
}
.btn-tarjeta:hover::before {
width: 300px;
height: 300px;
}
.btn-aceptar {
background: var(--color-exito);
color: white;
box-shadow: var(--sombra-md);
}
.btn-aceptar:hover {
background: var(--color-exito-hover);
transform: translateY(-2px);
box-shadow: var(--sombra-lg);
}
.btn-rechazar {
background: var(--color-peligro);
color: white;
box-shadow: var(--sombra-md);
}
.btn-rechazar:hover {
background: var(--color-peligro-hover);
transform: translateY(-2px);
box-shadow: var(--sombra-lg);
}
.btn-configuracion {
background: var(--superficie);
color: var(--texto-primario);
border: 1px solid var(--color-borde);
box-shadow: var(--sombra-sm);
}
.btn-configuracion:hover {
background: var(--color-borde);
transform: translateY(-2px);
box-shadow: var(--sombra-md);
}
.btn-tarjeta:active {
transform: translateY(0);
}
/* Modal de Configuración */
.modal-configuracion-cookies {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(8px);
display: flex;
align-items: center;
justify-content: center;
z-index: 10001;
opacity: 0;
visibility: hidden;
transition: var(--transicion);
}
.modal-configuracion-cookies.mostrar {
opacity: 1;
visibility: visible;
}
.tarjeta-configuracion {
background: var(--fondo);
border-radius: var(--radio-borde-lg);
box-shadow: var(--sombra-xl);
border: 1px solid var(--color-borde);
width: 90%;
max-width: 600px;
max-height: 80vh;
overflow: hidden;
transform: scale(0.9) translateY(20px);
transition: var(--transicion);
}
.modal-configuracion-cookies.mostrar .tarjeta-configuracion {
transform: scale(1) translateY(0);
}
.encabezado-configuracion {
background: linear-gradient(135deg, var(--color-primario) 0%, var(--color-primario-hover) 100%);
padding: 2rem;
color: white;
display: flex;
justify-content: space-between;
align-items: center;
}
.titulo-configuracion {
font-size: 1.5rem;
font-weight: 700;
}
.btn-cerrar {
width: 40px;
height: 40px;
border: none;
border-radius: 50%;
background: rgba(255, 255, 255, 0.2);
color: white;
font-size: 1.25rem;
cursor: pointer;
transition: var(--transicion-rapida);
display: flex;
align-items: center;
justify-content: center;
backdrop-filter: blur(10px);
}
.btn-cerrar:hover {
background: rgba(255, 255, 255, 0.3);
transform: scale(1.1) rotate(90deg);
}
.cuerpo-configuracion {
padding: 2rem;
max-height: 60vh;
overflow-y: auto;
}
.categoria-cookies {
margin-bottom: 2rem;
padding: 1.5rem;
background: var(--superficie);
border: 1px solid var(--color-borde);
border-radius: var(--radio-borde);
transition: var(--transicion-rapida);
}
.categoria-cookies:hover {
box-shadow: var(--sombra-md);
transform: translateY(-1px);
}
.encabezado-categoria {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
}
.titulo-categoria {
font-weight: 700;
font-size: 1.1rem;
color: var(--texto-primario);
}
.descripcion-categoria {
font-size: 0.9rem;
color: var(--texto-secundario);
line-height: 1.6;
}
/* Interruptor de Tarjeta */
.interruptor-tarjeta {
position: relative;
width: 56px;
height: 28px;
background: var(--color-borde);
border-radius: 14px;
cursor: pointer;
transition: var(--transicion);
border: 2px solid transparent;
}
.interruptor-tarjeta.activo {
background: var(--color-exito);
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);
}
.interruptor-tarjeta::before {
content: '';
position: absolute;
top: 2px;
left: 2px;
width: 20px;
height: 20px;
background: white;
border-radius: 50%;
transition: var(--transicion);
box-shadow: var(--sombra-sm);
}
.interruptor-tarjeta.activo::before {
transform: translateX(28px);
box-shadow: var(--sombra-md);
}
.interruptor-tarjeta:hover {
transform: scale(1.05);
}
.acciones-configuracion {
display: flex;
gap: 1rem;
justify-content: flex-end;
padding: 1.5rem 2rem;
background: var(--superficie);
border-top: 1px solid var(--color-borde);
}
/* Diseño Responsivo */
@media (max-width: 768px) {
.banner-cookies-flotante {
bottom: 1rem;
right: 1rem;
left: 1rem;
width: auto;
max-width: none;
}
.banner-cookies-flotante:hover {
transform: translateY(-2px) scale(1.01);
}
.acciones-cookies {
flex-direction: column;
}
.btn-tarjeta {
flex: none;
}
.tarjeta-configuracion {
margin: 1rem;
width: calc(100% - 2rem);
}
.encabezado-configuracion {
padding: 1.5rem;
}
.cuerpo-configuracion {
padding: 1.5rem;
}
.acciones-configuracion {
padding: 1rem 1.5rem;
flex-direction: column;
}
}
@media (max-width: 480px) {
body {
padding: 1rem;
}
.contenedor-demo h1 {
font-size: 2rem;
}
.banner-cookies-flotante {
bottom: 0.5rem;
right: 0.5rem;
left: 0.5rem;
}
.encabezado-banner {
padding: 1rem;
}
.contenido-banner {
padding: 1rem;
}
}
/* Animación de Carga */
.puntos-carga {
display: inline-flex;
gap: 4px;
}
.puntos-carga span {
width: 6px;
height: 6px;
background: currentColor;
border-radius: 50%;
animation: carga 1.4s infinite ease-in-out;
}
.puntos-carga span:nth-child(1) { animation-delay: -0.32s; }
.puntos-carga span:nth-child(2) { animation-delay: -0.16s; }
@keyframes carga {
0%, 80%, 100% {
transform: scale(0.8);
opacity: 0.5;
}
40% {
transform: scale(1);
opacity: 1;
}
}
/* Animación de Éxito */
.marca-exito {
width: 20px;
height: 20px;
border-radius: 50%;
display: inline-block;
stroke-width: 2;
stroke: currentColor;
stroke-miterlimit: 10;
box-shadow: inset 0px 0px 0px currentColor;
animation: llenar 0.4s ease-in-out 0.4s forwards, escalar 0.3s ease-in-out 0.9s both;
}
.circulo-marca-exito {
stroke-dasharray: 166;
stroke-dashoffset: 166;
stroke-width: 2;
stroke-miterlimit: 10;
stroke: currentColor;
fill: none;
animation: trazo 0.6s cubic-bezier(0.65, 0, 0.45, 1) forwards;
}
.check-marca-exito {
transform-origin: 50% 50%;
stroke-dasharray: 48;
stroke-dashoffset: 48;
animation: trazo 0.3s cubic-bezier(0.65, 0, 0.45, 1) 0.8s forwards;
}
@keyframes trazo {
100% {
stroke-dashoffset: 0;
}
}
@keyframes escalar {
0%, 100% {
transform: none;
}
50% {
transform: scale3d(1.1, 1.1, 1);
}
}
@keyframes llenar {
100% {
box-shadow: inset 0px 0px 0px 30px currentColor;
}
}
</style>
</head>
<body>
<div class="contenedor-demo">
<h1>Diseño de Tarjeta Flotante</h1>
<p>Experimenta la elegancia del diseño de tarjeta flotante con animaciones suaves e interacciones modernas</p>
<button class="btn-demo" onclick="mostrarBannerCookies()">Mostrar Banner de Cookies</button>
</div>
<!-- Banner de Cookies Flotante -->
<div id="bannerCookiesFlotante" class="banner-cookies-flotante">
<div class="encabezado-banner">
<div class="icono-banner">🍪</div>
<div class="titulo-banner">Preferencias de Cookies</div>
<div class="subtitulo-banner">Valoramos tu privacidad</div>
</div>
<div class="contenido-banner">
<div class="descripcion-cookies">
Utilizamos cookies para mejorar tu experiencia de navegación y proporcionar contenido personalizado.
<a href="#" class="enlace-cookies">Política de Privacidad</a> |
<a href="#" class="enlace-cookies">Política de Cookies</a>
</div>
<div class="acciones-cookies">
<button class="btn-tarjeta btn-aceptar" onclick="aceptarCookies()">Aceptar Todo</button>
<button class="btn-tarjeta btn-rechazar" onclick="rechazarCookies()">Rechazar</button>
<button class="btn-tarjeta btn-configuracion" onclick="abrirConfiguracion()">Personalizar</button>
</div>
</div>
</div>
<!-- Modal de Configuración -->
<div id="modalConfiguracionCookies" class="modal-configuracion-cookies">
<div class="tarjeta-configuracion">
<div class="encabezado-configuracion">
<h3 class="titulo-configuracion">Configuración de Cookies</h3>
<button class="btn-cerrar" onclick="cerrarConfiguracion()">×</button>
</div>
<div class="cuerpo-configuracion">
<div class="categoria-cookies">
<div class="encabezado-categoria">
<span class="titulo-categoria">Cookies Esenciales</span>
<div class="interruptor-tarjeta activo" data-categoria="esenciales"></div>
</div>
<div class="descripcion-categoria">
Estas cookies son necesarias para que el sitio web funcione y no se pueden desactivar. Generalmente solo se establecen en respuesta a acciones realizadas por ti.
</div>
</div>
<div class="categoria-cookies">
<div class="encabezado-categoria">
<span class="titulo-categoria">Cookies de Análisis</span>
<div class="interruptor-tarjeta" data-categoria="analiticas"></div>
</div>
<div class="descripcion-categoria">
Estas cookies nos ayudan a entender cómo los visitantes interactúan con nuestro sitio web recopilando y reportando información de forma anónima.
</div>
</div>
<div class="categoria-cookies">
<div class="encabezado-categoria">
<span class="titulo-categoria">Cookies de Marketing</span>
<div class="interruptor-tarjeta" data-categoria="marketing"></div>
</div>
<div class="descripcion-categoria">
Estas cookies se utilizan para entregar anuncios más relevantes para ti y tus intereses basados en tu comportamiento de navegación.
</div>
</div>
<div class="categoria-cookies">
<div class="encabezado-categoria">
<span class="titulo-categoria">Cookies Funcionales</span>
<div class="interruptor-tarjeta" data-categoria="funcionales"></div>
</div>
<div class="descripcion-categoria">
Estas cookies habilitan funcionalidad mejorada y personalización, como recordar tus preferencias y configuraciones.
</div>
</div>
</div>
<div class="acciones-configuracion">
<button class="btn-tarjeta btn-rechazar" onclick="guardarConfiguracion(false)">Guardar Preferencias</button>
<button class="btn-tarjeta btn-aceptar" onclick="guardarConfiguracion(true)">Aceptar Todo</button>
</div>
</div>
</div>
<script>
class BannerCookiesTarjetaFlotante {
constructor(opciones = {}) {
this.opciones = {
mostrarAuto: true,
retrasoMostrar: 1500,
claveAlmacenamiento: 'consentimiento_cookies_tarjeta_flotante',
diasExpiracion: 365,
habilitarAnimaciones: true,
posicion: 'abajo-derecha',
alAceptar: null,
alRechazar: null,
alGuardarConfiguracion: null,
...opciones
};
this.banner = document.getElementById('bannerCookiesFlotante');
this.modal = document.getElementById('modalConfiguracionCookies');
this.consentimiento = this.obtenerConsentimientoAlmacenado();
this.esVisible = false;
this.inicializar();
}
inicializar() {
if (this.opciones.mostrarAuto && !this.consentimiento) {
setTimeout(() => this.mostrar(), this.opciones.retrasoMostrar);
}
this.configurarEventListeners();
this.cargarConfiguracion();
this.configurarPosicion();
}
configurarEventListeners() {
// Interruptores de alternancia
document.querySelectorAll('.interruptor-tarjeta').forEach(interruptor => {
interruptor.addEventListener('click', () => {
if (interruptor.dataset.categoria !== 'esenciales') {
interruptor.classList.toggle('activo');
this.animarInterruptor(interruptor);
}
});
});
// Clic en el fondo del modal
this.modal.addEventListener('click', (e) => {
if (e.target === this.modal) {
this.cerrarConfiguracion();
}
});
// Navegación por teclado
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
this.cerrarConfiguracion();
}
});
// Efectos hover de botones
document.querySelectorAll('.btn-tarjeta').forEach(btn => {
btn.addEventListener('mouseenter', () => {
this.crearOnda(btn);
});
});
// Efectos hover del banner
this.banner.addEventListener('mouseenter', () => {
if (this.esVisible) {
this.mejorarEfectoHover();
}
});
this.banner.addEventListener('mouseleave', () => {
if (this.esVisible) {
this.resetearEfectoHover();
}
});
}
configurarPosicion() {
const posiciones = {
'abajo-derecha': { bottom: '2rem', right: '2rem', left: 'auto', top: 'auto' },
'abajo-izquierda': { bottom: '2rem', left: '2rem', right: 'auto', top: 'auto' },
'arriba-derecha': { top: '2rem', right: '2rem', left: 'auto', bottom: 'auto' },
'arriba-izquierda': { top: '2rem', left: '2rem', right: 'auto', bottom: 'auto' }
};
const pos = posiciones[this.opciones.posicion] || posiciones['abajo-derecha'];
Object.assign(this.banner.style, pos);
}
animarInterruptor(interruptor) {
if (!this.opciones.habilitarAnimaciones) return;
interruptor.style.transform = 'scale(0.9)';
setTimeout(() => {
interruptor.style.transform = 'scale(1)';
}, 150);
// Agregar efecto de pulso
interruptor.style.boxShadow = '0 0 0 8px rgba(16, 185, 129, 0.2)';
setTimeout(() => {
interruptor.style.boxShadow = '';
}, 300);
}
crearOnda(boton) {
if (!this.opciones.habilitarAnimaciones) return;
const onda = document.createElement('span');
const rect = boton.getBoundingClientRect();
const tamaño = Math.max(rect.width, rect.height);
onda.style.width = onda.style.height = tamaño + 'px';
onda.style.left = '50%';
onda.style.top = '50%';
onda.style.transform = 'translate(-50%, -50%) scale(0)';
onda.style.position = 'absolute';
onda.style.borderRadius = '50%';
onda.style.background = 'rgba(255, 255, 255, 0.3)';
onda.style.pointerEvents = 'none';
onda.style.animation = 'onda 0.6s ease-out';
boton.style.position = 'relative';
boton.style.overflow = 'hidden';
boton.appendChild(onda);
setTimeout(() => {
onda.remove();
}, 600);
}
mejorarEfectoHover() {
if (!this.opciones.habilitarAnimaciones) return;
const icono = this.banner.querySelector('.icono-banner');
if (icono) {
icono.style.transform = 'scale(1.1) rotate(5deg)';
}
}
resetearEfectoHover() {
if (!this.opciones.habilitarAnimaciones) return;
const icono = this.banner.querySelector('.icono-banner');
if (icono) {
icono.style.transform = '';
}
}
mostrar() {
this.banner.classList.add('mostrar');
this.esVisible = true;
if (this.opciones.habilitarAnimaciones) {
this.animarEntrada();
}
}
ocultar() {
this.banner.classList.remove('mostrar');
this.esVisible = false;
}
animarEntrada() {
const elementos = [
this.banner.querySelector('.icono-banner'),
this.banner.querySelector('.titulo-banner'),
this.banner.querySelector('.subtitulo-banner'),
this.banner.querySelector('.descripcion-cookies'),
this.banner.querySelector('.acciones-cookies')
];
elementos.forEach((el, index) => {
if (el) {
el.style.opacity = '0';
el.style.transform = 'translateY(20px)';
setTimeout(() => {
el.style.transition = 'all 0.6s cubic-bezier(0.4, 0, 0.2, 1)';
el.style.opacity = '1';
el.style.transform = 'translateY(0)';
}, index * 100);
}
});
}
aceptar() {
const consentimiento = {
esenciales: true,
analiticas: true,
marketing: true,
funcionales: true,
marcaTiempo: Date.now()
};
this.guardarConsentimiento(consentimiento);
this.mostrarAnimacionExito();
setTimeout(() => {
this.ocultar();
}, 1500);
if (this.opciones.alAceptar) {
this.opciones.alAceptar(consentimiento);
}
}
rechazar() {
const consentimiento = {
esenciales: true,
analiticas: false,
marketing: false,
funcionales: false,
marcaTiempo: Date.now()
};
this.guardarConsentimiento(consentimiento);
this.ocultar();
if (this.opciones.alRechazar) {
this.opciones.alRechazar(consentimiento);
}
}
mostrarAnimacionExito() {
if (!this.opciones.habilitarAnimaciones) return;
const btnAceptar = this.banner.querySelector('.btn-aceptar');
if (btnAceptar) {
btnAceptar.innerHTML = `
<svg class="marca-exito" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52">
<circle class="circulo-marca-exito" cx="26" cy="26" r="25" fill="none"/>
<path class="check-marca-exito" fill="none" d="m14.1 27.2l7.1 7.2 16.7-16.8"/>
</svg>
Aceptado
`;
btnAceptar.style.background = 'var(--color-exito)';
}
}
abrirConfiguracion() {
this.modal.classList.add('mostrar');
document.body.style.overflow = 'hidden';
if (this.opciones.habilitarAnimaciones) {
this.animarEntradaModal();
}
}
cerrarConfiguracion() {
this.modal.classList.remove('mostrar');
document.body.style.overflow = '';
}
animarEntradaModal() {
const categorias = this.modal.querySelectorAll('.categoria-cookies');
categorias.forEach((categoria, index) => {
categoria.style.opacity = '0';
categoria.style.transform = 'translateX(-20px)';
setTimeout(() => {
categoria.style.transition = 'all 0.4s cubic-bezier(0.4, 0, 0.2, 1)';
categoria.style.opacity = '1';
categoria.style.transform = 'translateX(0)';
}, index * 100);
});
}
guardarConfiguracion(aceptarTodo = false) {
const interruptores = document.querySelectorAll('.interruptor-tarjeta');
const consentimiento = { marcaTiempo: Date.now() };
interruptores.forEach(interruptor => {
const categoria = interruptor.dataset.categoria;
if (aceptarTodo) {
consentimiento[categoria] = true;
interruptor.classList.add('activo');
} else {
consentimiento[categoria] = interruptor.classList.contains('activo');
}
});
this.guardarConsentimiento(consentimiento);
this.cerrarConfiguracion();
this.ocultar();
if (this.opciones.alGuardarConfiguracion) {
this.opciones.alGuardarConfiguracion(consentimiento);
}
}
cargarConfiguracion() {
if (this.consentimiento) {
document.querySelectorAll('.interruptor-tarjeta').forEach(interruptor => {
const categoria = interruptor.dataset.categoria;
if (this.consentimiento[categoria]) {
interruptor.classList.add('activo');
} else {
interruptor.classList.remove('activo');
}
});
}
}
guardarConsentimiento(consentimiento) {
const fechaExpiracion = new Date();
fechaExpiracion.setDate(fechaExpiracion.getDate() + this.opciones.diasExpiracion);
const datosConsentimiento = {
...consentimiento,
expiracion: fechaExpiracion.getTime()
};
localStorage.setItem(this.opciones.claveAlmacenamiento, JSON.stringify(datosConsentimiento));
this.consentimiento = consentimiento;
}
obtenerConsentimientoAlmacenado() {
try {
const almacenado = localStorage.getItem(this.opciones.claveAlmacenamiento);
if (almacenado) {
const datos = JSON.parse(almacenado);
if (datos.expiracion && Date.now() < datos.expiracion) {
return datos;
} else {
localStorage.removeItem(this.opciones.claveAlmacenamiento);
}
}
} catch (e) {
console.error('Error al leer el consentimiento de cookies:', e);
}
return null;
}
resetear() {
localStorage.removeItem(this.opciones.claveAlmacenamiento);
this.consentimiento = null;
this.mostrar();
}
obtenerConsentimiento() {
return this.consentimiento;
}
establecerPosicion(posicion) {
this.opciones.posicion = posicion;
this.configurarPosicion();
}
habilitarAnimaciones(habilitado) {
this.opciones.habilitarAnimaciones = habilitado;
}
actualizarTema(tema) {
const temas = {
claro: {
'--fondo': '#ffffff',
'--superficie': '#f8fafc',
'--texto-primario': '#1f2937',
'--texto-secundario': '#6b7280'
},
oscuro: {
'--fondo': '#1f2937',
'--superficie': '#374151',
'--texto-primario': '#f9fafb',
'--texto-secundario': '#d1d5db'
}
};
if (temas[tema]) {
Object.entries(temas[tema]).forEach(([propiedad, valor]) => {
document.documentElement.style.setProperty(propiedad, valor);
});
}
}
}
// Agregar animación de onda CSS
const estilo = document.createElement('style');
estilo.textContent = `
@keyframes onda {
to {
transform: translate(-50%, -50%) scale(2);
opacity: 0;
}
}
`;
document.head.appendChild(estilo);
// Inicializar el banner
const bannerCookies = new BannerCookiesTarjetaFlotante({
posicion: 'abajo-derecha',
habilitarAnimaciones: true,
alAceptar: (consentimiento) => {
console.log('Cookies aceptadas:', consentimiento);
// Inicializar scripts de análisis, marketing, etc.
},
alRechazar: (consentimiento) => {
console.log('Cookies rechazadas:', consentimiento);
// Cargar solo scripts esenciales
},
alGuardarConfiguracion: (consentimiento) => {
console.log('Configuración guardada:', consentimiento);
// Cargar scripts basados en las preferencias del usuario
}
});
// Funciones globales para la demo
function mostrarBannerCookies() {
bannerCookies.resetear();
}
function aceptarCookies() {
bannerCookies.aceptar();
}
function rechazarCookies() {
bannerCookies.rechazar();
}
function abrirConfiguracion() {
bannerCookies.abrirConfiguracion();
}
function cerrarConfiguracion() {
bannerCookies.cerrarConfiguracion();
}
function guardarConfiguracion(aceptarTodo) {
bannerCookies.guardarConfiguracion(aceptarTodo);
}
</script>
</body>
</html>