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.