Browser Compatibility
Sightline supports all modern browsers. This guide details browser requirements, known issues, and polyfills.
Supported Browsers
Desktop Browsers
| Browser | Minimum Version | Status |
|---|---|---|
| Chrome | 90+ | ✅ Full Support |
| Firefox | 90+ | ✅ Full Support |
| Safari | 14+ | ✅ Full Support |
| Edge | 90+ | ✅ Full Support |
| Opera | 76+ | ✅ Full Support |
Mobile Browsers
| Browser | Minimum Version | Status |
|---|---|---|
| Chrome (Android) | 90+ | ✅ Full Support |
| Safari (iOS) | 14+ | ✅ Full Support |
| Samsung Internet | 14+ | ✅ Full Support |
| Firefox (Android) | 90+ | ✅ Full Support |
Not Supported
| Browser | Reason |
|---|---|
| Internet Explorer | End of life, no WebGL 2 |
| Legacy Edge (EdgeHTML) | Replaced by Chromium Edge |
| Opera Mini | No JavaScript execution |
Feature Requirements
Required Features
Sightline requires these browser features:
| Feature | Usage | Can I Use |
|---|---|---|
| WebGL 2.0 | Map rendering | caniuse.com/webgl2 |
| ES2020 | JavaScript features | caniuse.com/es2020 |
| CSS Custom Properties | Theming | caniuse.com/css-variables |
| Flexbox | Layout | caniuse.com/flexbox |
| CSS Grid | Layout | caniuse.com/css-grid |
| Fetch API | Data loading | caniuse.com/fetch |
| LocalStorage | Theme persistence | caniuse.com/localstorage |
Optional Features
These features enhance the experience but aren't required:
| Feature | Usage | Fallback |
|---|---|---|
| Geolocation API | "Near me" feature | Manual location entry |
| ResizeObserver | Responsive components | Window resize event |
| IntersectionObserver | Lazy loading | Load all images |
| Web Workers | Background processing | Main thread processing |
Checking Browser Support
Runtime Check
export function checkBrowserSupport(): { supported: boolean; issues: string[] } {
const issues: string[] = [];
// Check WebGL 2
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl2');
if (!gl) {
issues.push('WebGL 2.0 is not supported');
}
// Check CSS Custom Properties
if (!CSS.supports('color', 'var(--test)')) {
issues.push('CSS Custom Properties are not supported');
}
// Check Fetch API
if (typeof fetch === 'undefined') {
issues.push('Fetch API is not supported');
}
// Check localStorage
try {
localStorage.setItem('test', 'test');
localStorage.removeItem('test');
} catch {
issues.push('LocalStorage is not available');
}
return {
supported: issues.length === 0,
issues,
};
}Display Warning
'use client';
import { useEffect, useState } from 'react';
import { checkBrowserSupport } from '@/lib/browser-support';
export function BrowserWarning() {
const [issues, setIssues] = useState<string[]>([]);
useEffect(() => {
const { supported, issues } = checkBrowserSupport();
if (!supported) {
setIssues(issues);
}
}, []);
if (issues.length === 0) return null;
return (
<div className="fixed top-0 inset-x-0 bg-yellow-500 text-yellow-900 p-4 z-50">
<p className="font-semibold">Your browser may not fully support this application:</p>
<ul className="list-disc list-inside mt-2">
{issues.map((issue) => (
<li key={issue}>{issue}</li>
))}
</ul>
<p className="mt-2">Please use a modern browser like Chrome, Firefox, Safari, or Edge.</p>
</div>
);
}Known Issues
Safari
Safari has some specific behaviors to be aware of.
Issue: Date input shows different format
Workaround: Use a custom date picker component
Issue: WebGL memory limits stricter
Workaround: Reduce max zoom level for very large datasets
Issue: 100vh doesn't account for browser chrome on iOS
Workaround: Use dvh units or JavaScript calculation
/* Fix iOS viewport height */
.full-height {
height: 100vh;
height: 100dvh;
}Firefox
Issue: Slightly different scrollbar styling
Workaround: Use CSS scrollbar properties
/* Firefox scrollbar styling */
* {
scrollbar-width: thin;
scrollbar-color: hsl(var(--muted)) transparent;
}Edge
No known issues specific to Edge (Chromium-based).
Mobile Browsers
Issue: Touch events may interfere with map gestures
Workaround: Sightline handles this automatically
Issue: Virtual keyboard affects viewport
Workaround: Use visualViewport API
useEffect(() => {
const viewport = window.visualViewport;
if (viewport) {
const handleResize = () => {
document.documentElement.style.setProperty(
'--viewport-height',
`${viewport.height}px`
);
};
viewport.addEventListener('resize', handleResize);
return () => viewport.removeEventListener('resize', handleResize);
}
}, []);Polyfills
Sightline includes minimal polyfills. For older browsers, you may need to add:
ResizeObserver
npm install resize-observer-polyfillimport ResizeObserver from 'resize-observer-polyfill';
if (typeof window !== 'undefined' && !window.ResizeObserver) {
window.ResizeObserver = ResizeObserver;
}IntersectionObserver
npm install intersection-observerimport 'intersection-observer';WebGL Support
Mapbox GL requires WebGL. Here's how to handle devices without support:
Check WebGL Support
export function hasWebGLSupport(): boolean {
try {
const canvas = document.createElement('canvas');
return !!(
window.WebGLRenderingContext &&
(canvas.getContext('webgl') || canvas.getContext('experimental-webgl'))
);
} catch {
return false;
}
}Fallback UI
function MapContainer() {
const [hasWebGL, setHasWebGL] = useState(true);
useEffect(() => {
setHasWebGL(hasWebGLSupport());
}, []);
if (!hasWebGL) {
return (
<div className="h-full flex items-center justify-center bg-muted">
<div className="text-center p-8">
<h2 className="text-xl font-semibold">Map Unavailable</h2>
<p className="text-muted-foreground mt-2">
Your browser doesn't support WebGL, which is required for the map.
</p>
<p className="mt-4">
<a href="/incidents" className="text-primary underline">
View incidents as a list instead
</a>
</p>
</div>
</div>
);
}
return <MapEngine ... />;
}Performance by Browser
General performance characteristics:
| Browser | Rendering | Memory | Battery |
|---|---|---|---|
| Chrome | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ |
| Firefox | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| Safari | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| Edge | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ |
Safari typically offers the best battery efficiency on macOS/iOS. Chrome offers the best developer tools for debugging.
Testing Across Browsers
Local Testing
Use these tools to test across browsers:
- BrowserStack — Cloud-based cross-browser testing
- Playwright — Automated testing (Chrome, Firefox, Safari)
- Safari Technology Preview — Test upcoming Safari features
Automated Testing
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
{ name: 'mobile-chrome', use: { ...devices['Pixel 5'] } },
{ name: 'mobile-safari', use: { ...devices['iPhone 12'] } },
],
});