Back to blog
InspectionJanuary 1, 2024ยท 8 min read

Browser Compatibility Analysis: Will This Site Work Everywhere?

A practical Fusebox guide to browser compatibility analysis.

Browser Compatibility Analysis: Will This Site Work Everywhere?

Published: January 2024
Reading time: 8 minutes

Not all browsers are created equal. A site that works perfectly in Chrome might break in Safari or Internet Explorer. Here's how to detect compatibility issues, understand browser support, and ensure sites work for all users.

Why Browser Compatibility Matters

  • Chrome has 65% market share - But that leaves 35% on other browsers
  • Safari is 19% - Especially high on mobile (50%+ iOS)
  • Corporate users - Often stuck on old Edge/IE
  • International markets - Different browser preferences
  • Feature availability - Not all browsers support everything

Quick Compatibility Check

1. Feature Detection Script

// Comprehensive browser feature detection
(function browserCompatCheck() {
  const features = {
    // Modern JavaScript
    'ES6 Arrow Functions': () => {
      try { eval('() => {}'); return true; } 
      catch(e) { return false; }
    },
    'ES6 Classes': () => {
      try { eval('class Test {}'); return true; } 
      catch(e) { return false; }
    },
    'Async/Await': () => {
      try { eval('async function test() { await 1; }'); return true; } 
      catch(e) { return false; }
    },
    'Optional Chaining': () => {
      try { eval('const x = {}; x?.y'); return true; } 
      catch(e) { return false; }
    },
    
    // Browser APIs
    'Service Workers': 'serviceWorker' in navigator,
    'WebRTC': 'RTCPeerConnection' in window,
    'WebSocket': 'WebSocket' in window,
    'LocalStorage': 'localStorage' in window,
    'IndexedDB': 'indexedDB' in window,
    'Geolocation': 'geolocation' in navigator,
    'Notifications': 'Notification' in window,
    'WebGL': (() => {
      const canvas = document.createElement('canvas');
      return !!(canvas.getContext('webgl') || canvas.getContext('experimental-webgl'));
    })(),
    
    // CSS Features
    'CSS Grid': CSS.supports('display', 'grid'),
    'CSS Flexbox': CSS.supports('display', 'flex'),
    'CSS Variables': CSS.supports('--test', '1'),
    'CSS Sticky': CSS.supports('position', 'sticky'),
    
    // Media
    'WebP Images': (() => {
      const canvas = document.createElement('canvas');
      canvas.width = 1;
      canvas.height = 1;
      return canvas.toDataURL('image/webp').indexOf('image/webp') === 0;
    })(),
    'AVIF Images': (() => {
      const img = new Image();
      return img.decode !== undefined;
    })()
  };
  
  console.log('๐ŸŒ Browser Compatibility Report\n');
  
  // Browser info
  console.log('Browser:', navigator.userAgent);
  console.log('Platform:', navigator.platform);
  console.log('Language:', navigator.language);
  
  console.log('\n๐Ÿ“‹ Feature Support:');
  Object.entries(features).forEach(([feature, supported]) => {
    const isSupported = typeof supported === 'function' ? supported() : supported;
    console.log(`${isSupported ? 'โœ…' : 'โŒ'} ${feature}`);
  });
})();

2. CSS Feature Detection

// Check CSS compatibility
function checkCSSSupport() {
  const cssFeatures = {
    // Layout
    'Grid': 'display: grid',
    'Flexbox': 'display: flex',
    'Subgrid': 'grid-template-columns: subgrid',
    
    // Modern features
    'Container Queries': 'container-type: inline-size',
    'Cascade Layers': '@layer',
    'Aspect Ratio': 'aspect-ratio: 1',
    'Gap in Flexbox': 'gap: 1rem',
    
    // Visual effects
    'Backdrop Filter': 'backdrop-filter: blur(10px)',
    'Mix Blend Mode': 'mix-blend-mode: multiply',
    'Clip Path': 'clip-path: circle(50%)',
    'CSS Filters': 'filter: blur(5px)',
    
    // Animations
    'CSS Animations': 'animation: test 1s',
    'CSS Transitions': 'transition: all 0.3s',
    'Transform 3D': 'transform: translateZ(0)',
    
    // Variables
    'Custom Properties': '--test: 1',
    'env() variables': 'padding: env(safe-area-inset-top)'
  };
  
  console.log('\n๐ŸŽจ CSS Feature Support:');
  
  Object.entries(cssFeatures).forEach(([name, declaration]) => {
    let supported = false;
    
    if (declaration.startsWith('@')) {
      // At-rule detection
      try {
        const style = document.createElement('style');
        style.textContent = `${declaration} test { }`;
        document.head.appendChild(style);
        supported = style.sheet.cssRules.length > 0;
        style.remove();
      } catch(e) {
        supported = false;
      }
    } else {
      // Property detection
      const [prop, value] = declaration.split(':').map(s => s.trim());
      supported = CSS.supports(prop, value);
    }
    
    console.log(`${supported ? 'โœ…' : 'โŒ'} ${name}`);
  });
}

checkCSSSupport();

Browser Detection

1. Detailed Browser Info

// Get comprehensive browser information
function getBrowserInfo() {
  const ua = navigator.userAgent;
  const info = {
    browser: 'Unknown',
    version: 'Unknown',
    engine: 'Unknown',
    os: 'Unknown',
    device: 'Desktop'
  };
  
  // Browser detection
  if (ua.includes('Chrome') && !ua.includes('Edg')) {
    info.browser = 'Chrome';
    info.version = ua.match(/Chrome\/(\d+)/)?.[1];
    info.engine = 'Blink';
  } else if (ua.includes('Safari') && !ua.includes('Chrome')) {
    info.browser = 'Safari';
    info.version = ua.match(/Version\/(\d+)/)?.[1];
    info.engine = 'WebKit';
  } else if (ua.includes('Firefox')) {
    info.browser = 'Firefox';
    info.version = ua.match(/Firefox\/(\d+)/)?.[1];
    info.engine = 'Gecko';
  } else if (ua.includes('Edg')) {
    info.browser = 'Edge';
    info.version = ua.match(/Edg\/(\d+)/)?.[1];
    info.engine = 'Blink';
  } else if (ua.includes('Trident')) {
    info.browser = 'Internet Explorer';
    info.version = ua.match(/rv:(\d+)/)?.[1];
    info.engine = 'Trident';
  }
  
  // OS detection
  if (ua.includes('Windows')) info.os = 'Windows';
  else if (ua.includes('Mac')) info.os = 'macOS';
  else if (ua.includes('Linux')) info.os = 'Linux';
  else if (ua.includes('Android')) info.os = 'Android';
  else if (ua.includes('iOS')) info.os = 'iOS';
  
  // Device type
  if (ua.includes('Mobile')) info.device = 'Mobile';
  else if (ua.includes('Tablet')) info.device = 'Tablet';
  
  return info;
}

const browserInfo = getBrowserInfo();
console.log('\n๐Ÿ–ฅ๏ธ Browser Details:', browserInfo);

2. Feature-Based Detection

// Detect browser by features (more reliable)
function detectBrowserByFeatures() {
  const detection = {
    isChrome: !!(window.chrome && window.chrome.webstore),
    isFirefox: typeof InstallTrigger !== 'undefined',
    isSafari: /constructor/i.test(window.HTMLElement) || 
              window.safari?.pushNotification?.toString() === '[object SafariRemoteNotification]',
    isEdge: window.navigator.userAgent.includes('Edg'),
    isIE: /*@cc_on!@*/false || !!document.documentMode,
    isOpera: !!window.opr || !!window.opera || navigator.userAgent.includes('OPR/')
  };
  
  console.log('\n๐Ÿ” Feature-based Browser Detection:');
  Object.entries(detection).forEach(([browser, detected]) => {
    if (detected) console.log(`โœ… ${browser}`);
  });
  
  return detection;
}

Compatibility Issues Detection

1. JavaScript Compatibility

// Check for potential JS issues
function checkJavaScriptCompat() {
  console.log('\nโš ๏ธ JavaScript Compatibility Issues:');
  
  const scripts = Array.from(document.scripts);
  const issues = [];
  
  scripts.forEach(script => {
    if (!script.src) return;
    
    // Check for modern syntax that might break
    fetch(script.src)
      .then(r => r.text())
      .then(code => {
        // Check for ES6+ features
        const modernFeatures = {
          'Arrow functions': /=>/,
          'Template literals': /`[^`]*\${[^}]*}[^`]*`/,
          'Destructuring': /const\s*{[^}]+}\s*=/,
          'Async/Await': /async\s+function|await\s+/,
          'Optional chaining': /\?\./,
          'Nullish coalescing': /\?\?/,
          'Class syntax': /class\s+\w+/
        };
        
        Object.entries(modernFeatures).forEach(([feature, regex]) => {
          if (regex.test(code)) {
            issues.push({
              script: script.src.split('/').pop(),
              feature,
              browsers: getBrowserSupport(feature)
            });
          }
        });
      })
      .catch(() => {});
  });
  
  setTimeout(() => {
    if (issues.length > 0) {
      console.table(issues);
    } else {
      console.log('No obvious compatibility issues found');
    }
  }, 2000);
}

function getBrowserSupport(feature) {
  const support = {
    'Arrow functions': 'IE 11 โŒ',
    'Template literals': 'IE 11 โŒ',
    'Async/Await': 'IE 11 โŒ, Safari < 10.1 โŒ',
    'Optional chaining': 'Safari < 13.1 โŒ, Firefox < 74 โŒ',
    'Class syntax': 'IE 11 โŒ'
  };
  
  return support[feature] || 'Check caniuse.com';
}

2. CSS Compatibility Issues

// Detect CSS that might not work everywhere
function checkCSSCompat() {
  console.log('\n๐ŸŽจ CSS Compatibility Check:');
  
  const stylesheets = Array.from(document.styleSheets);
  const issues = new Set();
  
  stylesheets.forEach(sheet => {
    try {
      const rules = Array.from(sheet.cssRules || []);
      
      rules.forEach(rule => {
        if (!rule.style) return;
        
        // Check for modern CSS
        const modernCSS = {
          'CSS Grid': /display:\s*grid/,
          'CSS Variables': /var\(--/,
          'Flexbox gap': /gap:/,
          'Aspect ratio': /aspect-ratio:/,
          'Clamp()': /clamp\(/,
          'Logical properties': /margin-inline|padding-block/
        };
        
        const cssText = rule.cssText;
        Object.entries(modernCSS).forEach(([feature, regex]) => {
          if (regex.test(cssText)) {
            issues.add(feature);
          }
        });
      });
    } catch(e) {
      // Cross-origin stylesheets
    }
  });
  
  if (issues.size > 0) {
    console.log('Modern CSS features used:');
    issues.forEach(feature => {
      console.log(`  โš ๏ธ ${feature} - Check browser support`);
    });
  }
}

Polyfill Detection

1. Check for Polyfills

// Detect what polyfills are loaded
function detectPolyfills() {
  console.log('\n๐Ÿ”ง Polyfill Detection:');
  
  const polyfills = {
    'Promise': window.Promise?._polyfill,
    'Fetch': window.fetch?._polyfill,
    'Object.assign': Object.assign?._polyfill,
    'Array.from': Array.from?._polyfill,
    'IntersectionObserver': window.IntersectionObserver?._polyfill,
    'ResizeObserver': window.ResizeObserver?._polyfill,
    'CustomEvent': window.CustomEvent?._polyfill
  };
  
  // Check for polyfill.io
  const hasPolyfillIO = Array.from(document.scripts).some(s => 
    s.src.includes('polyfill.io')
  );
  
  if (hasPolyfillIO) {
    console.log('โœ… Polyfill.io detected');
  }
  
  // Check for core-js
  if (window.core) {
    console.log('โœ… Core-js polyfills detected');
  }
  
  // Check for specific polyfills
  Object.entries(polyfills).forEach(([feature, isPolyfilled]) => {
    if (isPolyfilled) {
      console.log(`โœ… ${feature} polyfilled`);
    }
  });
  
  // Check for babel runtime
  if (window._babelPolyfill || window.regeneratorRuntime) {
    console.log('โœ… Babel polyfills detected');
  }
}

Browser-Specific Issues

1. Safari Quirks

// Check for Safari-specific issues
function checkSafariIssues() {
  if (!detectBrowserByFeatures().isSafari) return;
  
  console.log('\n๐Ÿฆ Safari-Specific Checks:');
  
  const safariIssues = {
    'Date parsing': () => {
      // Safari is strict with date formats
      try {
        new Date('2024-01-01 00:00:00'); // Fails in Safari
        return false;
      } catch {
        return true;
      }
    },
    'Regex lookbehind': () => {
      try {
        new RegExp('(?<=test)');
        return false;
      } catch {
        return true;
      }
    },
    'WebP support': () => {
      // Older Safari doesn't support WebP
      const canvas = document.createElement('canvas');
      canvas.width = 1;
      canvas.height = 1;
      return !canvas.toDataURL('image/webp').includes('webp');
    }
  };
  
  Object.entries(safariIssues).forEach(([issue, test]) => {
    if (test()) {
      console.log(`โš ๏ธ ${issue} - Potential issue`);
    }
  });
}

2. Mobile Browser Detection

// Mobile-specific compatibility
function checkMobileCompat() {
  const isMobile = /Mobile|Android|iPhone|iPad/i.test(navigator.userAgent);
  
  if (!isMobile) return;
  
  console.log('\n๐Ÿ“ฑ Mobile Compatibility:');
  
  // Touch support
  console.log(`Touch events: ${'ontouchstart' in window ? 'โœ…' : 'โŒ'}`);
  console.log(`Pointer events: ${'PointerEvent' in window ? 'โœ…' : 'โŒ'}`);
  
  // Viewport
  const viewport = document.querySelector('meta[name="viewport"]');
  console.log(`Viewport meta: ${viewport ? 'โœ…' : 'โŒ Missing!'}`);
  
  // iOS specific
  if (/iPhone|iPad/i.test(navigator.userAgent)) {
    console.log('\niOS Specific:');
    console.log(`Standalone mode: ${window.navigator.standalone ? 'Yes' : 'No'}`);
    
    // Check for iOS viewport issues
    if (viewport && !viewport.content.includes('viewport-fit=cover')) {
      console.log('โš ๏ธ Missing viewport-fit=cover for iPhone X+ notch');
    }
  }
  
  // Check for hover-dependent features
  const hasHover = window.matchMedia('(hover: hover)').matches;
  if (!hasHover) {
    console.log('โš ๏ธ No hover support - check hover-dependent UI');
  }
}

Performance by Browser

Browser Performance Analysis

// Compare performance across browsers
function analyzeBrowserPerformance() {
  console.log('\nโšก Browser Performance Analysis:');
  
  const metrics = {
    'DOM Ready': performance.timing.domContentLoadedEventEnd - performance.timing.navigationStart,
    'Page Load': performance.timing.loadEventEnd - performance.timing.navigationStart,
    'First Paint': performance.getEntriesByType('paint')[0]?.startTime || 'Not supported',
    'Memory Used': performance.memory?.usedJSHeapSize 
      ? `${(performance.memory.usedJSHeapSize / 1048576).toFixed(2)} MB` 
      : 'Not supported'
  };
  
  console.table(metrics);
  
  // Browser-specific optimizations
  const browserInfo = getBrowserInfo();
  
  console.log('\n๐Ÿ’ก Browser-Specific Recommendations:');
  
  if (browserInfo.browser === 'Safari') {
    console.log('Safari: Consider will-change CSS carefully (memory issues)');
  } else if (browserInfo.browser === 'Firefox') {
    console.log('Firefox: Great DevTools for performance profiling');
  } else if (browserInfo.browser === 'Chrome') {
    console.log('Chrome: Use Coverage tab to find unused CSS/JS');
  }
}

Compatibility Testing Checklist

// Comprehensive compatibility audit
(function fullCompatibilityAudit() {
  console.log('๐Ÿ” Full Browser Compatibility Audit\n');
  
  // 1. Browser detection
  const browser = getBrowserInfo();
  console.log('1๏ธโƒฃ Browser:', `${browser.browser} ${browser.version}`);
  
  // 2. Feature support summary
  const criticalFeatures = {
    'Service Workers': 'serviceWorker' in navigator,
    'Fetch API': 'fetch' in window,
    'CSS Grid': CSS.supports('display', 'grid'),
    'IntersectionObserver': 'IntersectionObserver' in window,
    'WebP Images': document.createElement('canvas').toDataURL('image/webp').includes('webp')
  };
  
  console.log('\n2๏ธโƒฃ Critical Features:');
  let supported = 0;
  Object.entries(criticalFeatures).forEach(([feature, isSupported]) => {
    console.log(`${isSupported ? 'โœ…' : 'โŒ'} ${feature}`);
    if (isSupported) supported++;
  });
  
  const score = (supported / Object.keys(criticalFeatures).length * 100).toFixed(0);
  console.log(`\nCompatibility Score: ${score}%`);
  
  // 3. Recommendations
  console.log('\n3๏ธโƒฃ Recommendations:');
  if (score < 80) {
    console.log('โš ๏ธ Consider adding polyfills for missing features');
  }
  if (!criticalFeatures['CSS Grid']) {
    console.log('โš ๏ธ Provide flexbox fallback for layout');
  }
  if (!criticalFeatures['WebP Images']) {
    console.log('โš ๏ธ Serve JPEG/PNG fallbacks for images');
  }
  
  // 4. Test other functions
  checkMobileCompat();
  detectPolyfills();
  analyzeBrowserPerformance();
})();

The Bottom Line

Browser compatibility affects:

  • User reach - Don't exclude users on different browsers
  • Feature availability - Not everything works everywhere
  • Performance - Different browsers = different speeds
  • Maintenance - Polyfills and fallbacks need updates
  • Testing complexity - More browsers = more testing

Build progressively. Enhance for modern browsers. Support the basics everywhere.


Check browser compatibility instantly: Fusebox detects browser features, compatibility issues, and polyfills while you browse. Know what works where. $29 one-time purchase.