Cross-browser testing ensures your site works for all users. Firefox, Chrome, Safari, and Edge all render the same HTML/CSS/JS differently in edge cases. This guide covers what to test, how to test it efficiently, and Firefox-specific quirks.
Why Cross-Browser Testing Still Matters
Despite web standards, browsers differ:
- CSS rendering: different default stylesheets, rounding behavior, font metrics
- JavaScript: different optimization strategies, timing behavior
- Web APIs: different implementations of newer APIs, prefixed properties
- Form elements: completely different native styling
- Scrollbar width: varies, affects layout calculations
- Input behavior: cursor position, selection behavior
The most common issue: "It works in Chrome but not Firefox" — because Chrome is the most-tested browser.
Essential Firefox Checks
CSS Specifics
/* Scrollbar styling: Firefox uses these */
.scrollable {
scrollbar-width: thin;
scrollbar-color: #6B7280 transparent;
}
/* Chrome uses ::-webkit-scrollbar (non-standard) */
.scrollable::-webkit-scrollbar { width: 6px; }
.scrollable::-webkit-scrollbar-thumb { background: #6B7280; }
/* The correct cross-browser approach: both */
Form Styling
Firefox renders <input> and <select> differently than Chrome. Reset styles:
input, select, textarea, button {
/* Normalize across browsers */
font: inherit;
-webkit-appearance: none;
appearance: none;
border-radius: 0; /* Firefox adds rounding to some inputs */
}
/* Firefox-specific: number input arrows */
input[type=number]::-moz-inner-spin-button,
input[type=number]::-moz-outer-spin-button {
-moz-appearance: none;
}
Flexbox/Grid Differences
Most flex/grid differences are now resolved, but check:
-
gapin flex (Firefox supported earlier than Chrome) -
subgrid(Firefox supported earlier) -
text-overflow: ellipsisin flex items (may needmin-width: 0)
/* Fix: text truncation in flex items */
.flex-item {
min-width: 0; /* Allows flex item to shrink below content size */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
position: sticky Issues
/* Make sticky work correctly */
.sticky-header {
position: sticky;
top: 0;
z-index: 10;
/* Parent must not have overflow: hidden or overflow: auto */
}
/* Check: parent containers for overflow */
/* overflow: hidden on a parent breaks sticky positioning */
Firefox-Specific Testing
Privacy Enhancements
Firefox's Total Cookie Protection and Enhanced Tracking Protection can affect:
- Third-party cookie-based features
- Cross-origin embedded widgets that rely on cookies
- CDN-served resources that are on tracking blocklists
Test your site in Firefox Strict mode (Settings → Privacy → Strict) to see what breaks.
CSS :focus-visible
Firefox implements :focus-visible (show focus ring only for keyboard navigation):
/* Correct approach */
button:focus-visible {
outline: 2px solid blue;
outline-offset: 2px;
}
button:focus:not(:focus-visible) {
outline: none; /* No ring for mouse clicks */
}
Firefox vs Chrome may differ in when :focus-visible activates.
<dialog> Element
Firefox 98+ supports the native <dialog> element:
<dialog id="modal">
<form method="dialog">
<button type="submit">Close</button>
</form>
</dialog>
dialog.showModal(); // Opens with backdrop
dialog.close(); // Closes
The native dialog handles: focus trap, escape key, backdrop, ::backdrop pseudo-element. Test across browsers for styling consistency.
Testing Strategies
BrowserStack and Sauce Labs
Commercial services provide real browsers on real OS/device combinations:
- Test on actual Firefox 120 on Windows 10
- Test on Safari 16.6 on real macOS
- Test on Chrome on Android 13
Free alternatives:
- BrowserStack free tier: limited sessions
- LambdaTest: similar to BrowserStack
Local Testing Setup
Use Docker for quick cross-browser testing:
# Firefox in Docker
docker run -it --rm \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
selenium/standalone-firefox
Playwright for Automated Cross-Browser Tests
// playwright.config.js
import { defineConfig } from '@playwright/test';
export default defineConfig({
projects: [
{ name: 'Firefox', use: { ...devices['Firefox'] } },
{ name: 'Chromium', use: { ...devices['Chromium'] } },
{ name: 'WebKit', use: { ...devices['WebKit'] } }, // Safari engine
],
});
// Cross-browser test
test('form submission works', async ({ page }) => {
await page.goto('https://example.com/form');
await page.fill('#email', 'test@example.com');
await page.click('button[type="submit"]');
await expect(page.locator('.success')).toBeVisible();
});
Playwright runs the same test in Firefox, Chrome, and Safari automatically.
Chrome DevTools Protocol → Firefox Debugging Protocol
Note: Firefox uses its own Remote Debugging Protocol, not CDP (Chrome DevTools Protocol). Tools written for CDP may not work directly with Firefox — use Playwright/Selenium which abstract the difference.
Quick Browser Compatibility Checklist
Before shipping:
□ Tested in latest Firefox and Firefox ESR
□ Tested in latest Chrome/Edge
□ Tested in Safari (real macOS if possible)
□ Tested with keyboard-only navigation
□ Tested with screen reader (NVDA on Windows + Firefox)
□ Tested with uBlock Origin active (Firefox + uBlock)
□ Tested with Firefox ETP Strict mode
□ console.log() outputs reviewed (no errors in any browser)
□ Network panel checked for 4xx/5xx errors
□ Responsive design checked in Firefox Responsive Mode
Firefox-Specific Debugging
When something works in Chrome but not Firefox:
- Open Firefox DevTools Console — any JavaScript errors?
- Inspector → check computed styles — any differences?
- Network panel — any blocked requests (ETP)?
- Check
about:configfor any non-default settings affecting the behavior - Test in Firefox Safe Mode (Help → Restart with Add-ons Disabled) — extension issue?
Top comments (0)