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
1125
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-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;
}.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-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-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);
}@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;
}
}.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;
}
}.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>
<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>
<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() {
document.querySelectorAll('.interruptor-tarjeta').forEach(interruptor => {
interruptor.addEventListener('click', () => {
if (interruptor.dataset.categoria !== 'esenciales') {
interruptor.classList.toggle('activo');
this.animarInterruptor(interruptor);
}
});
});
this.modal.addEventListener('click', (e) => {
if (e.target === this.modal) {
this.cerrarConfiguracion();
}
});
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
this.cerrarConfiguracion();
}
});
document.querySelectorAll('.btn-tarjeta').forEach(btn => {
btn.addEventListener('mouseenter', () => {
this.crearOnda(btn);
});
});
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);
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);
});
}
}
}
const estilo = document.createElement('style');
estilo.textContent = `
@keyframes onda {
to {
transform: translate(-50%, -50%) scale(2);
opacity: 0;
}
}
`;
document.head.appendChild(estilo);
const bannerCookies = new BannerCookiesTarjetaFlotante({
posicion: 'abajo-derecha',
habilitarAnimaciones: true,
alAceptar: (consentimiento) => {
console.log('Cookies aceptadas:', consentimiento);
},
alRechazar: (consentimiento) => {
console.log('Cookies rechazadas:', consentimiento);
},
alGuardarConfiguracion: (consentimiento) => {
console.log('Configuración guardada:', consentimiento);
}
});
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
const bannerCookies = new BannerCookiesTarjetaFlotante();
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);
if (consentimiento.analiticas) {
cargarGoogleAnalytics();
}
if (consentimiento.marketing) {
cargarPixelsMarketing();
}
},
alRechazar: (consentimiento) => {
console.log('Usuario rechazó cookies:', consentimiento);
},
alGuardarConfiguracion: (consentimiento) => {
console.log('Usuario guardó configuración personalizada:', consentimiento);
}
});
Configuración Avanzada
const bannerAvanzado = new BannerCookiesTarjetaFlotante({
mostrarAuto: false, // Control manual
retrasoMostrar: 0,
claveAlmacenamiento: 'consentimiento_avanzado',
diasExpiracion: 90,
habilitarAnimaciones: true,
posicion: 'arriba-derecha',
alAceptar: (consentimiento) => {
inicializarSeguimientoAvanzado(consentimiento);
},
alRechazar: (consentimiento) => {
inicializarSoloEsencial();
},
alGuardarConfiguracion: (consentimiento) => {
cargarScriptsBasadosEnConsentimiento(consentimiento);
}
});
function cambiarPosicion(posicion) {
bannerAvanzado.establecerPosicion(posicion);
}
function alternarAnimaciones(habilitado) {
bannerAvanzado.habilitarAnimaciones(habilitado);
}
function cambiarTema(tema) {
bannerAvanzado.actualizarTema(tema);
}
function mostrarBannerConsentimiento() {
bannerAvanzado.mostrar();
}
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
1095
líneas
JavaScript
30
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-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;
}.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-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-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);
}@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;
}
}.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;
}
}.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>
<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>
<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() {
document.querySelectorAll('.interruptor-tarjeta').forEach(interruptor => {
interruptor.addEventListener('click', () => {
if (interruptor.dataset.categoria !== 'esenciales') {
interruptor.classList.toggle('activo');
this.animarInterruptor(interruptor);
}
});
});
this.modal.addEventListener('click', (e) => {
if (e.target === this.modal) {
this.cerrarConfiguracion();
}
});
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
this.cerrarConfiguracion();
}
});
document.querySelectorAll('.btn-tarjeta').forEach(btn => {
btn.addEventListener('mouseenter', () => {
this.crearOnda(btn);
});
});
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);
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);
});
}
}
}
const estilo = document.createElement('style');
estilo.textContent = `
@keyframes onda {
to {
transform: translate(-50%, -50%) scale(2);
opacity: 0;
}
}
`;
document.head.appendChild(estilo);
const bannerCookies = new BannerCookiesTarjetaFlotante({
posicion: 'abajo-derecha',
habilitarAnimaciones: true,
alAceptar: (consentimiento) => {
console.log('Cookies aceptadas:', consentimiento);
},
alRechazar: (consentimiento) => {
console.log('Cookies rechazadas:', consentimiento);
},
alGuardarConfiguracion: (consentimiento) => {
console.log('Configuración guardada:', consentimiento);
}
});
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>