Bottom Slide-in Cookie Consent Banner
A sleek bottom slide-in cookie consent banner with smooth transitions, progressive disclosure, and elegant animation effects
Responsive Design
Yes
Dark Mode Support
No
lines
1124
Browser Compatibility
No
Live Preview
Interact with the component without leaving the page.
Bottom Slide-in Cookie Consent Banner
A beautifully designed bottom slide-in cookie consent banner that appears with smooth transitions and elegant animations. Features progressive disclosure, customizable settings, and a modern design that enhances user experience while ensuring GDPR compliance.
Features
- Smooth Slide Animation: Elegant bottom slide-in transition with easing curves
- Progressive Disclosure: Expandable sections for detailed cookie information
- Smooth Transitions: Fluid animations for all interactive elements
- 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 implementation with fast loading
Preview
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bottom Slide Cookie Banner</title>
<style>
:root {
--primary-color: #4f46e5;
--primary-hover: #4338ca;
--secondary-color: #6b7280;
--success-color: #059669;
--success-hover: #047857;
--danger-color: #dc2626;
--danger-hover: #b91c1c;
--background: #ffffff;
--surface: #f9fafb;
--text-primary: #111827;
--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);
--border-radius: 8px;
--border-radius-lg: 12px;
--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);
--slide-distance: 100%;
}
* {
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;
overflow-x: hidden;
}
.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);
}
/* Bottom Slide Cookie Banner */
.bottom-slide-cookie-banner {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: var(--background);
border-top: 1px solid var(--border-color);
box-shadow: 0 -4px 6px -1px rgba(0, 0, 0, 0.1), 0 -2px 4px -1px rgba(0, 0, 0, 0.06);
transform: translateY(var(--slide-distance));
transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
z-index: 10000;
backdrop-filter: blur(20px);
}
.bottom-slide-cookie-banner.show {
transform: translateY(0);
}
.banner-content {
max-width: 1200px;
margin: 0 auto;
padding: 1.5rem;
}
.banner-header {
display: flex;
align-items: flex-start;
gap: 1rem;
margin-bottom: 1rem;
}
.banner-icon {
width: 48px;
height: 48px;
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-hover) 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
color: white;
flex-shrink: 0;
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% {
transform: scale(1);
box-shadow: 0 0 0 0 rgba(79, 70, 229, 0.4);
}
50% {
transform: scale(1.05);
box-shadow: 0 0 0 10px rgba(79, 70, 229, 0);
}
}
.banner-text {
flex: 1;
}
.banner-title {
font-size: 1.25rem;
font-weight: 700;
color: var(--text-primary);
margin-bottom: 0.5rem;
}
.banner-description {
color: var(--text-secondary);
font-size: 0.95rem;
line-height: 1.6;
}
.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%;
}
.banner-actions {
display: flex;
gap: 0.75rem;
align-items: center;
flex-wrap: wrap;
margin-top: 1rem;
}
/* Slide Buttons */
.slide-btn {
padding: 0.75rem 1.5rem;
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;
min-width: 120px;
}
.slide-btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
transition: left 0.5s ease;
}
.slide-btn:hover::before {
left: 100%;
}
.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-customize {
background: var(--surface);
color: var(--text-primary);
border: 1px solid var(--border-color);
box-shadow: var(--shadow-sm);
}
.btn-customize:hover {
background: var(--border-color);
transform: translateY(-2px);
box-shadow: var(--shadow-md);
}
.btn-expand {
background: transparent;
color: var(--primary-color);
border: 1px solid var(--primary-color);
padding: 0.5rem 1rem;
font-size: 0.8rem;
}
.btn-expand:hover {
background: var(--primary-color);
color: white;
}
/* Expandable Details */
.expandable-details {
max-height: 0;
overflow: hidden;
transition: max-height 0.4s cubic-bezier(0.4, 0, 0.2, 1), padding 0.4s ease;
background: var(--surface);
border-radius: var(--border-radius);
margin-top: 1rem;
}
.expandable-details.expanded {
max-height: 400px;
padding: 1.5rem;
border: 1px solid var(--border-color);
}
.details-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
}
.cookie-category {
background: var(--background);
padding: 1rem;
border-radius: var(--border-radius);
border: 1px solid var(--border-color);
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: 0.75rem;
}
.category-title {
font-weight: 700;
font-size: 1rem;
color: var(--text-primary);
}
.category-description {
font-size: 0.85rem;
color: var(--text-secondary);
line-height: 1.5;
}
/* Slide Toggle */
.slide-toggle {
position: relative;
width: 48px;
height: 24px;
background: var(--border-color);
border-radius: 12px;
cursor: pointer;
transition: var(--transition);
}
.slide-toggle.active {
background: var(--success-color);
}
.slide-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);
}
.slide-toggle.active::before {
transform: translateX(24px);
}
.slide-toggle:hover {
transform: scale(1.05);
}
/* Progress Indicator */
.progress-indicator {
position: absolute;
bottom: 0;
left: 0;
height: 3px;
background: var(--primary-color);
width: 0;
transition: width 0.3s ease;
}
.banner-content:hover .progress-indicator {
width: 100%;
}
/* 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;
}
.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;
}
.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;
}
}
/* Responsive Design */
@media (max-width: 768px) {
.banner-header {
flex-direction: column;
text-align: center;
}
.banner-actions {
justify-content: center;
flex-direction: column;
}
.slide-btn {
width: 100%;
min-width: auto;
}
.details-grid {
grid-template-columns: 1fr;
}
.banner-content {
padding: 1rem;
}
}
@media (max-width: 480px) {
body {
padding: 1rem;
}
.demo-container h1 {
font-size: 2rem;
}
.banner-content {
padding: 0.75rem;
}
.banner-title {
font-size: 1.1rem;
}
.banner-description {
font-size: 0.9rem;
}
}
/* Slide-in Animation Variants */
.slide-in-left {
transform: translateX(-100%);
}
.slide-in-right {
transform: translateX(100%);
}
.slide-in-fade {
transform: translateY(100%) scale(0.9);
opacity: 0;
}
.slide-in-fade.show {
transform: translateY(0) scale(1);
opacity: 1;
}
/* Bounce Effect */
.bounce-in {
animation: bounceIn 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
@keyframes bounceIn {
0% {
transform: translateY(100%) scale(0.3);
opacity: 0;
}
50% {
transform: translateY(-10%) scale(1.05);
}
70% {
transform: translateY(5%) scale(0.98);
}
100% {
transform: translateY(0) scale(1);
opacity: 1;
}
}
</style>
</head>
<body>
<div class="demo-container">
<h1>Smooth Slide Design</h1>
<p>Experience the elegance of smooth slide transitions with progressive disclosure and modern interactions</p>
<button class="demo-btn" onclick="showCookieBanner()">Show Cookie Banner</button>
</div>
<!-- Bottom Slide Cookie Banner -->
<div id="bottomSlideCookieBanner" class="bottom-slide-cookie-banner">
<div class="progress-indicator"></div>
<div class="banner-content">
<div class="banner-header">
<div class="banner-icon">🍪</div>
<div class="banner-text">
<div class="banner-title">Cookie Preferences</div>
<div class="banner-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>
</div>
<div class="banner-actions">
<button class="slide-btn btn-accept" onclick="acceptCookies()">Accept All</button>
<button class="slide-btn btn-decline" onclick="declineCookies()">Decline</button>
<button class="slide-btn btn-customize" onclick="openCustomization()">Customize</button>
<button class="slide-btn btn-expand" onclick="toggleDetails()">Learn More</button>
</div>
<!-- Expandable Details -->
<div id="expandableDetails" class="expandable-details">
<div class="details-grid">
<div class="cookie-category">
<div class="category-header">
<span class="category-title">Essential Cookies</span>
<div class="slide-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="slide-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="slide-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="slide-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>
</div>
</div>
<script>
class BottomSlideCookieBanner {
constructor(options = {}) {
this.options = {
autoShow: true,
showDelay: 1500,
storageKey: 'bottom_slide_cookie_consent',
expirationDays: 365,
enableAnimations: true,
slideDirection: 'bottom',
animationType: 'slide', // 'slide', 'fade', 'bounce'
progressiveDisclosure: true,
onAccept: null,
onDecline: null,
onCustomize: null,
...options
};
this.banner = document.getElementById('bottomSlideCookieBanner');
this.expandableDetails = document.getElementById('expandableDetails');
this.consent = this.getStoredConsent();
this.isVisible = false;
this.isExpanded = false;
this.init();
}
init() {
if (this.options.autoShow && !this.consent) {
setTimeout(() => this.show(), this.options.showDelay);
}
this.setupEventListeners();
this.loadConfiguration();
this.setupAnimationType();
}
setupEventListeners() {
// Toggle switches
document.querySelectorAll('.slide-toggle').forEach(toggle => {
toggle.addEventListener('click', () => {
if (toggle.dataset.category !== 'essential') {
toggle.classList.toggle('active');
this.animateToggle(toggle);
}
});
});
// Keyboard navigation
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && this.isExpanded) {
this.toggleDetails();
}
});
// Button hover effects
document.querySelectorAll('.slide-btn').forEach(btn => {
btn.addEventListener('mouseenter', () => {
this.createRipple(btn);
});
});
// Progress indicator on hover
this.banner.addEventListener('mouseenter', () => {
if (this.isVisible) {
this.enhanceProgressIndicator();
}
});
this.banner.addEventListener('mouseleave', () => {
if (this.isVisible) {
this.resetProgressIndicator();
}
});
}
setupAnimationType() {
const animationClasses = {
slide: '',
fade: 'slide-in-fade',
bounce: 'bounce-in'
};
const animationClass = animationClasses[this.options.animationType];
if (animationClass) {
this.banner.classList.add(animationClass);
}
}
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(5, 150, 105, 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);
}
enhanceProgressIndicator() {
if (!this.options.enableAnimations) return;
const indicator = this.banner.querySelector('.progress-indicator');
if (indicator) {
indicator.style.background = 'linear-gradient(90deg, var(--primary-color), var(--success-color))';
indicator.style.height = '4px';
}
}
resetProgressIndicator() {
if (!this.options.enableAnimations) return;
const indicator = this.banner.querySelector('.progress-indicator');
if (indicator) {
indicator.style.background = 'var(--primary-color)';
indicator.style.height = '3px';
}
}
show() {
this.banner.classList.add('show');
this.isVisible = true;
if (this.options.enableAnimations) {
this.animateEntrance();
}
}
hide() {
this.banner.classList.remove('show');
this.isVisible = false;
this.isExpanded = false;
this.expandableDetails.classList.remove('expanded');
}
animateEntrance() {
const elements = [
this.banner.querySelector('.banner-icon'),
this.banner.querySelector('.banner-title'),
this.banner.querySelector('.banner-description'),
this.banner.querySelector('.banner-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);
}
});
}
toggleDetails() {
this.isExpanded = !this.isExpanded;
if (this.isExpanded) {
this.expandableDetails.classList.add('expanded');
if (this.options.enableAnimations) {
this.animateDetailsExpansion();
}
} else {
this.expandableDetails.classList.remove('expanded');
}
// Update button text
const expandBtn = this.banner.querySelector('.btn-expand');
if (expandBtn) {
expandBtn.textContent = this.isExpanded ? 'Show Less' : 'Learn More';
}
}
animateDetailsExpansion() {
const categories = this.expandableDetails.querySelectorAll('.cookie-category');
categories.forEach((category, index) => {
category.style.opacity = '0';
category.style.transform = 'translateY(20px)';
setTimeout(() => {
category.style.transition = 'all 0.4s cubic-bezier(0.4, 0, 0.2, 1)';
category.style.opacity = '1';
category.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="checkmark-circle" cx="26" cy="26" r="25" fill="none"/>
<path class="checkmark-check" fill="none" d="m14.1 27.2l7.1 7.2 16.7-16.8"/>
</svg>
Accepted
`;
acceptBtn.style.background = 'var(--success-color)';
}
}
customize() {
this.toggleDetails();
if (this.options.onCustomize) {
this.options.onCustomize();
}
}
saveCustomization() {
const toggles = document.querySelectorAll('.slide-toggle');
const consent = { timestamp: Date.now() };
toggles.forEach(toggle => {
const category = toggle.dataset.category;
consent[category] = toggle.classList.contains('active');
});
this.saveConsent(consent);
this.hide();
if (this.options.onCustomize) {
this.options.onCustomize(consent);
}
}
loadConfiguration() {
if (this.consent) {
document.querySelectorAll('.slide-toggle').forEach(toggle => {
const category = toggle.dataset.category;
if (this.consent[category]) {
toggle.classList.add('active');
} else {
toggle.classList.remove('active');
}
});
}
}
saveConsent(consent) {
const expirationDate = new Date();
expirationDate.setDate(expirationDate.getDate() + this.options.expirationDays);
const consentData = {
...consent,
expiration: expirationDate.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.expiration && Date.now() < data.expiration) {
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;
}
setSlideDirection(direction) {
this.options.slideDirection = direction;
this.setupSlideDirection();
}
setupSlideDirection() {
const directions = {
bottom: 'translateY(100%)',
top: 'translateY(-100%)',
left: 'translateX(-100%)',
right: 'translateX(100%)'
};
const transform = directions[this.options.slideDirection] || directions.bottom;
document.documentElement.style.setProperty('--slide-distance', transform);
}
setAnimationType(type) {
this.options.animationType = type;
this.setupAnimationType();
}
enableAnimations(enabled) {
this.options.enableAnimations = enabled;
}
updateTheme(theme) {
const themes = {
light: {
'--background': '#ffffff',
'--surface': '#f9fafb',
'--text-primary': '#111827',
'--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 BottomSlideCookieBanner({
slideDirection: 'bottom',
animationType: 'slide',
enableAnimations: true,
progressiveDisclosure: true,
onAccept: (consent) => {
console.log('Cookies accepted:', consent);
// Initialize analytics, marketing scripts, etc.
},
onDecline: (consent) => {
console.log('Cookies declined:', consent);
// Load only essential scripts
},
onCustomize: (consent) => {
console.log('Custom configuration 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 openCustomization() {
cookieBanner.customize();
}
function toggleDetails() {
cookieBanner.toggleDetails();
}
</script>
</body>
</html>Usage
Basic Implementation
// Initialize with default settings
const cookieBanner = new BottomSlideCookieBanner();
// Initialize with custom options
const cookieBanner = new BottomSlideCookieBanner({
autoShow: true,
showDelay: 2000,
storageKey: 'my_cookie_consent',
expirationDays: 180,
enableAnimations: true,
slideDirection: 'bottom',
animationType: 'slide',
progressiveDisclosure: true,
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
},
onCustomize: (consent) => {
console.log('User saved custom configuration:', consent);
// Load scripts based on specific preferences
}
});Advanced Configuration
// Custom styling and behavior
const advancedBanner = new BottomSlideCookieBanner({
autoShow: false, // Manual control
showDelay: 0,
storageKey: 'advanced_consent',
expirationDays: 90,
enableAnimations: true,
slideDirection: 'bottom',
animationType: 'bounce',
progressiveDisclosure: true,
// Custom callbacks
onAccept: (consent) => {
// Advanced analytics setup
initializeAdvancedTracking(consent);
},
onDecline: (consent) => {
// Minimal tracking setup
initializeEssentialOnly();
},
onCustomize: (consent) => {
// Granular script loading
loadScriptsBasedOnConsent(consent);
}
});
// Direction control
function changeSlideDirection(direction) {
advancedBanner.setSlideDirection(direction);
}
// Animation control
function changeAnimationType(type) {
advancedBanner.setAnimationType(type);
}
// Animation toggle
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
Configuration Management
toggleDetails()- Toggle expandable details sectioncustomize()- Open customization interfacesaveCustomization()- Save current configurationloadConfiguration()- Load and apply stored configuration
Data Management
getConsent()- Get current consent objectsaveConsent(consent)- Save consent to storagegetStoredConsent()- Retrieve consent from storage
Customization
setSlideDirection(direction)- Change slide direction (‘bottom’, ‘top’, ‘left’, ‘right’)setAnimationType(type)- Change animation type (‘slide’, ‘fade’, ‘bounce’)enableAnimations(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
- Slide Effects: Customize slide directions and animation types
- 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
- Progressive Disclosure: Expandable sections for detailed information
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
1090
lines
CSS
1
lines
JavaScript
33
lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bottom Slide Cookie Banner</title>
<style>
:root {
--primary-color: #4f46e5;
--primary-hover: #4338ca;
--secondary-color: #6b7280;
--success-color: #059669;
--success-hover: #047857;
--danger-color: #dc2626;
--danger-hover: #b91c1c;
--background: #ffffff;
--surface: #f9fafb;
--text-primary: #111827;
--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);
--border-radius: 8px;
--border-radius-lg: 12px;
--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);
--slide-distance: 100%;
}
* {
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;
overflow-x: hidden;
}
.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);
}
/* Bottom Slide Cookie Banner */
.bottom-slide-cookie-banner {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: var(--background);
border-top: 1px solid var(--border-color);
box-shadow: 0 -4px 6px -1px rgba(0, 0, 0, 0.1), 0 -2px 4px -1px rgba(0, 0, 0, 0.06);
transform: translateY(var(--slide-distance));
transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
z-index: 10000;
backdrop-filter: blur(20px);
}
.bottom-slide-cookie-banner.show {
transform: translateY(0);
}
.banner-content {
max-width: 1200px;
margin: 0 auto;
padding: 1.5rem;
}
.banner-header {
display: flex;
align-items: flex-start;
gap: 1rem;
margin-bottom: 1rem;
}
.banner-icon {
width: 48px;
height: 48px;
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-hover) 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
color: white;
flex-shrink: 0;
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% {
transform: scale(1);
box-shadow: 0 0 0 0 rgba(79, 70, 229, 0.4);
}
50% {
transform: scale(1.05);
box-shadow: 0 0 0 10px rgba(79, 70, 229, 0);
}
}
.banner-text {
flex: 1;
}
.banner-title {
font-size: 1.25rem;
font-weight: 700;
color: var(--text-primary);
margin-bottom: 0.5rem;
}
.banner-description {
color: var(--text-secondary);
font-size: 0.95rem;
line-height: 1.6;
}
.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%;
}
.banner-actions {
display: flex;
gap: 0.75rem;
align-items: center;
flex-wrap: wrap;
margin-top: 1rem;
}
/* Slide Buttons */
.slide-btn {
padding: 0.75rem 1.5rem;
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;
min-width: 120px;
}
.slide-btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
transition: left 0.5s ease;
}
.slide-btn:hover::before {
left: 100%;
}
.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-customize {
background: var(--surface);
color: var(--text-primary);
border: 1px solid var(--border-color);
box-shadow: var(--shadow-sm);
}
.btn-customize:hover {
background: var(--border-color);
transform: translateY(-2px);
box-shadow: var(--shadow-md);
}
.btn-expand {
background: transparent;
color: var(--primary-color);
border: 1px solid var(--primary-color);
padding: 0.5rem 1rem;
font-size: 0.8rem;
}
.btn-expand:hover {
background: var(--primary-color);
color: white;
}
/* Expandable Details */
.expandable-details {
max-height: 0;
overflow: hidden;
transition: max-height 0.4s cubic-bezier(0.4, 0, 0.2, 1), padding 0.4s ease;
background: var(--surface);
border-radius: var(--border-radius);
margin-top: 1rem;
}
.expandable-details.expanded {
max-height: 400px;
padding: 1.5rem;
border: 1px solid var(--border-color);
}
.details-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
}
.cookie-category {
background: var(--background);
padding: 1rem;
border-radius: var(--border-radius);
border: 1px solid var(--border-color);
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: 0.75rem;
}
.category-title {
font-weight: 700;
font-size: 1rem;
color: var(--text-primary);
}
.category-description {
font-size: 0.85rem;
color: var(--text-secondary);
line-height: 1.5;
}
/* Slide Toggle */
.slide-toggle {
position: relative;
width: 48px;
height: 24px;
background: var(--border-color);
border-radius: 12px;
cursor: pointer;
transition: var(--transition);
}
.slide-toggle.active {
background: var(--success-color);
}
.slide-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);
}
.slide-toggle.active::before {
transform: translateX(24px);
}
.slide-toggle:hover {
transform: scale(1.05);
}
/* Progress Indicator */
.progress-indicator {
position: absolute;
bottom: 0;
left: 0;
height: 3px;
background: var(--primary-color);
width: 0;
transition: width 0.3s ease;
}
.banner-content:hover .progress-indicator {
width: 100%;
}
/* 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;
}
.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;
}
.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;
}
}
/* Responsive Design */
@media (max-width: 768px) {
.banner-header {
flex-direction: column;
text-align: center;
}
.banner-actions {
justify-content: center;
flex-direction: column;
}
.slide-btn {
width: 100%;
min-width: auto;
}
.details-grid {
grid-template-columns: 1fr;
}
.banner-content {
padding: 1rem;
}
}
@media (max-width: 480px) {
body {
padding: 1rem;
}
.demo-container h1 {
font-size: 2rem;
}
.banner-content {
padding: 0.75rem;
}
.banner-title {
font-size: 1.1rem;
}
.banner-description {
font-size: 0.9rem;
}
}
/* Slide-in Animation Variants */
.slide-in-left {
transform: translateX(-100%);
}
.slide-in-right {
transform: translateX(100%);
}
.slide-in-fade {
transform: translateY(100%) scale(0.9);
opacity: 0;
}
.slide-in-fade.show {
transform: translateY(0) scale(1);
opacity: 1;
}
/* Bounce Effect */
.bounce-in {
animation: bounceIn 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
@keyframes bounceIn {
0% {
transform: translateY(100%) scale(0.3);
opacity: 0;
}
50% {
transform: translateY(-10%) scale(1.05);
}
70% {
transform: translateY(5%) scale(0.98);
}
100% {
transform: translateY(0) scale(1);
opacity: 1;
}
}
</style>
</head>
<body>
<div class="demo-container">
<h1>Smooth Slide Design</h1>
<p>Experience the elegance of smooth slide transitions with progressive disclosure and modern interactions</p>
<button class="demo-btn" onclick="showCookieBanner()">Show Cookie Banner</button>
</div>
<!-- Bottom Slide Cookie Banner -->
<div id="bottomSlideCookieBanner" class="bottom-slide-cookie-banner">
<div class="progress-indicator"></div>
<div class="banner-content">
<div class="banner-header">
<div class="banner-icon">🍪</div>
<div class="banner-text">
<div class="banner-title">Cookie Preferences</div>
<div class="banner-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>
</div>
<div class="banner-actions">
<button class="slide-btn btn-accept" onclick="acceptCookies()">Accept All</button>
<button class="slide-btn btn-decline" onclick="declineCookies()">Decline</button>
<button class="slide-btn btn-customize" onclick="openCustomization()">Customize</button>
<button class="slide-btn btn-expand" onclick="toggleDetails()">Learn More</button>
</div>
<!-- Expandable Details -->
<div id="expandableDetails" class="expandable-details">
<div class="details-grid">
<div class="cookie-category">
<div class="category-header">
<span class="category-title">Essential Cookies</span>
<div class="slide-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="slide-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="slide-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="slide-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>
</div>
</div>
<script>
class BottomSlideCookieBanner {
constructor(options = {}) {
this.options = {
autoShow: true,
showDelay: 1500,
storageKey: 'bottom_slide_cookie_consent',
expirationDays: 365,
enableAnimations: true,
slideDirection: 'bottom',
animationType: 'slide', // 'slide', 'fade', 'bounce'
progressiveDisclosure: true,
onAccept: null,
onDecline: null,
onCustomize: null,
...options
};
this.banner = document.getElementById('bottomSlideCookieBanner');
this.expandableDetails = document.getElementById('expandableDetails');
this.consent = this.getStoredConsent();
this.isVisible = false;
this.isExpanded = false;
this.init();
}
init() {
if (this.options.autoShow && !this.consent) {
setTimeout(() => this.show(), this.options.showDelay);
}
this.setupEventListeners();
this.loadConfiguration();
this.setupAnimationType();
}
setupEventListeners() {
// Toggle switches
document.querySelectorAll('.slide-toggle').forEach(toggle => {
toggle.addEventListener('click', () => {
if (toggle.dataset.category !== 'essential') {
toggle.classList.toggle('active');
this.animateToggle(toggle);
}
});
});
// Keyboard navigation
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && this.isExpanded) {
this.toggleDetails();
}
});
// Button hover effects
document.querySelectorAll('.slide-btn').forEach(btn => {
btn.addEventListener('mouseenter', () => {
this.createRipple(btn);
});
});
// Progress indicator on hover
this.banner.addEventListener('mouseenter', () => {
if (this.isVisible) {
this.enhanceProgressIndicator();
}
});
this.banner.addEventListener('mouseleave', () => {
if (this.isVisible) {
this.resetProgressIndicator();
}
});
}
setupAnimationType() {
const animationClasses = {
slide: '',
fade: 'slide-in-fade',
bounce: 'bounce-in'
};
const animationClass = animationClasses[this.options.animationType];
if (animationClass) {
this.banner.classList.add(animationClass);
}
}
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(5, 150, 105, 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);
}
enhanceProgressIndicator() {
if (!this.options.enableAnimations) return;
const indicator = this.banner.querySelector('.progress-indicator');
if (indicator) {
indicator.style.background = 'linear-gradient(90deg, var(--primary-color), var(--success-color))';
indicator.style.height = '4px';
}
}
resetProgressIndicator() {
if (!this.options.enableAnimations) return;
const indicator = this.banner.querySelector('.progress-indicator');
if (indicator) {
indicator.style.background = 'var(--primary-color)';
indicator.style.height = '3px';
}
}
show() {
this.banner.classList.add('show');
this.isVisible = true;
if (this.options.enableAnimations) {
this.animateEntrance();
}
}
hide() {
this.banner.classList.remove('show');
this.isVisible = false;
this.isExpanded = false;
this.expandableDetails.classList.remove('expanded');
}
animateEntrance() {
const elements = [
this.banner.querySelector('.banner-icon'),
this.banner.querySelector('.banner-title'),
this.banner.querySelector('.banner-description'),
this.banner.querySelector('.banner-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);
}
});
}
toggleDetails() {
this.isExpanded = !this.isExpanded;
if (this.isExpanded) {
this.expandableDetails.classList.add('expanded');
if (this.options.enableAnimations) {
this.animateDetailsExpansion();
}
} else {
this.expandableDetails.classList.remove('expanded');
}
// Update button text
const expandBtn = this.banner.querySelector('.btn-expand');
if (expandBtn) {
expandBtn.textContent = this.isExpanded ? 'Show Less' : 'Learn More';
}
}
animateDetailsExpansion() {
const categories = this.expandableDetails.querySelectorAll('.cookie-category');
categories.forEach((category, index) => {
category.style.opacity = '0';
category.style.transform = 'translateY(20px)';
setTimeout(() => {
category.style.transition = 'all 0.4s cubic-bezier(0.4, 0, 0.2, 1)';
category.style.opacity = '1';
category.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="checkmark-circle" cx="26" cy="26" r="25" fill="none"/>
<path class="checkmark-check" fill="none" d="m14.1 27.2l7.1 7.2 16.7-16.8"/>
</svg>
Accepted
`;
acceptBtn.style.background = 'var(--success-color)';
}
}
customize() {
this.toggleDetails();
if (this.options.onCustomize) {
this.options.onCustomize();
}
}
saveCustomization() {
const toggles = document.querySelectorAll('.slide-toggle');
const consent = { timestamp: Date.now() };
toggles.forEach(toggle => {
const category = toggle.dataset.category;
consent[category] = toggle.classList.contains('active');
});
this.saveConsent(consent);
this.hide();
if (this.options.onCustomize) {
this.options.onCustomize(consent);
}
}
loadConfiguration() {
if (this.consent) {
document.querySelectorAll('.slide-toggle').forEach(toggle => {
const category = toggle.dataset.category;
if (this.consent[category]) {
toggle.classList.add('active');
} else {
toggle.classList.remove('active');
}
});
}
}
saveConsent(consent) {
const expirationDate = new Date();
expirationDate.setDate(expirationDate.getDate() + this.options.expirationDays);
const consentData = {
...consent,
expiration: expirationDate.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.expiration && Date.now() < data.expiration) {
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;
}
setSlideDirection(direction) {
this.options.slideDirection = direction;
this.setupSlideDirection();
}
setupSlideDirection() {
const directions = {
bottom: 'translateY(100%)',
top: 'translateY(-100%)',
left: 'translateX(-100%)',
right: 'translateX(100%)'
};
const transform = directions[this.options.slideDirection] || directions.bottom;
document.documentElement.style.setProperty('--slide-distance', transform);
}
setAnimationType(type) {
this.options.animationType = type;
this.setupAnimationType();
}
enableAnimations(enabled) {
this.options.enableAnimations = enabled;
}
updateTheme(theme) {
const themes = {
light: {
'--background': '#ffffff',
'--surface': '#f9fafb',
'--text-primary': '#111827',
'--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 BottomSlideCookieBanner({
slideDirection: 'bottom',
animationType: 'slide',
enableAnimations: true,
progressiveDisclosure: true,
onAccept: (consent) => {
console.log('Cookies accepted:', consent);
// Initialize analytics, marketing scripts, etc.
},
onDecline: (consent) => {
console.log('Cookies declined:', consent);
// Load only essential scripts
},
onCustomize: (consent) => {
console.log('Custom configuration 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 openCustomization() {
cookieBanner.customize();
}
function toggleDetails() {
cookieBanner.toggleDetails();
}
</script>
</body>
</html>