webdevpuneet.com

Cookie Preferences Modal — Free HTML CSS JS Snippet

Cookie Preferences · Modals · Plain HTML, CSS & JS · Live preview

CategoryModals
TagsSVG

Copy & paste

Source Code

<div class="page">
  <div class="backdrop" id="backdrop"></div>
  <div class="banner" id="banner">
    <div class="banner-left">
      <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><circle cx="9" cy="9" r="1.5" fill="currentColor"/><circle cx="15" cy="9" r="1" fill="currentColor"/><circle cx="10" cy="14" r="1" fill="currentColor"/><circle cx="14" cy="13" r="1.5" fill="currentColor"/></svg>
      <div>
        <div class="banner-title">We use cookies</div>
        <div class="banner-sub">We use cookies to personalise content and ads, analyse traffic, and improve your experience.</div>
      </div>
    </div>
    <div class="banner-btns">
      <button class="btn-pref" onclick="openModal()">Manage Preferences</button>
      <button class="btn-reject" onclick="reject()">Reject All</button>
      <button class="btn-accept" onclick="acceptAll()">Accept All</button>
    </div>
  </div>
  <div class="modal" id="modal" style="display:none">
    <div class="modal-box">
      <div class="modal-head">
        <h2 class="modal-title">Cookie Preferences</h2>
        <button class="modal-close" onclick="closeModal()">
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
        </button>
      </div>
      <p class="modal-desc">Choose which cookies you allow us to use. You can change these preferences at any time.</p>
      <div class="pref-list">
        <div class="pref-row required">
          <div class="pref-info">
            <div class="pref-name">Essential Cookies <span class="required-badge">Required</span></div>
            <div class="pref-desc">Necessary for the website to function correctly. Cannot be disabled.</div>
          </div>
          <label class="toggle disabled"><input type="checkbox" checked disabled><span class="track"></span></label>
        </div>
        <div class="pref-row">
          <div class="pref-info">
            <div class="pref-name">Analytics Cookies</div>
            <div class="pref-desc">Help us understand how visitors interact with the site (Google Analytics, Hotjar).</div>
          </div>
          <label class="toggle"><input type="checkbox" id="analytics" checked><span class="track"></span></label>
        </div>
        <div class="pref-row">
          <div class="pref-info">
            <div class="pref-name">Marketing Cookies</div>
            <div class="pref-desc">Used to show personalised ads and track campaigns across platforms.</div>
          </div>
          <label class="toggle"><input type="checkbox" id="marketing"><span class="track"></span></label>
        </div>
        <div class="pref-row">
          <div class="pref-info">
            <div class="pref-name">Preference Cookies</div>
            <div class="pref-desc">Remember your settings like language, region, and display preferences.</div>
          </div>
          <label class="toggle"><input type="checkbox" id="preferences" checked><span class="track"></span></label>
        </div>
      </div>
      <div class="modal-footer">
        <button class="btn-reject-sm" onclick="reject()">Reject All</button>
        <button class="btn-save" onclick="savePrefs()">Save Preferences</button>
        <button class="btn-accept" onclick="acceptAll()">Accept All</button>
      </div>
    </div>
  </div>
  <div class="page-content">
    <h1>Demo Page</h1>
    <p>This page shows a cookie banner at the bottom. Click "Manage Preferences" to open the cookie preferences modal.</p>
    <div class="status-box" id="statusBox" style="display:none">
      <div class="status-icon">&#10003;</div>
      <div id="statusMsg"></div>
    </div>
  </div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Fixed bottom banner: center-aligned with max-width cap at 860px
Three banner actions: Manage Preferences, Reject All, Accept All
Modal overlay with fixed backdrop at z-index: 300
4 cookie categories: Essential (required), Analytics, Marketing, Preferences
CSS toggle switches with disabled state for Essential (always on)
Accept All, Reject All, Save Preferences in both banner and modal
Confirmation status box: shown on page after banner dismissal
No external CMP library — pure HTML/CSS/JS cookie consent UI

About this UI Snippet

Cookie Preferences Modal — GDPR Consent Banner with Category Toggles

Screenshot of the Cookie Preferences snippet rendered live

A cookie preferences modal is a legal requirement for websites under GDPR (EU), CCPA (California), and similar privacy regulations. This snippet provides a complete cookie consent system: a fixed bottom banner with Accept All, Reject All, and Manage Preferences buttons; a modal overlay with per-category toggle switches (Essential, Analytics, Marketing, Preferences); and a confirmation state after any choice is saved.

The banner layout

The .banner uses position: fixed, bottom: 20px, left: 50% with transform: translateX(-50%) to centre it above the page footer. A max-width: 860px keeps it from stretching too wide on large screens. The backdrop is a fixed overlay that darkens the page when the modal is open.

The CSS toggle switches

Each cookie category uses the same CSS toggle pattern: a hidden checkbox + .track pseudo-element. The Essential Cookies toggle has disabled attribute and .disabled class — its .track background is set to a light indigo (always-on appearance) without the cursor: pointer, communicating that it cannot be changed. The other three toggles start with different default states (Analytics: on, Marketing: off, Preferences: on) to demonstrate a realistic defaults scenario.

The three action paths

Accept All checks all three optional checkboxes before calling dismiss(). Reject All unchecks all three before calling dismiss(). Save Preferences reads the current checkbox states and builds a summary message before calling dismiss(). All three then hide the banner and show the status confirmation box on the page.

GDPR compliance notes

This snippet provides the UI pattern. For actual legal compliance, integrate with a Consent Management Platform (CMP) like the GDPR consent manager or store consent preferences in a cookie: document.cookie = "consent=" + JSON.stringify({ analytics, marketing, preferences }) + "; max-age=31536000; SameSite=Lax". Only load third-party analytics/ad scripts after the user has given consent.

Conditional script injection after consent

The most important production step is ensuring that tracking scripts are never executed before the user grants the relevant consent. The standard technique is to not include script tags for Google Analytics, Facebook Pixel, or any ad network in the initial HTML. Instead, dynamically create and append script elements only inside the acceptAll() or savePrefs() callback after reading the consent flags. For Tag Manager (GTM) workflows, push a custom dataLayer event: window.dataLayer.push({ event: "cookie_consent_update", analytics_consent: "granted" }) and configure GTM triggers that fire only when this event is present. This keeps all tracking logic in GTM without code changes for future tag additions.

Re-opening the preferences modal

Users must be able to withdraw or change consent at any time under GDPR. Add a "Cookie Settings" link in your site footer that calls openModal() to re-show the modal at any time. Read the current saved consent cookie and pre-populate the toggle checkboxes to their last saved state so users see their existing choices before making changes. After they save again, overwrite the consent cookie with the new values and apply or remove scripts accordingly — marketing scripts already injected may need a page reload to fully deactivate.

Step by step

How to Use

  1. 1
    See the banner on page loadThe cookie banner appears fixed at the bottom of the page. It has three buttons: Manage Preferences, Reject All, and Accept All.
  2. 2
    Open the preferences modalClick "Manage Preferences" to open the modal with four cookie categories. Essential is always on. Toggle Analytics, Marketing, and Preferences independently.
  3. 3
    Save, Accept, or RejectClick "Save Preferences" to save your current toggle states. "Accept All" turns on all optional categories. "Reject All" turns them all off. The banner dismisses and a confirmation appears on the page.
  4. 4
    Persist consent to a cookieIn the dismiss() function, save the consent state: document.cookie = "consent=" + JSON.stringify({ analytics, marketing, preferences }) + "; max-age=31536000". On page load, read this cookie and skip showing the banner if it exists.
  5. 5
    Load scripts conditionally on consentAfter accept/save, check each consent flag before injecting analytics or marketing scripts: if (analytics) { const s = document.createElement("script"); s.src = "https://www.google-analytics.com/analytics.js"; document.head.appendChild(s); }
  6. 6
    Export for your frameworkClick "JSX" for a React component with useState for modal open state and toggle values. Click "Vue" for a Vue 3 SFC with reactive consent object.

Real-world uses

Common Use Cases

GDPR cookie consent for EU-targeted web apps
Required for any website with EU visitors that uses tracking cookies (Google Analytics, Facebook Pixel, Hotjar, etc.). Wire the consent choices to conditional script loading: only inject third-party scripts after the user grants consent for that category.
Privacy-first SaaS onboarding with consent step
Show the preferences modal as part of account creation rather than a banner — step 3 of 5 in the onboarding flow. This is cleaner than a banner and gets explicit, documented per-category consent at signup time.
E-commerce site cookie management for ad tracking
Marketing cookies control Facebook Pixel, Google Ads, and retargeting pixels. Reject All compliance means these scripts are not loaded when rejected. Wire Marketing consent flag to conditional Facebook Pixel init: if (consent.marketing) { fbq("init", "PIXEL_ID"); }
Integrate with a backend consent audit log
POST consent choices to /api/consent on save: { userId, analytics, marketing, preferences, timestamp, ip }. This creates an audit trail for compliance with GDPR Art. 7 (documented consent). Store in a separate consent_logs table, never in the main user record.
Study fixed positioning, modal overlays, and CSS toggles
The snippet demonstrates three layout techniques: fixed bottom banner positioning, a modal dialog with backdrop overlay at higher z-index, and the CSS toggle switch pattern (hidden checkbox + pseudo-element track). These patterns are foundational for cookie banners, dialogs, and drawers.
Cookie-free analytics with consent-aware fallback
Use the Marketing and Analytics consent flags to switch between full tracking and privacy-respecting alternatives: Plausible.io or Fathom (no cookies, no consent required) vs. Google Analytics (requires consent). Show different tracking scripts based on the consent state.
Related: Cookie Preferences Panel
See the Cookie Preferences Panel for a related modals pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

Use a cookie: document.cookie = "cookie_consent=" + JSON.stringify({ analytics: true, marketing: false, preferences: true }) + "; max-age=31536000; path=/; SameSite=Lax". On DOMContentLoaded, read with document.cookie and skip showing the banner if "cookie_consent=" is found. Parse with JSON.parse(cookieVal) to get the per-category choices.

The UI meets the visual and functional requirements (prior consent, granular controls, easy rejection, no pre-ticked marketing boxes). Legal compliance also requires: storing a dated consent record linked to the user, a privacy policy link, ability to withdraw consent, and only loading tracking scripts after consent. Consult a lawyer or use a full CMP for regulated environments.

In acceptAll() or savePrefs(), check analytics consent: if (analytics) { window.dataLayer = window.dataLayer || []; function gtag(){ dataLayer.push(arguments); } gtag("js", new Date()); gtag("config", "GA_ID"); const s = document.createElement("script"); s.src = "https://www.googletagmanager.com/gtag/js?id=GA_ID"; s.async = true; document.head.appendChild(s); }

In React, manage state with const [visible, setVisible] = useState(true) for the banner, const [modalOpen, setModalOpen] = useState(false), and const [prefs, setPrefs] = useState({ analytics: true, marketing: false, preferences: true }). Read persisted consent from localStorage on mount in useEffect. In Vue 3, use ref(true) for bannerVisible and a reactive() object for prefs. In Angular, create a CookieConsentService with BehaviorSubject<ConsentPrefs> and inject it into your app root component. All three frameworks follow the same pattern: read → show banner if no saved consent → save on user action.