Skip to main content

Menu

Choose a theme and configure high-contrast mode. Preferences are saved in your browser only.

User Preferences

Theme

Pick a palette or follow your system preference.

High Contrast

Sharper text and borders. System follows your OS setting.

Styling & Customization

Customize the appearance of Zest consent UI

Theming

Zest supports three theme modes:

window.ZestConfig = {
  theme: 'auto' // 'light', 'dark', or 'auto'
};
Theme Behavior
light Always use light theme
dark Always use dark theme
auto Follow system preference (prefers-color-scheme)

Accent Color

Customize the primary button color:

window.ZestConfig = {
  accentColor: '#0071e3' // Any valid CSS color
};

The accent color is used for:

  • “Accept All” button background
  • Toggle switches when enabled
  • Focus rings and highlights

Validated since v2.0.0. The value is passed through a strict color validator that accepts hex (#0071e3), named colors (rebeccapurple), and the rgb(), rgba(), hsl(), and hsla() functions. Anything else falls back silently to the default.

Control where the banner appears:

window.ZestConfig = {
  position: 'bottom-right'
};
Position Description
bottom Centered at bottom of page
bottom-left Floating card at bottom-left corner
bottom-right Floating card at bottom-right corner
top Centered at top of page
top-left Floating card at top-left corner (v2.6.0+)
top-right Floating card at top-right corner (v2.6.0+)
center Dead-center of the viewport, fades in with a subtle scale (v2.6.0+)

Button Style & Layout

Control how the action buttons look and are arranged:

window.ZestConfig = {
  buttonStyle: 'fill',     // 'fill' (solid) or 'outline' (accent-bordered)
  buttonLayout: 'row'      // 'row', 'split', or 'split-modern'
};
Layout Description
row All buttons in a single row (default)
split Settings/Save on the left, Accept + Reject grouped on the right (v2.6.0+)
split-modern Same as split, but Settings/Save is the primary button and Accept/Reject are secondary (v2.6.0+)

The split-modern layout draws attention to the preferences action — useful when you want visitors to engage with the settings modal rather than blindly accepting.

Backdrop Blur

Blur the page content behind the modal and hard wall overlay:

window.ZestConfig = {
  backdropBlur: 8  // blur radius in pixels, 0 disables
};

The blur applies to both the settings modal overlay and the hard consent wall. Off by default because backdrop-filter can be expensive on low-end devices.

Block all page interaction until the visitor decides:

window.ZestConfig = {
  hardWall: true
};

A full-viewport overlay renders behind the banner, preventing clicks or interaction with the page until the visitor accepts or rejects. The banner becomes aria-modal when the wall is active. Useful for compliance-sensitive sites that need provable awareness — 100% decision visibility.

Hidden Categories

Remove unused consent categories from the settings modal:

window.ZestConfig = {
  categories: {
    analytics: { hidden: true },
    marketing: { hidden: true }
  }
};

Hidden categories are forced to false (rejected) — a visitor can never accept a toggle they cannot see. Essential cannot be hidden. Also accepted via data-hide-categories="analytics,marketing".

This solves a real transparency problem: showing empty toggles for categories a site doesn’t use implies data processing that isn’t happening. A site with only embedded YouTube (marketing) and cookieless analytics doesn’t need to show Functional or Analytics toggles.

CSS Custom Properties

Zest uses CSS custom properties that you can override. Since Zest uses Shadow DOM, you need to use the customStyles configuration option:

window.ZestConfig = {
  customStyles: `
    :host {
      --zest-accent: #ff6b35;
      --zest-bg: #1a1a2e;
      --zest-bg-secondary: #16213e;
      --zest-text: #edf2f7;
      --zest-text-secondary: #a0aec0;
      --zest-border: #2d3748;
      --zest-radius: 16px;
      --zest-radius-sm: 8px;
    }
  `
};

Available CSS Variables

Variable Default (Light) Description
--zest-accent #0071e3 Primary accent color
--zest-accent-text auto Text color on primary buttons. Uses CSS contrast-color() (Baseline April 2026) with a JS WCAG luminance fallback for older browsers. Light accent colors get dark text automatically (v2.6.0+)
--zest-overlay rgba(0, 0, 0, 0.5) Background color of the modal overlay and hard consent wall. One variable, same color everywhere (v2.6.0+)
--zest-bg #ffffff Background color
--zest-bg-secondary #f3f4f6 Secondary background
--zest-text #1f2937 Primary text color
--zest-text-secondary #6b7280 Secondary text color
--zest-border #e5e7eb Border color
--zest-radius 12px Large border radius
--zest-radius-sm 8px Small border radius

Custom CSS

Inject custom CSS into the Shadow DOM.

Sanitized since v2.0.0. customStyles is hard-capped at 20 KB, and the following are stripped before injection: @import, @charset, expression(), -moz-binding, and external url() values. Selectors targeting the accept/reject buttons (e.g. .zest-btn--primary { opacity: 0 }) are also removed to prevent clickjacking via invisible-button attacks. Theme variables and ordinary layout styles are unaffected.

window.ZestConfig = {
  customStyles: `
    /* Custom banner styles */
    .zest-banner {
      max-width: 500px;
      box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
    }

    /* Custom button styles */
    .zest-btn--primary {
      border-radius: 9999px;
      font-weight: 600;
      text-transform: uppercase;
      letter-spacing: 0.05em;
    }

    /* Custom modal styles */
    .zest-modal {
      max-width: 600px;
    }

    /* Custom widget styles */
    .zest-widget {
      bottom: 24px;
      right: 24px;
    }
  `
};

CSS Class Reference

Banner:

  • .zest-banner - Main banner container
  • .zest-banner--bottom / .zest-banner--top / .zest-banner--center etc. - Position variants
  • .zest-banner-wall - Hard wall overlay (v2.6.0+)
  • .zest-banner__title - Banner title
  • .zest-banner__description - Banner description
  • .zest-banner__buttons - Button container
  • .zest-banner__buttons--split - Split layout container (v2.6.0+)
  • .zest-banner__buttons-group - Grouped buttons in split layout (v2.6.0+)

Buttons:

  • .zest-btn - Base button class
  • .zest-btn--primary - Primary action button (Accept All)
  • .zest-btn--secondary - Secondary action button (outlined, used in split-modern) (v2.6.0+)
  • .zest-btn--ghost - Tertiary button (Settings/Save)

Modal:

  • .zest-modal-overlay - Background overlay
  • .zest-modal - Modal container
  • .zest-modal__header - Modal header
  • .zest-modal__body - Modal body
  • .zest-modal__footer - Modal footer
  • .zest-modal__footer--split - Split layout footer (v2.6.0+)
  • .zest-modal__buttons-group - Grouped buttons in split layout (v2.6.0+)

Categories:

  • .zest-category - Category item
  • .zest-category__header - Category header
  • .zest-category__label - Category title
  • .zest-category__description - Category description
  • .zest-toggle - Toggle switch

Widget:

  • .zest-widget - Floating widget button

Custom Labels

Customize all UI text:

window.ZestConfig = {
  labels: {
    banner: {
      title: 'We value your privacy',
      description: 'We use cookies to enhance your browsing experience and analyze our traffic.',
      acceptAll: 'Accept',
      rejectAll: 'Decline',
      settings: 'Preferences'
    },
    modal: {
      title: 'Cookie Preferences',
      description: 'Manage your cookie preferences below.',
      save: 'Save',
      acceptAll: 'Accept All',
      rejectAll: 'Reject All'
    },
    widget: {
      label: 'Cookies'
    },
    categories: {
      essential: {
        title: 'Essential',
        description: 'Required for the website to function properly.'
      },
      functional: {
        title: 'Functional',
        description: 'Remember your preferences and settings.'
      },
      analytics: {
        title: 'Analytics',
        description: 'Help us understand how visitors use our site.'
      },
      marketing: {
        title: 'Marketing',
        description: 'Used to deliver relevant advertisements.'
      }
    }
  }
};

Examples

Minimal Dark Theme

window.ZestConfig = {
  theme: 'dark',
  position: 'bottom-right',
  accentColor: '#10b981',
  customStyles: `
    .zest-banner {
      border: 1px solid var(--zest-border);
    }
    .zest-btn {
      font-size: 14px;
    }
  `
};

Corporate Style

window.ZestConfig = {
  theme: 'light',
  position: 'bottom',
  accentColor: '#1e40af',
  customStyles: `
    :host {
      --zest-radius: 4px;
      --zest-radius-sm: 2px;
    }
    .zest-banner {
      border-top: 3px solid var(--zest-accent);
    }
    .zest-btn {
      font-family: 'Inter', sans-serif;
      text-transform: uppercase;
      font-size: 12px;
      letter-spacing: 0.1em;
    }
  `
};

Playful Style

window.ZestConfig = {
  theme: 'auto',
  position: 'bottom-left',
  accentColor: '#f97316',
  customStyles: `
    :host {
      --zest-radius: 24px;
      --zest-radius-sm: 12px;
    }
    .zest-banner {
      box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
    }
    .zest-btn--primary {
      border-radius: 9999px;
      padding: 12px 24px;
    }
  `
};

Hiding the Widget

Disable the floating widget:

window.ZestConfig = {
  showWidget: false
};

You can still provide a way for users to change preferences:

<button onclick="Zest.showSettings()">Cookie Settings</button>