Floating Card Cookie Consent Banner
An elegant floating card-style cookie consent banner with smooth animations, hover effects, and modern card design patterns
Responsive Design
Yes
Dark Mode Support
No
lines
1156
Browser Compatibility
No
Live Preview
Interact with the component without leaving the page.
Floating Card Cookie Consent Banner
A beautifully designed floating card-style cookie consent banner that appears with smooth animations and elegant hover effects. Features a modern card design with subtle shadows, rounded corners, and interactive elements that enhance user engagement.
Features
- Floating Card Design: Elegant card-style layout with subtle shadows and rounded corners
- Smooth Animations: Fluid entrance animations and micro-interactions
- Hover Effects: Interactive hover states with scale and shadow transitions
- Modern Typography: Clean, readable fonts with proper hierarchy
- GDPR Compliant: Complete consent management with granular controls
- Accessibility First: Full keyboard navigation and screen reader support
- Responsive Design: Adapts beautifully to all screen sizes and orientations
- Customizable Styling: Easy theme customization with CSS variables
- Performance Optimized: Lightweight and fast-loading implementation
Preview
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Floating Card Cookie Banner</title>
<style>
:root {
--primary-color: #3b82f6;
--primary-hover: #2563eb;
--secondary-color: #6b7280;
--success-color: #10b981;
--success-hover: #059669;
--danger-color: #ef4444;
--danger-hover: #dc2626;
--background: #ffffff;
--surface: #f8fafc;
--text-primary: #1f2937;
--text-secondary: #6b7280;
--text-muted: #9ca3af;
--border-color: #e5e7eb;
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
--border-radius: 12px;
--border-radius-lg: 16px;
--transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
--transition-fast: 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(--text-primary);
line-height: 1.6;
padding: 2rem;
}
.demo-container {
max-width: 1200px;
margin: 0 auto;
text-align: center;
color: white;
}
.demo-container 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;
}
.demo-container p {
font-size: 1.2rem;
opacity: 0.9;
margin-bottom: 2rem;
}
.demo-btn {
padding: 1rem 2rem;
border: none;
border-radius: var(--border-radius);
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(--transition);
border: 1px solid rgba(255, 255, 255, 0.3);
}
.demo-btn:hover {
background: rgba(255, 255, 255, 0.3);
transform: translateY(-2px);
box-shadow: var(--shadow-lg);
}
/* Floating Card Cookie Banner */
.floating-cookie-banner {
position: fixed;
bottom: 2rem;
right: 2rem;
width: 420px;
max-width: calc(100vw - 4rem);
background: var(--background);
border-radius: var(--border-radius-lg);
box-shadow: var(--shadow-xl);
border: 1px solid var(--border-color);
overflow: hidden;
transform: translateY(120%) scale(0.8);
opacity: 0;
transition: var(--transition);
z-index: 10000;
backdrop-filter: blur(20px);
}
.floating-cookie-banner.show {
transform: translateY(0) scale(1);
opacity: 1;
}
.floating-cookie-banner:hover {
transform: translateY(-4px) scale(1.02);
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
}
.banner-header {
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-hover) 100%);
padding: 1.5rem;
color: white;
position: relative;
overflow: hidden;
}
.banner-header::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: shimmer 3s infinite;
}
@keyframes shimmer {
0% { left: -100%; }
100% { left: 100%; }
}
.banner-icon {
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: float 3s ease-in-out infinite;
}
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-5px); }
}
.banner-title {
font-size: 1.25rem;
font-weight: 700;
margin-bottom: 0.5rem;
position: relative;
z-index: 1;
}
.banner-subtitle {
font-size: 0.9rem;
opacity: 0.9;
position: relative;
z-index: 1;
}
.banner-content {
padding: 1.5rem;
}
.cookie-description {
color: var(--text-secondary);
font-size: 0.95rem;
line-height: 1.6;
margin-bottom: 1.5rem;
}
.cookie-link {
color: var(--primary-color);
text-decoration: none;
font-weight: 600;
transition: var(--transition-fast);
position: relative;
}
.cookie-link::after {
content: '';
position: absolute;
bottom: -2px;
left: 0;
width: 0;
height: 2px;
background: var(--primary-color);
transition: width 0.3s ease;
}
.cookie-link:hover {
color: var(--primary-hover);
}
.cookie-link:hover::after {
width: 100%;
}
.cookie-actions {
display: flex;
gap: 0.75rem;
margin-top: 1.5rem;
}
/* Floating Card Buttons */
.card-btn {
flex: 1;
padding: 0.75rem 1rem;
border: none;
border-radius: var(--border-radius);
font-family: inherit;
font-size: 0.9rem;
font-weight: 600;
cursor: pointer;
transition: var(--transition);
position: relative;
overflow: hidden;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.card-btn::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;
}
.card-btn:hover::before {
width: 300px;
height: 300px;
}
.btn-accept {
background: var(--success-color);
color: white;
box-shadow: var(--shadow-md);
}
.btn-accept:hover {
background: var(--success-hover);
transform: translateY(-2px);
box-shadow: var(--shadow-lg);
}
.btn-decline {
background: var(--danger-color);
color: white;
box-shadow: var(--shadow-md);
}
.btn-decline:hover {
background: var(--danger-hover);
transform: translateY(-2px);
box-shadow: var(--shadow-lg);
}
.btn-settings {
background: var(--surface);
color: var(--text-primary);
border: 1px solid var(--border-color);
box-shadow: var(--shadow-sm);
}
.btn-settings:hover {
background: var(--border-color);
transform: translateY(-2px);
box-shadow: var(--shadow-md);
}
.card-btn:active {
transform: translateY(0);
}
/* Settings Modal */
.cookie-settings-modal {
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(--transition);
}
.cookie-settings-modal.show {
opacity: 1;
visibility: visible;
}
.settings-card {
background: var(--background);
border-radius: var(--border-radius-lg);
box-shadow: var(--shadow-xl);
border: 1px solid var(--border-color);
width: 90%;
max-width: 600px;
max-height: 80vh;
overflow: hidden;
transform: scale(0.9) translateY(20px);
transition: var(--transition);
}
.cookie-settings-modal.show .settings-card {
transform: scale(1) translateY(0);
}
.settings-header {
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-hover) 100%);
padding: 2rem;
color: white;
display: flex;
justify-content: space-between;
align-items: center;
}
.settings-title {
font-size: 1.5rem;
font-weight: 700;
}
.close-btn {
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(--transition-fast);
display: flex;
align-items: center;
justify-content: center;
backdrop-filter: blur(10px);
}
.close-btn:hover {
background: rgba(255, 255, 255, 0.3);
transform: scale(1.1) rotate(90deg);
}
.settings-body {
padding: 2rem;
max-height: 60vh;
overflow-y: auto;
}
.cookie-category {
margin-bottom: 2rem;
padding: 1.5rem;
background: var(--surface);
border: 1px solid var(--border-color);
border-radius: var(--border-radius);
transition: var(--transition-fast);
}
.cookie-category:hover {
box-shadow: var(--shadow-md);
transform: translateY(-1px);
}
.category-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
}
.category-title {
font-weight: 700;
font-size: 1.1rem;
color: var(--text-primary);
}
.category-description {
font-size: 0.9rem;
color: var(--text-secondary);
line-height: 1.6;
}
/* Card Toggle Switch */
.card-toggle {
position: relative;
width: 56px;
height: 28px;
background: var(--border-color);
border-radius: 14px;
cursor: pointer;
transition: var(--transition);
border: 2px solid transparent;
}
.card-toggle.active {
background: var(--success-color);
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);
}
.card-toggle::before {
content: '';
position: absolute;
top: 2px;
left: 2px;
width: 20px;
height: 20px;
background: white;
border-radius: 50%;
transition: var(--transition);
box-shadow: var(--shadow-sm);
}
.card-toggle.active::before {
transform: translateX(28px);
box-shadow: var(--shadow-md);
}
.card-toggle:hover {
transform: scale(1.05);
}
.settings-actions {
display: flex;
gap: 1rem;
justify-content: flex-end;
padding: 1.5rem 2rem;
background: var(--surface);
border-top: 1px solid var(--border-color);
}
/* Responsive Design */
@media (max-width: 768px) {
.floating-cookie-banner {
bottom: 1rem;
right: 1rem;
left: 1rem;
width: auto;
max-width: none;
}
.floating-cookie-banner:hover {
transform: translateY(-2px) scale(1.01);
}
.cookie-actions {
flex-direction: column;
}
.card-btn {
flex: none;
}
.settings-card {
margin: 1rem;
width: calc(100% - 2rem);
}
.settings-header {
padding: 1.5rem;
}
.settings-body {
padding: 1.5rem;
}
.settings-actions {
padding: 1rem 1.5rem;
flex-direction: column;
}
}
@media (max-width: 480px) {
body {
padding: 1rem;
}
.demo-container h1 {
font-size: 2rem;
}
.floating-cookie-banner {
bottom: 0.5rem;
right: 0.5rem;
left: 0.5rem;
}
.banner-header {
padding: 1rem;
}
.banner-content {
padding: 1rem;
}
}
/* Loading Animation */
.loading-dots {
display: inline-flex;
gap: 4px;
}
.loading-dots span {
width: 6px;
height: 6px;
background: currentColor;
border-radius: 50%;
animation: loading 1.4s infinite ease-in-out;
}
.loading-dots span:nth-child(1) { animation-delay: -0.32s; }
.loading-dots span:nth-child(2) { animation-delay: -0.16s; }
@keyframes loading {
0%, 80%, 100% {
transform: scale(0.8);
opacity: 0.5;
}
40% {
transform: scale(1);
opacity: 1;
}
}
/* Success Animation */
.success-checkmark {
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: fill 0.4s ease-in-out 0.4s forwards, scale 0.3s ease-in-out 0.9s both;
}
.success-checkmark-circle {
stroke-dasharray: 166;
stroke-dashoffset: 166;
stroke-width: 2;
stroke-miterlimit: 10;
stroke: currentColor;
fill: none;
animation: stroke 0.6s cubic-bezier(0.65, 0, 0.45, 1) forwards;
}
.success-checkmark-check {
transform-origin: 50% 50%;
stroke-dasharray: 48;
stroke-dashoffset: 48;
animation: stroke 0.3s cubic-bezier(0.65, 0, 0.45, 1) 0.8s forwards;
}
@keyframes stroke {
100% {
stroke-dashoffset: 0;
}
}
@keyframes scale {
0%, 100% {
transform: none;
}
50% {
transform: scale3d(1.1, 1.1, 1);
}
}
@keyframes fill {
100% {
box-shadow: inset 0px 0px 0px 30px currentColor;
}
}
</style>
</head>
<body>
<div class="demo-container">
<h1>Floating Card Design</h1>
<p>Experience the elegance of floating card design with smooth animations and modern interactions</p>
<button class="demo-btn" onclick="showCookieBanner()">Show Cookie Banner</button>
</div>
<!-- Floating Cookie Banner -->
<div id="floatingCookieBanner" class="floating-cookie-banner">
<div class="banner-header">
<div class="banner-icon">🍪</div>
<div class="banner-title">Cookie Preferences</div>
<div class="banner-subtitle">We value your privacy</div>
</div>
<div class="banner-content">
<div class="cookie-description">
We use cookies to enhance your browsing experience and provide personalized content.
<a href="#" class="cookie-link">Privacy Policy</a> |
<a href="#" class="cookie-link">Cookie Policy</a>
</div>
<div class="cookie-actions">
<button class="card-btn btn-accept" onclick="acceptCookies()">Accept All</button>
<button class="card-btn btn-decline" onclick="declineCookies()">Decline</button>
<button class="card-btn btn-settings" onclick="openSettings()">Customize</button>
</div>
</div>
</div>
<!-- Settings Modal -->
<div id="cookieSettingsModal" class="cookie-settings-modal">
<div class="settings-card">
<div class="settings-header">
<h3 class="settings-title">Cookie Settings</h3>
<button class="close-btn" onclick="closeSettings()">×</button>
</div>
<div class="settings-body">
<div class="cookie-category">
<div class="category-header">
<span class="category-title">Essential Cookies</span>
<div class="card-toggle active" data-category="essential"></div>
</div>
<div class="category-description">
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you.
</div>
</div>
<div class="cookie-category">
<div class="category-header">
<span class="category-title">Analytics Cookies</span>
<div class="card-toggle" data-category="analytics"></div>
</div>
<div class="category-description">
These cookies help us understand how visitors interact with our website by collecting and reporting information anonymously.
</div>
</div>
<div class="cookie-category">
<div class="category-header">
<span class="category-title">Marketing Cookies</span>
<div class="card-toggle" data-category="marketing"></div>
</div>
<div class="category-description">
These cookies are used to deliver advertisements more relevant to you and your interests based on your browsing behavior.
</div>
</div>
<div class="cookie-category">
<div class="category-header">
<span class="category-title">Functional Cookies</span>
<div class="card-toggle" data-category="functional"></div>
</div>
<div class="category-description">
These cookies enable enhanced functionality and personalization, such as remembering your preferences and settings.
</div>
</div>
</div>
<div class="settings-actions">
<button class="card-btn btn-decline" onclick="saveSettings(false)">Save Preferences</button>
<button class="card-btn btn-accept" onclick="saveSettings(true)">Accept All</button>
</div>
</div>
</div>
<script>
class FloatingCardCookieBanner {
constructor(options = {}) {
this.options = {
autoShow: true,
showDelay: 1500,
storageKey: 'floating_card_cookie_consent',
expiryDays: 365,
enableAnimations: true,
position: 'bottom-right',
onAccept: null,
onDecline: null,
onSettingsSave: null,
...options
};
this.banner = document.getElementById('floatingCookieBanner');
this.modal = document.getElementById('cookieSettingsModal');
this.consent = this.getStoredConsent();
this.isVisible = false;
this.init();
}
init() {
if (this.options.autoShow && !this.consent) {
setTimeout(() => this.show(), this.options.showDelay);
}
this.setupEventListeners();
this.loadSettings();
this.setupPosition();
}
setupEventListeners() {
// Toggle switches
document.querySelectorAll('.card-toggle').forEach(toggle => {
toggle.addEventListener('click', () => {
if (toggle.dataset.category !== 'essential') {
toggle.classList.toggle('active');
this.animateToggle(toggle);
}
});
});
// Modal backdrop click
this.modal.addEventListener('click', (e) => {
if (e.target === this.modal) {
this.closeSettings();
}
});
// Keyboard navigation
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
this.closeSettings();
}
});
// Button hover effects
document.querySelectorAll('.card-btn').forEach(btn => {
btn.addEventListener('mouseenter', () => {
this.createRipple(btn);
});
});
// Banner hover effects
this.banner.addEventListener('mouseenter', () => {
if (this.isVisible) {
this.enhanceHoverEffect();
}
});
this.banner.addEventListener('mouseleave', () => {
if (this.isVisible) {
this.resetHoverEffect();
}
});
}
setupPosition() {
const positions = {
'bottom-right': { bottom: '2rem', right: '2rem', left: 'auto', top: 'auto' },
'bottom-left': { bottom: '2rem', left: '2rem', right: 'auto', top: 'auto' },
'top-right': { top: '2rem', right: '2rem', left: 'auto', bottom: 'auto' },
'top-left': { top: '2rem', left: '2rem', right: 'auto', bottom: 'auto' }
};
const pos = positions[this.options.position] || positions['bottom-right'];
Object.assign(this.banner.style, pos);
}
animateToggle(toggle) {
if (!this.options.enableAnimations) return;
toggle.style.transform = 'scale(0.9)';
setTimeout(() => {
toggle.style.transform = 'scale(1)';
}, 150);
// Add pulse effect
toggle.style.boxShadow = '0 0 0 8px rgba(16, 185, 129, 0.2)';
setTimeout(() => {
toggle.style.boxShadow = '';
}, 300);
}
createRipple(button) {
if (!this.options.enableAnimations) return;
const ripple = document.createElement('span');
const rect = button.getBoundingClientRect();
const size = Math.max(rect.width, rect.height);
ripple.style.width = ripple.style.height = size + 'px';
ripple.style.left = '50%';
ripple.style.top = '50%';
ripple.style.transform = 'translate(-50%, -50%) scale(0)';
ripple.style.position = 'absolute';
ripple.style.borderRadius = '50%';
ripple.style.background = 'rgba(255, 255, 255, 0.3)';
ripple.style.pointerEvents = 'none';
ripple.style.animation = 'ripple 0.6s ease-out';
button.style.position = 'relative';
button.style.overflow = 'hidden';
button.appendChild(ripple);
setTimeout(() => {
ripple.remove();
}, 600);
}
enhanceHoverEffect() {
if (!this.options.enableAnimations) return;
const icon = this.banner.querySelector('.banner-icon');
if (icon) {
icon.style.transform = 'scale(1.1) rotate(5deg)';
}
}
resetHoverEffect() {
if (!this.options.enableAnimations) return;
const icon = this.banner.querySelector('.banner-icon');
if (icon) {
icon.style.transform = '';
}
}
show() {
this.banner.classList.add('show');
this.isVisible = true;
if (this.options.enableAnimations) {
this.animateEntrance();
}
}
hide() {
this.banner.classList.remove('show');
this.isVisible = false;
}
animateEntrance() {
const elements = [
this.banner.querySelector('.banner-icon'),
this.banner.querySelector('.banner-title'),
this.banner.querySelector('.banner-subtitle'),
this.banner.querySelector('.cookie-description'),
this.banner.querySelector('.cookie-actions')
];
elements.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);
}
});
}
accept() {
const consent = {
essential: true,
analytics: true,
marketing: true,
functional: true,
timestamp: Date.now()
};
this.saveConsent(consent);
this.showSuccessAnimation();
setTimeout(() => {
this.hide();
}, 1500);
if (this.options.onAccept) {
this.options.onAccept(consent);
}
}
decline() {
const consent = {
essential: true,
analytics: false,
marketing: false,
functional: false,
timestamp: Date.now()
};
this.saveConsent(consent);
this.hide();
if (this.options.onDecline) {
this.options.onDecline(consent);
}
}
showSuccessAnimation() {
if (!this.options.enableAnimations) return;
const acceptBtn = this.banner.querySelector('.btn-accept');
if (acceptBtn) {
acceptBtn.innerHTML = `
<svg class="success-checkmark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52">
<circle class="success-checkmark-circle" cx="26" cy="26" r="25" fill="none"/>
<path class="success-checkmark-check" fill="none" d="m14.1 27.2l7.1 7.2 16.7-16.8"/>
</svg>
Accepted
`;
acceptBtn.style.background = 'var(--success-color)';
}
}
openSettings() {
this.modal.classList.add('show');
document.body.style.overflow = 'hidden';
if (this.options.enableAnimations) {
this.animateModalEntrance();
}
}
closeSettings() {
this.modal.classList.remove('show');
document.body.style.overflow = '';
}
animateModalEntrance() {
const categories = this.modal.querySelectorAll('.cookie-category');
categories.forEach((category, index) => {
category.style.opacity = '0';
category.style.transform = 'translateX(-20px)';
setTimeout(() => {
category.style.transition = 'all 0.4s cubic-bezier(0.4, 0, 0.2, 1)';
category.style.opacity = '1';
category.style.transform = 'translateX(0)';
}, index * 100);
});
}
saveSettings(acceptAll = false) {
const toggles = document.querySelectorAll('.card-toggle');
const consent = { timestamp: Date.now() };
toggles.forEach(toggle => {
const category = toggle.dataset.category;
if (acceptAll) {
consent[category] = true;
toggle.classList.add('active');
} else {
consent[category] = toggle.classList.contains('active');
}
});
this.saveConsent(consent);
this.closeSettings();
this.hide();
if (this.options.onSettingsSave) {
this.options.onSettingsSave(consent);
}
}
loadSettings() {
if (this.consent) {
document.querySelectorAll('.card-toggle').forEach(toggle => {
const category = toggle.dataset.category;
if (this.consent[category]) {
toggle.classList.add('active');
} else {
toggle.classList.remove('active');
}
});
}
}
saveConsent(consent) {
const expiryDate = new Date();
expiryDate.setDate(expiryDate.getDate() + this.options.expiryDays);
const consentData = {
...consent,
expiry: expiryDate.getTime()
};
localStorage.setItem(this.options.storageKey, JSON.stringify(consentData));
this.consent = consent;
}
getStoredConsent() {
try {
const stored = localStorage.getItem(this.options.storageKey);
if (stored) {
const data = JSON.parse(stored);
if (data.expiry && Date.now() < data.expiry) {
return data;
} else {
localStorage.removeItem(this.options.storageKey);
}
}
} catch (e) {
console.error('Error reading cookie consent:', e);
}
return null;
}
reset() {
localStorage.removeItem(this.options.storageKey);
this.consent = null;
this.show();
}
getConsent() {
return this.consent;
}
setPosition(position) {
this.options.position = position;
this.setupPosition();
}
enableAnimations(enabled) {
this.options.enableAnimations = enabled;
}
updateTheme(theme) {
const themes = {
light: {
'--background': '#ffffff',
'--surface': '#f8fafc',
'--text-primary': '#1f2937',
'--text-secondary': '#6b7280'
},
dark: {
'--background': '#1f2937',
'--surface': '#374151',
'--text-primary': '#f9fafb',
'--text-secondary': '#d1d5db'
}
};
if (themes[theme]) {
Object.entries(themes[theme]).forEach(([property, value]) => {
document.documentElement.style.setProperty(property, value);
});
}
}
}
// Add ripple animation CSS
const style = document.createElement('style');
style.textContent = `
@keyframes ripple {
to {
transform: translate(-50%, -50%) scale(2);
opacity: 0;
}
}
`;
document.head.appendChild(style);
// Initialize the banner
const cookieBanner = new FloatingCardCookieBanner({
position: 'bottom-right',
enableAnimations: true,
onAccept: (consent) => {
console.log('Cookies accepted:', consent);
// Initialize analytics, marketing scripts, etc.
},
onDecline: (consent) => {
console.log('Cookies declined:', consent);
// Load only essential scripts
},
onSettingsSave: (consent) => {
console.log('Settings saved:', consent);
// Load scripts based on user preferences
}
});
// Global functions for demo
function showCookieBanner() {
cookieBanner.reset();
}
function acceptCookies() {
cookieBanner.accept();
}
function declineCookies() {
cookieBanner.decline();
}
function openSettings() {
cookieBanner.openSettings();
}
function closeSettings() {
cookieBanner.closeSettings();
}
function saveSettings(acceptAll) {
cookieBanner.saveSettings(acceptAll);
}
</script>
</body>
</html>Usage
Basic Implementation
// Initialize with default settings
const cookieBanner = new FloatingCardCookieBanner();
// Initialize with custom options
const cookieBanner = new FloatingCardCookieBanner({
autoShow: true,
showDelay: 2000,
storageKey: 'my_cookie_consent',
expiryDays: 180,
enableAnimations: true,
position: 'bottom-left',
onAccept: (consent) => {
console.log('User accepted cookies:', consent);
// Load analytics scripts
if (consent.analytics) {
loadGoogleAnalytics();
}
// Load marketing scripts
if (consent.marketing) {
loadMarketingPixels();
}
},
onDecline: (consent) => {
console.log('User declined cookies:', consent);
// Load only essential functionality
},
onSettingsSave: (consent) => {
console.log('User saved custom settings:', consent);
// Load scripts based on specific preferences
}
});Advanced Configuration
// Custom styling and behavior
const advancedBanner = new FloatingCardCookieBanner({
autoShow: false, // Manual control
showDelay: 0,
storageKey: 'advanced_consent',
expiryDays: 90,
enableAnimations: true,
position: 'top-right',
// Custom callbacks
onAccept: (consent) => {
// Advanced analytics setup
initializeAdvancedTracking(consent);
},
onDecline: (consent) => {
// Minimal tracking setup
initializeEssentialOnly();
},
onSettingsSave: (consent) => {
// Granular script loading
loadScriptsBasedOnConsent(consent);
}
});
// Position control
function changePosition(position) {
advancedBanner.setPosition(position);
}
// Animation control
function toggleAnimations(enabled) {
advancedBanner.enableAnimations(enabled);
}
// Theme switching
function switchTheme(theme) {
advancedBanner.updateTheme(theme);
}
// Manual control
function showConsentBanner() {
advancedBanner.show();
}
// Check current consent status
function checkConsentStatus() {
const consent = advancedBanner.getConsent();
if (consent) {
console.log('Current consent:', consent);
} else {
console.log('No consent given yet');
}
}API Methods
Core Methods
show()- Display the cookie bannerhide()- Hide the cookie banneraccept()- Accept all cookies and hide bannerdecline()- Decline optional cookies and hide bannerreset()- Clear stored consent and show banner again
Settings Management
openSettings()- Open the settings modalcloseSettings()- Close the settings modalsaveSettings(acceptAll)- Save current settingsloadSettings()- Load and apply stored settings
Data Management
getConsent()- Get current consent objectsaveConsent(consent)- Save consent to storagegetStoredConsent()- Retrieve consent from storage
Customization
setPosition(position)- Change banner positionenableAnimations(enabled)- Enable/disable animationsupdateTheme(theme)- Switch between light/dark themescreateRipple(button)- Create ripple effects on buttons
Customization Options
Visual Customization
- Color Schemes: Modify CSS custom properties for different color themes
- Animation Speed: Adjust transition durations and animation timings
- Card Styling: Customize border radius, shadows, and spacing
- Typography: Change font families, sizes, and weights
Functional Configuration
- Auto Display: Control automatic banner appearance
- Storage Duration: Set cookie consent expiration period
- Delay Settings: Configure show/hide timing
- Callback Functions: Custom handlers for user actions
Accessibility Features
- Keyboard Navigation: Full keyboard support with focus indicators
- Screen Reader Support: Proper ARIA labels and descriptions
- High Contrast: Enhanced visibility for accessibility
- Focus Management: Proper focus trapping in modal
Browser Compatibility
- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+
- Mobile browsers (iOS Safari 12+, Chrome Mobile 60+)
License
MIT License - free to use in personal and commercial projects.
HTML
1124
lines
CSS
1
lines
JavaScript
31
lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Floating Card Cookie Banner</title>
<style>
:root {
--primary-color: #3b82f6;
--primary-hover: #2563eb;
--secondary-color: #6b7280;
--success-color: #10b981;
--success-hover: #059669;
--danger-color: #ef4444;
--danger-hover: #dc2626;
--background: #ffffff;
--surface: #f8fafc;
--text-primary: #1f2937;
--text-secondary: #6b7280;
--text-muted: #9ca3af;
--border-color: #e5e7eb;
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
--border-radius: 12px;
--border-radius-lg: 16px;
--transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
--transition-fast: 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(--text-primary);
line-height: 1.6;
padding: 2rem;
}
.demo-container {
max-width: 1200px;
margin: 0 auto;
text-align: center;
color: white;
}
.demo-container 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;
}
.demo-container p {
font-size: 1.2rem;
opacity: 0.9;
margin-bottom: 2rem;
}
.demo-btn {
padding: 1rem 2rem;
border: none;
border-radius: var(--border-radius);
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(--transition);
border: 1px solid rgba(255, 255, 255, 0.3);
}
.demo-btn:hover {
background: rgba(255, 255, 255, 0.3);
transform: translateY(-2px);
box-shadow: var(--shadow-lg);
}
/* Floating Card Cookie Banner */
.floating-cookie-banner {
position: fixed;
bottom: 2rem;
right: 2rem;
width: 420px;
max-width: calc(100vw - 4rem);
background: var(--background);
border-radius: var(--border-radius-lg);
box-shadow: var(--shadow-xl);
border: 1px solid var(--border-color);
overflow: hidden;
transform: translateY(120%) scale(0.8);
opacity: 0;
transition: var(--transition);
z-index: 10000;
backdrop-filter: blur(20px);
}
.floating-cookie-banner.show {
transform: translateY(0) scale(1);
opacity: 1;
}
.floating-cookie-banner:hover {
transform: translateY(-4px) scale(1.02);
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
}
.banner-header {
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-hover) 100%);
padding: 1.5rem;
color: white;
position: relative;
overflow: hidden;
}
.banner-header::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: shimmer 3s infinite;
}
@keyframes shimmer {
0% { left: -100%; }
100% { left: 100%; }
}
.banner-icon {
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: float 3s ease-in-out infinite;
}
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-5px); }
}
.banner-title {
font-size: 1.25rem;
font-weight: 700;
margin-bottom: 0.5rem;
position: relative;
z-index: 1;
}
.banner-subtitle {
font-size: 0.9rem;
opacity: 0.9;
position: relative;
z-index: 1;
}
.banner-content {
padding: 1.5rem;
}
.cookie-description {
color: var(--text-secondary);
font-size: 0.95rem;
line-height: 1.6;
margin-bottom: 1.5rem;
}
.cookie-link {
color: var(--primary-color);
text-decoration: none;
font-weight: 600;
transition: var(--transition-fast);
position: relative;
}
.cookie-link::after {
content: '';
position: absolute;
bottom: -2px;
left: 0;
width: 0;
height: 2px;
background: var(--primary-color);
transition: width 0.3s ease;
}
.cookie-link:hover {
color: var(--primary-hover);
}
.cookie-link:hover::after {
width: 100%;
}
.cookie-actions {
display: flex;
gap: 0.75rem;
margin-top: 1.5rem;
}
/* Floating Card Buttons */
.card-btn {
flex: 1;
padding: 0.75rem 1rem;
border: none;
border-radius: var(--border-radius);
font-family: inherit;
font-size: 0.9rem;
font-weight: 600;
cursor: pointer;
transition: var(--transition);
position: relative;
overflow: hidden;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.card-btn::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;
}
.card-btn:hover::before {
width: 300px;
height: 300px;
}
.btn-accept {
background: var(--success-color);
color: white;
box-shadow: var(--shadow-md);
}
.btn-accept:hover {
background: var(--success-hover);
transform: translateY(-2px);
box-shadow: var(--shadow-lg);
}
.btn-decline {
background: var(--danger-color);
color: white;
box-shadow: var(--shadow-md);
}
.btn-decline:hover {
background: var(--danger-hover);
transform: translateY(-2px);
box-shadow: var(--shadow-lg);
}
.btn-settings {
background: var(--surface);
color: var(--text-primary);
border: 1px solid var(--border-color);
box-shadow: var(--shadow-sm);
}
.btn-settings:hover {
background: var(--border-color);
transform: translateY(-2px);
box-shadow: var(--shadow-md);
}
.card-btn:active {
transform: translateY(0);
}
/* Settings Modal */
.cookie-settings-modal {
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(--transition);
}
.cookie-settings-modal.show {
opacity: 1;
visibility: visible;
}
.settings-card {
background: var(--background);
border-radius: var(--border-radius-lg);
box-shadow: var(--shadow-xl);
border: 1px solid var(--border-color);
width: 90%;
max-width: 600px;
max-height: 80vh;
overflow: hidden;
transform: scale(0.9) translateY(20px);
transition: var(--transition);
}
.cookie-settings-modal.show .settings-card {
transform: scale(1) translateY(0);
}
.settings-header {
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-hover) 100%);
padding: 2rem;
color: white;
display: flex;
justify-content: space-between;
align-items: center;
}
.settings-title {
font-size: 1.5rem;
font-weight: 700;
}
.close-btn {
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(--transition-fast);
display: flex;
align-items: center;
justify-content: center;
backdrop-filter: blur(10px);
}
.close-btn:hover {
background: rgba(255, 255, 255, 0.3);
transform: scale(1.1) rotate(90deg);
}
.settings-body {
padding: 2rem;
max-height: 60vh;
overflow-y: auto;
}
.cookie-category {
margin-bottom: 2rem;
padding: 1.5rem;
background: var(--surface);
border: 1px solid var(--border-color);
border-radius: var(--border-radius);
transition: var(--transition-fast);
}
.cookie-category:hover {
box-shadow: var(--shadow-md);
transform: translateY(-1px);
}
.category-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
}
.category-title {
font-weight: 700;
font-size: 1.1rem;
color: var(--text-primary);
}
.category-description {
font-size: 0.9rem;
color: var(--text-secondary);
line-height: 1.6;
}
/* Card Toggle Switch */
.card-toggle {
position: relative;
width: 56px;
height: 28px;
background: var(--border-color);
border-radius: 14px;
cursor: pointer;
transition: var(--transition);
border: 2px solid transparent;
}
.card-toggle.active {
background: var(--success-color);
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);
}
.card-toggle::before {
content: '';
position: absolute;
top: 2px;
left: 2px;
width: 20px;
height: 20px;
background: white;
border-radius: 50%;
transition: var(--transition);
box-shadow: var(--shadow-sm);
}
.card-toggle.active::before {
transform: translateX(28px);
box-shadow: var(--shadow-md);
}
.card-toggle:hover {
transform: scale(1.05);
}
.settings-actions {
display: flex;
gap: 1rem;
justify-content: flex-end;
padding: 1.5rem 2rem;
background: var(--surface);
border-top: 1px solid var(--border-color);
}
/* Responsive Design */
@media (max-width: 768px) {
.floating-cookie-banner {
bottom: 1rem;
right: 1rem;
left: 1rem;
width: auto;
max-width: none;
}
.floating-cookie-banner:hover {
transform: translateY(-2px) scale(1.01);
}
.cookie-actions {
flex-direction: column;
}
.card-btn {
flex: none;
}
.settings-card {
margin: 1rem;
width: calc(100% - 2rem);
}
.settings-header {
padding: 1.5rem;
}
.settings-body {
padding: 1.5rem;
}
.settings-actions {
padding: 1rem 1.5rem;
flex-direction: column;
}
}
@media (max-width: 480px) {
body {
padding: 1rem;
}
.demo-container h1 {
font-size: 2rem;
}
.floating-cookie-banner {
bottom: 0.5rem;
right: 0.5rem;
left: 0.5rem;
}
.banner-header {
padding: 1rem;
}
.banner-content {
padding: 1rem;
}
}
/* Loading Animation */
.loading-dots {
display: inline-flex;
gap: 4px;
}
.loading-dots span {
width: 6px;
height: 6px;
background: currentColor;
border-radius: 50%;
animation: loading 1.4s infinite ease-in-out;
}
.loading-dots span:nth-child(1) { animation-delay: -0.32s; }
.loading-dots span:nth-child(2) { animation-delay: -0.16s; }
@keyframes loading {
0%, 80%, 100% {
transform: scale(0.8);
opacity: 0.5;
}
40% {
transform: scale(1);
opacity: 1;
}
}
/* Success Animation */
.success-checkmark {
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: fill 0.4s ease-in-out 0.4s forwards, scale 0.3s ease-in-out 0.9s both;
}
.success-checkmark-circle {
stroke-dasharray: 166;
stroke-dashoffset: 166;
stroke-width: 2;
stroke-miterlimit: 10;
stroke: currentColor;
fill: none;
animation: stroke 0.6s cubic-bezier(0.65, 0, 0.45, 1) forwards;
}
.success-checkmark-check {
transform-origin: 50% 50%;
stroke-dasharray: 48;
stroke-dashoffset: 48;
animation: stroke 0.3s cubic-bezier(0.65, 0, 0.45, 1) 0.8s forwards;
}
@keyframes stroke {
100% {
stroke-dashoffset: 0;
}
}
@keyframes scale {
0%, 100% {
transform: none;
}
50% {
transform: scale3d(1.1, 1.1, 1);
}
}
@keyframes fill {
100% {
box-shadow: inset 0px 0px 0px 30px currentColor;
}
}
</style>
</head>
<body>
<div class="demo-container">
<h1>Floating Card Design</h1>
<p>Experience the elegance of floating card design with smooth animations and modern interactions</p>
<button class="demo-btn" onclick="showCookieBanner()">Show Cookie Banner</button>
</div>
<!-- Floating Cookie Banner -->
<div id="floatingCookieBanner" class="floating-cookie-banner">
<div class="banner-header">
<div class="banner-icon">🍪</div>
<div class="banner-title">Cookie Preferences</div>
<div class="banner-subtitle">We value your privacy</div>
</div>
<div class="banner-content">
<div class="cookie-description">
We use cookies to enhance your browsing experience and provide personalized content.
<a href="#" class="cookie-link">Privacy Policy</a> |
<a href="#" class="cookie-link">Cookie Policy</a>
</div>
<div class="cookie-actions">
<button class="card-btn btn-accept" onclick="acceptCookies()">Accept All</button>
<button class="card-btn btn-decline" onclick="declineCookies()">Decline</button>
<button class="card-btn btn-settings" onclick="openSettings()">Customize</button>
</div>
</div>
</div>
<!-- Settings Modal -->
<div id="cookieSettingsModal" class="cookie-settings-modal">
<div class="settings-card">
<div class="settings-header">
<h3 class="settings-title">Cookie Settings</h3>
<button class="close-btn" onclick="closeSettings()">×</button>
</div>
<div class="settings-body">
<div class="cookie-category">
<div class="category-header">
<span class="category-title">Essential Cookies</span>
<div class="card-toggle active" data-category="essential"></div>
</div>
<div class="category-description">
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you.
</div>
</div>
<div class="cookie-category">
<div class="category-header">
<span class="category-title">Analytics Cookies</span>
<div class="card-toggle" data-category="analytics"></div>
</div>
<div class="category-description">
These cookies help us understand how visitors interact with our website by collecting and reporting information anonymously.
</div>
</div>
<div class="cookie-category">
<div class="category-header">
<span class="category-title">Marketing Cookies</span>
<div class="card-toggle" data-category="marketing"></div>
</div>
<div class="category-description">
These cookies are used to deliver advertisements more relevant to you and your interests based on your browsing behavior.
</div>
</div>
<div class="cookie-category">
<div class="category-header">
<span class="category-title">Functional Cookies</span>
<div class="card-toggle" data-category="functional"></div>
</div>
<div class="category-description">
These cookies enable enhanced functionality and personalization, such as remembering your preferences and settings.
</div>
</div>
</div>
<div class="settings-actions">
<button class="card-btn btn-decline" onclick="saveSettings(false)">Save Preferences</button>
<button class="card-btn btn-accept" onclick="saveSettings(true)">Accept All</button>
</div>
</div>
</div>
<script>
class FloatingCardCookieBanner {
constructor(options = {}) {
this.options = {
autoShow: true,
showDelay: 1500,
storageKey: 'floating_card_cookie_consent',
expiryDays: 365,
enableAnimations: true,
position: 'bottom-right',
onAccept: null,
onDecline: null,
onSettingsSave: null,
...options
};
this.banner = document.getElementById('floatingCookieBanner');
this.modal = document.getElementById('cookieSettingsModal');
this.consent = this.getStoredConsent();
this.isVisible = false;
this.init();
}
init() {
if (this.options.autoShow && !this.consent) {
setTimeout(() => this.show(), this.options.showDelay);
}
this.setupEventListeners();
this.loadSettings();
this.setupPosition();
}
setupEventListeners() {
// Toggle switches
document.querySelectorAll('.card-toggle').forEach(toggle => {
toggle.addEventListener('click', () => {
if (toggle.dataset.category !== 'essential') {
toggle.classList.toggle('active');
this.animateToggle(toggle);
}
});
});
// Modal backdrop click
this.modal.addEventListener('click', (e) => {
if (e.target === this.modal) {
this.closeSettings();
}
});
// Keyboard navigation
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
this.closeSettings();
}
});
// Button hover effects
document.querySelectorAll('.card-btn').forEach(btn => {
btn.addEventListener('mouseenter', () => {
this.createRipple(btn);
});
});
// Banner hover effects
this.banner.addEventListener('mouseenter', () => {
if (this.isVisible) {
this.enhanceHoverEffect();
}
});
this.banner.addEventListener('mouseleave', () => {
if (this.isVisible) {
this.resetHoverEffect();
}
});
}
setupPosition() {
const positions = {
'bottom-right': { bottom: '2rem', right: '2rem', left: 'auto', top: 'auto' },
'bottom-left': { bottom: '2rem', left: '2rem', right: 'auto', top: 'auto' },
'top-right': { top: '2rem', right: '2rem', left: 'auto', bottom: 'auto' },
'top-left': { top: '2rem', left: '2rem', right: 'auto', bottom: 'auto' }
};
const pos = positions[this.options.position] || positions['bottom-right'];
Object.assign(this.banner.style, pos);
}
animateToggle(toggle) {
if (!this.options.enableAnimations) return;
toggle.style.transform = 'scale(0.9)';
setTimeout(() => {
toggle.style.transform = 'scale(1)';
}, 150);
// Add pulse effect
toggle.style.boxShadow = '0 0 0 8px rgba(16, 185, 129, 0.2)';
setTimeout(() => {
toggle.style.boxShadow = '';
}, 300);
}
createRipple(button) {
if (!this.options.enableAnimations) return;
const ripple = document.createElement('span');
const rect = button.getBoundingClientRect();
const size = Math.max(rect.width, rect.height);
ripple.style.width = ripple.style.height = size + 'px';
ripple.style.left = '50%';
ripple.style.top = '50%';
ripple.style.transform = 'translate(-50%, -50%) scale(0)';
ripple.style.position = 'absolute';
ripple.style.borderRadius = '50%';
ripple.style.background = 'rgba(255, 255, 255, 0.3)';
ripple.style.pointerEvents = 'none';
ripple.style.animation = 'ripple 0.6s ease-out';
button.style.position = 'relative';
button.style.overflow = 'hidden';
button.appendChild(ripple);
setTimeout(() => {
ripple.remove();
}, 600);
}
enhanceHoverEffect() {
if (!this.options.enableAnimations) return;
const icon = this.banner.querySelector('.banner-icon');
if (icon) {
icon.style.transform = 'scale(1.1) rotate(5deg)';
}
}
resetHoverEffect() {
if (!this.options.enableAnimations) return;
const icon = this.banner.querySelector('.banner-icon');
if (icon) {
icon.style.transform = '';
}
}
show() {
this.banner.classList.add('show');
this.isVisible = true;
if (this.options.enableAnimations) {
this.animateEntrance();
}
}
hide() {
this.banner.classList.remove('show');
this.isVisible = false;
}
animateEntrance() {
const elements = [
this.banner.querySelector('.banner-icon'),
this.banner.querySelector('.banner-title'),
this.banner.querySelector('.banner-subtitle'),
this.banner.querySelector('.cookie-description'),
this.banner.querySelector('.cookie-actions')
];
elements.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);
}
});
}
accept() {
const consent = {
essential: true,
analytics: true,
marketing: true,
functional: true,
timestamp: Date.now()
};
this.saveConsent(consent);
this.showSuccessAnimation();
setTimeout(() => {
this.hide();
}, 1500);
if (this.options.onAccept) {
this.options.onAccept(consent);
}
}
decline() {
const consent = {
essential: true,
analytics: false,
marketing: false,
functional: false,
timestamp: Date.now()
};
this.saveConsent(consent);
this.hide();
if (this.options.onDecline) {
this.options.onDecline(consent);
}
}
showSuccessAnimation() {
if (!this.options.enableAnimations) return;
const acceptBtn = this.banner.querySelector('.btn-accept');
if (acceptBtn) {
acceptBtn.innerHTML = `
<svg class="success-checkmark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52">
<circle class="success-checkmark-circle" cx="26" cy="26" r="25" fill="none"/>
<path class="success-checkmark-check" fill="none" d="m14.1 27.2l7.1 7.2 16.7-16.8"/>
</svg>
Accepted
`;
acceptBtn.style.background = 'var(--success-color)';
}
}
openSettings() {
this.modal.classList.add('show');
document.body.style.overflow = 'hidden';
if (this.options.enableAnimations) {
this.animateModalEntrance();
}
}
closeSettings() {
this.modal.classList.remove('show');
document.body.style.overflow = '';
}
animateModalEntrance() {
const categories = this.modal.querySelectorAll('.cookie-category');
categories.forEach((category, index) => {
category.style.opacity = '0';
category.style.transform = 'translateX(-20px)';
setTimeout(() => {
category.style.transition = 'all 0.4s cubic-bezier(0.4, 0, 0.2, 1)';
category.style.opacity = '1';
category.style.transform = 'translateX(0)';
}, index * 100);
});
}
saveSettings(acceptAll = false) {
const toggles = document.querySelectorAll('.card-toggle');
const consent = { timestamp: Date.now() };
toggles.forEach(toggle => {
const category = toggle.dataset.category;
if (acceptAll) {
consent[category] = true;
toggle.classList.add('active');
} else {
consent[category] = toggle.classList.contains('active');
}
});
this.saveConsent(consent);
this.closeSettings();
this.hide();
if (this.options.onSettingsSave) {
this.options.onSettingsSave(consent);
}
}
loadSettings() {
if (this.consent) {
document.querySelectorAll('.card-toggle').forEach(toggle => {
const category = toggle.dataset.category;
if (this.consent[category]) {
toggle.classList.add('active');
} else {
toggle.classList.remove('active');
}
});
}
}
saveConsent(consent) {
const expiryDate = new Date();
expiryDate.setDate(expiryDate.getDate() + this.options.expiryDays);
const consentData = {
...consent,
expiry: expiryDate.getTime()
};
localStorage.setItem(this.options.storageKey, JSON.stringify(consentData));
this.consent = consent;
}
getStoredConsent() {
try {
const stored = localStorage.getItem(this.options.storageKey);
if (stored) {
const data = JSON.parse(stored);
if (data.expiry && Date.now() < data.expiry) {
return data;
} else {
localStorage.removeItem(this.options.storageKey);
}
}
} catch (e) {
console.error('Error reading cookie consent:', e);
}
return null;
}
reset() {
localStorage.removeItem(this.options.storageKey);
this.consent = null;
this.show();
}
getConsent() {
return this.consent;
}
setPosition(position) {
this.options.position = position;
this.setupPosition();
}
enableAnimations(enabled) {
this.options.enableAnimations = enabled;
}
updateTheme(theme) {
const themes = {
light: {
'--background': '#ffffff',
'--surface': '#f8fafc',
'--text-primary': '#1f2937',
'--text-secondary': '#6b7280'
},
dark: {
'--background': '#1f2937',
'--surface': '#374151',
'--text-primary': '#f9fafb',
'--text-secondary': '#d1d5db'
}
};
if (themes[theme]) {
Object.entries(themes[theme]).forEach(([property, value]) => {
document.documentElement.style.setProperty(property, value);
});
}
}
}
// Add ripple animation CSS
const style = document.createElement('style');
style.textContent = `
@keyframes ripple {
to {
transform: translate(-50%, -50%) scale(2);
opacity: 0;
}
}
`;
document.head.appendChild(style);
// Initialize the banner
const cookieBanner = new FloatingCardCookieBanner({
position: 'bottom-right',
enableAnimations: true,
onAccept: (consent) => {
console.log('Cookies accepted:', consent);
// Initialize analytics, marketing scripts, etc.
},
onDecline: (consent) => {
console.log('Cookies declined:', consent);
// Load only essential scripts
},
onSettingsSave: (consent) => {
console.log('Settings saved:', consent);
// Load scripts based on user preferences
}
});
// Global functions for demo
function showCookieBanner() {
cookieBanner.reset();
}
function acceptCookies() {
cookieBanner.accept();
}
function declineCookies() {
cookieBanner.decline();
}
function openSettings() {
cookieBanner.openSettings();
}
function closeSettings() {
cookieBanner.closeSettings();
}
function saveSettings(acceptAll) {
cookieBanner.saveSettings(acceptAll);
}
</script>
</body>
</html>