Categoría · Interactivo Nivel de Dificultad · Intermedio Publicado el · 15 de enero de 2024

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

#cookie-banner #gdpr #privacy #consent #responsive #modern #animated

Diseño Responsivo

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.

400px

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()">&times;</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 cookies
  • ocultar() - Ocultar el banner de cookies
  • aceptar() - Aceptar todas las cookies y ocultar banner
  • rechazar() - Rechazar cookies opcionales y ocultar banner
  • resetear() - Limpiar consentimiento almacenado y mostrar banner nuevamente

Gestión de Configuración

  • abrirConfiguracion() - Abrir el modal de configuración
  • cerrarConfiguracion() - Cerrar el modal de configuración
  • guardarConfiguracion(aceptarTodo) - Guardar configuración actual
  • cargarConfiguracion() - Cargar y aplicar configuración almacenada

Gestión de Datos

  • obtenerConsentimiento() - Obtener objeto de consentimiento actual
  • guardarConsentimiento(consentimiento) - Guardar consentimiento en almacenamiento
  • obtenerConsentimientoAlmacenado() - Recuperar consentimiento del almacenamiento

Personalización

  • establecerPosicion(posicion) - Cambiar posición del banner
  • habilitarAnimaciones(habilitado) - Habilitar/deshabilitar animaciones
  • actualizarTema(tema) - Cambiar entre temas claro/oscuro
  • crearOnda(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()">&times;</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>

              
1124líneas
38014caracteres
HTMLIdioma

Fragmentos de Código Relacionados

Explora packs de plantillas

¿Necesitas bloques más grandes? Descubre landings y colecciones de componentes.

Abrir la biblioteca de plantillas →