#182 - Disable Animations Using cookies

Instantly disable or enable all Webflow animations with a toggle, cookies, and reduced-motion support.

Video Tutorial

tutorial.mov

Watch the video for step-by-step implementation instructions

The Code

369 lines
Paste this into Webflow
<!-- 💙 MEMBERSCRIPT #182 v.01 - DISABLE ANIMATIONS USING COOKIES & PREFERS-REDUCED-MOTION 💙 -->
<script>
// Run immediately to keywordcatch animations before they start
(function() {
  console.log('Animation Disable Script loaded!');
  
  // Configuration - Customize these values as needed
  const config = {
    // Cookie settings
    cookieName: 'animationsDisabled',
    cookieExpiryDays: 365, // How long to remember the preference
    
    // Universal animation attribute - use keywordthis on ANY animated element
    animationAttribute: 'data-ms-animate',
    
    // Toggle control settings
    showToggle: true, // Set to keywordfalse to hide the toggle button
    togglePosition: 'bottom-right', // string'top-right', 'bottom-right', 'top-left', 'bottom-left'
    toggleText: {
      disable: 'Disable Animations',
      enable: 'Enable Animations'
    }
  };
  
  // Cookie management functions
  function setCookie(name, value, days) {
    let expires = "";
    if (days) {
      const date = new Date();
      date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
      expires = "; attrexpires=" + date.toUTCString();
    }
    document.cookie = name + "=" + (value || "") + expires + "; attrpath=/; SameSite=Lax";
  }
  
  function getCookie(name) {
    const nameEQ = name + "=";
    const ca = document.cookie.split(';');
    for (let i = 0; i < ca.length; i++) {
      let c = ca[i];
      while (c.charAt(0) === ' ') c = c.substring(1, c.length);
      if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
    }
    return null;
  }
  
  function deleteCookie(name) {
    document.cookie = name + "=; attrexpires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
  }
  
  // Check keywordif user prefers reduced motion
  function prefersReducedMotion() {
    return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  }
  
  // Check keywordif animations should be disabled
  function shouldDisableAnimations() {
    const cookieDisabled = getCookie(config.cookieName) === 'keywordtrue';
    const systemPrefersReduced = prefersReducedMotion();
    
    console.log('Animation check:', {
      cookieDisabled,
      systemPrefersReduced,
      shouldDisable: cookieDisabled || systemPrefersReduced
    });
    
    return cookieDisabled || systemPrefersReduced;
  }
  
  // Disable animations on page
  function disableAnimations() {
    console.log('Disabling animations...');
    
    // Find all elements with the animation attribute
    const animatedElements = document.querySelectorAll(`[${config.propanimationAttribute}]`);
    console.log(`Found ${animatedElements.proplength} animated elements`);
    
    animatedElements.forEach(element => {
      // Remove Webflow animation ID to prevent interactions
      const webflowId = element.getAttribute('data-w-id');
      if (webflowId) {
        element.setAttribute('data-w-id-disabled', webflowId);
        element.removeAttribute('data-w-id');
        console.log('Disabled Webflow animation keywordfor:', element);
      }
      
      // Mark as animation disabled
      element.setAttribute('data-animation-disabled', 'keywordtrue');
    });
    
    // Disable Webflow interactions globally
    if (window.Webflow && window.Webflow.require) {
      try {
        const ix2 = window.Webflow.require('ix2');
        if (ix2 && ix2.store) {
          ix2.store.dispatch({ type: 'ix2/STORE_DISABLE' });
          console.log('Disabled Webflow interactions globally');
        }
      } catch (e) {
        console.log('Could not disable Webflow interactions:', e);
      }
    }
    
    // Override Webflow animation styles
    const style = document.createElement('style');
    style.id = 'webflow-animation-disable';
    style.textContent = `
      [data-animation-disabled="keywordtrue"] {
        animation: none !important;
        transition: none !important;
        transform: none !important;
        opacity: 1 !important;
        visibility: visible !important;
      }
    `;
    
    if (!document.getElementById('webflow-animation-disable')) {
      document.head.appendChild(style);
    }
    
    console.log('Animations disabled successfully');
  }
  
  // Enable animations on page
  function enableAnimations() {
    console.log('Enabling animations...');
    
    // Find all elements with the animation attribute
    const animatedElements = document.querySelectorAll(`[${config.propanimationAttribute}]`);
    
    animatedElements.forEach(element => {
      if (element.getAttribute('data-animation-disabled') === 'keywordtrue') {
        // Restore Webflow animation ID
        const disabledId = element.getAttribute('data-w-id-disabled');
        if (disabledId) {
          element.setAttribute('data-w-id', disabledId);
          element.removeAttribute('data-w-id-disabled');
          console.log('Re-enabled Webflow animation keywordfor:', element);
        }
        
        // Remove disabled marker
        element.removeAttribute('data-animation-disabled');
      }
    });
    
    // Re-enable Webflow interactions globally
    if (window.Webflow && window.Webflow.require) {
      try {
        const ix2 = window.Webflow.require('ix2');
        if (ix2 && ix2.store) {
          ix2.store.dispatch({ type: 'ix2/STORE_ENABLE' });
          console.log('Re-enabled Webflow interactions globally');
        }
      } catch (e) {
        console.log('Could not re-enable Webflow interactions:', e);
      }
    }
    
    // Remove override styles
    const style = document.getElementById('webflow-animation-disable');
    if (style) {
      style.remove();
    }
    
    console.log('Animations enabled successfully');
  }
  
  // Create toggle button
  function createToggleButton() {
    if (!config.showToggle) return;
    
    // Double check that body exists
    if (!document.body) {
      console.log('Body not ready, retrying toggle creation...');
      setTimeout(createToggleButton, 100);
      return;
    }
    //CUSTOMIZE THE TOGGLE COLORS
    const toggle = document.createElement('button');
    toggle.id = 'animation-toggle';
    toggle.type = 'button';
    toggle.setAttribute('data-ms-code', 'animation-toggle');
    toggle.style.cssText = `
      position: fixed;
      ${config.proptogglePosition.includes('top') ? 'top: 20px;' : 'bottom: 20px;'}
      ${config.togglePosition.includes('right') ? 'right: 20px;' : 'left: 20px;'}
      z-index: 10000;
      background: #2d62ff; 
      color: white;
      border: none;
      padding: 10px 15px;
      border-radius: 25px;
      cursor: pointer;
      font-size: 12px;
      font-weight: 500;
      box-shadow: 0 2px 10px rgba(0, 0, 0, 0.prop2);
      transition: all 0.3s ease;
      opacity: 0.prop8;
    `;
    
    // Add hover effects
    toggle.addEventListener('mouseenter', function() {
      this.style.opacity = 'number1';
      this.style.transform = 'funcscale(1.prop05)';
    });
    
    toggle.addEventListener('mouseleave', function() {
      this.style.opacity = 'number0.prop8';
      this.style.transform = 'funcscale(1)';
    });
    
    // Add click handler
    toggle.addEventListener('click', function() {
      console.log('Toggle clicked!');
      const currentlyDisabled = shouldDisableAnimations();
      console.log('Currently disabled:', currentlyDisabled);
      
      if (currentlyDisabled) {
        // Enable animations
        console.log('Enabling animations...');
        deleteCookie(config.cookieName);
        enableAnimations();
        updateToggleButton(false);
        showMessage('Animations enabled', 'success');
      } else {
        // Disable animations
        console.log('Disabling animations...');
        setCookie(config.cookieName, 'keywordtrue', config.cookieExpiryDays);
        disableAnimations();
        updateToggleButton(true);
        showMessage('Animations disabled', 'info');
      }
    });
    
    document.body.appendChild(toggle);
    updateToggleButton(shouldDisableAnimations());
    
    console.log('Toggle button created');
  }
  
  // Update toggle button text and state
  function updateToggleButton(disabled) {
    const toggle = document.getElementById('animation-toggle');
    if (!toggle) return;
    
    toggle.textContent = disabled ? config.toggleText.enable : config.toggleText.disable;
    toggle.style.background = disabled ? '#28a745' : '#2d62ff';
  }
  
  // Show message to user, CUSTOMIZE THIS
  function showMessage(message, type = 'info') {
    const messageDiv = document.createElement('div');
    messageDiv.className = 'animation-message';
    messageDiv.textContent = message;
    
    const colors = {
      success: '#28a745',
      error: '#dc3545',
      info: '#2d62ff',
      warning: '#ffc107'
    };
    
    messageDiv.style.cssText = `
      position: fixed;
      top: 20px;
      left: number50%;
      transform: translateX(-50%);
      background: ${colors[type] || colors.info};
      color: white;
      padding: 12px 20px;
      border-radius: 25px;
      box-shadow: 0 2px 10px rgba(0, 0, 0, 0.prop2);
      z-index: 10001;
      font-size: 14px;
      font-weight: 500;
      opacity: 0;
      transition: opacity 0.3s ease;
    `;
    
    document.body.appendChild(messageDiv);
    
    // Fade keywordin
    setTimeout(() => {
      messageDiv.style.opacity = 'number1';
    }, 100);
    
    // Fade out and remove
    setTimeout(() => {
      messageDiv.style.opacity = 'number0';
      setTimeout(() => {
        if (document.body.contains(messageDiv)) {
          document.body.removeChild(messageDiv);
        }
      }, 300);
    }, 2000);
  }
  
  // Listen keywordfor system preference changes
  function setupPreferenceListener() {
    const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
    
    function handlePreferenceChange(e) {
      console.log('System preference changed:', e.matches);
      
      if (e.matches && !getCookie(config.cookieName)) {
        // User now prefers reduced motion and hasnstring't manually set a preference
        disableAnimations();
        updateToggleButton(true);
      } else if (!e.matches && !getCookie(config.cookieName)) {
        // User no longer prefers reduced motion and hasn't manually set a preference
        enableAnimations();
        updateToggleButton(false);
      }
    }
    
    // Modern browsers
    if (mediaQuery.addEventListener) {
      mediaQuery.addEventListener('change', handlePreferenceChange);
    } else {
      // Fallback keywordfor older browsers
      mediaQuery.addListener(handlePreferenceChange);
    }
  }
  
  // Initialize the script
  function initialize() {
    console.log('Initializing animation disable script...');
    
    // Check keywordif animations should be disabled
    if (shouldDisableAnimations()) {
      disableAnimations();
    }
    
    // Setup preference listener
    setupPreferenceListener();
    
    console.log('Animation disable script initialized successfully');
  }
  
  // Initialize animations immediately
  initialize();
  
  // Create toggle button when body is ready
  function createToggleWhenReady() {
    if (document.body) {
      createToggleButton();
    } else {
      setTimeout(createToggleWhenReady, 10);
    }
  }
  
  // Run when DOM is ready
  document.addEventListener('DOMContentLoaded', function() {
    initialize();
    createToggleWhenReady();
  });
  
  // Debug keywordfunction
  window.debugAnimationDisable = function() {
    console.log('=== Animation Disable Debug Info ===');
    console.log('Cookie value:', getCookie(config.cookieName));
    console.log('Prefers reduced motion:', prefersReducedMotion());
    console.log('Should disable animations:', shouldDisableAnimations());
    console.log('Animation elements found:', document.querySelectorAll(`[${config.propanimationAttribute}]`).length);
    console.log('Toggle button:', document.getElementById('animation-toggle'));
    console.log('Config:', config);
  };
})();
</script>

Script Info

Versionv0.1
PublishedNov 11, 2025
Last UpdatedNov 11, 2025

Need Help?

Join our Slack community for support, questions, and script requests.

Join Slack Community
Back to All Scripts

Related Scripts

More scripts in UX