Skip to content

@tank/browser-polyfills

1.0.0
Skill

Description

Diagnose and fix browser compatibility issues in Next.js apps. Covers Safari/iOS Safari JS polyfills, CSS workarounds, Next.js polyfill config (App Router + Pages Router), browserslist, feature detection, and safe polyfill delivery.

Triggered by

polyfillSafari brokenworks in Chrome not SafariiOS Safari bugbrowserslistcross-browser
Download
Concerns Found
tank install @tank/browser-polyfills

Browser Polyfills for Next.js

Core Philosophy

  • Fix what's broken, not what's theoretical. Check caniuse before adding polyfills.
  • Load polyfills conditionally. Modern browsers should not pay for Safari's gaps.
  • Safari on iOS is the primary target. All iOS browsers use WebKit, so a Safari bug affects Chrome on iPhone too.
  • Prefer CSS workarounds over JavaScript polyfills when possible — zero runtime cost.
  • Never use polyfill.io — it was compromised in 2024. Self-host or use Cloudflare's mirror.

Quick-Start: Diagnosing What Broke

"My app works in Chrome but breaks in Safari"

  1. Open Safari DevTools (or WebKit Inspector on iOS via Mac)
  2. Check the Console for errors — note the API name
  3. Look up the API in references/safari-js-polyfills.md for the compatibility matrix
  4. If it's a CSS issue (layout, styling), check references/safari-css-workarounds.md
  5. Add the polyfill via instrumentation-client.ts (App Router) or _app.tsx (Pages Router)
  6. See references/nextjs-polyfill-config.md for configuration

"Dates show as Invalid Date on Safari"

Safari is strict about date string formats. new Date('2025-01-15') works in Chrome but can break in Safari without the T separator. -> See references/safari-react-bugs.md for safe patterns and date-fns usage.

"Input fields zoom the page on iOS"

Any <input> with font-size < 16px triggers iOS auto-zoom on focus. -> See references/safari-react-bugs.md for the CSS fix.

"100vh doesn't work right on iOS"

iOS Safari's dynamic address bar causes 100vh to include the hidden chrome. -> See references/safari-react-bugs.md for the layered CSS + JS fallback.

"I need to set up polyfills from scratch in Next.js"

-> See references/nextjs-polyfill-config.md for the full configuration guide.

Decision Trees

What to Polyfill

SymptomLikely CauseReference
JS error in Safari consoleMissing APIreferences/safari-js-polyfills.md
Layout broken on iOS onlyCSS gap / viewportreferences/safari-css-workarounds.md
Date shows NaN or InvalidDate parsingreferences/safari-react-bugs.md
Page zooms on input focusFont-size < 16pxreferences/safari-react-bugs.md
Scroll doesn't lock on modaliOS body overflow bugreferences/safari-react-bugs.md
Firefox-specific layout issueScrollbar / Houdinireferences/firefox-quirks.md
Bundle too largeUnnecessary polyfillsreferences/polyfill-delivery.md

Where to Add Polyfills in Next.js

RouterEntry PointWhen
App Routerinstrumentation-client.tsRuns before hydration — best for global polyfills
App RouterDynamic import() in useEffectHeavy polyfills needed by specific components only
Pages Routerimport '../polyfills' in _app.tsxTop-level import, runs before anything else
Either<Script strategy="beforeInteractive">External CDN polyfill scripts

How to Load Polyfills

StrategyWhen to UseBundle Impact
Static import in entry fileAlways-needed polyfills (requestIdleCallback)Always loaded
Dynamic import with feature detectionHeavy polyfills for older browsers onlyLoaded on demand
CDN script tagThird-party polyfill serviceExternal, cached
browserslist narrowingEliminate auto-injected polyfillsReduces bundle 10-15 KiB

Priority Polyfills for Safari (2026)

PriorityAPI / FeatureAction
CriticalrequestIdleCallbackAlways polyfill — Safari will never ship this
CriticalDate string parsingUse ISO 8601 with T separator, or use date-fns
CriticalInput zoom preventionCSS: font-size: 16px on inputs
Criticalpolyfill.io removalReplace with Cloudflare mirror or self-host
High-webkit-backdrop-filterAdd prefix alongside standard property
Highdvh / viewport heightLayered fallback: 100vh then 100dvh then JS
HighiOS scroll lockUse position: fixed pattern, not overflow: hidden
Mediumsmoothscroll-polyfillFor Safari < 15.4 smooth scroll support
MediumFirefox scrollbar stylingDual scrollbar-width + ::-webkit-scrollbar
LowTemporal APIDo not use — Safari has no timeline. Use date-fns

Reference Files

FileContents
references/safari-js-polyfills.mdJS API compatibility matrix, polyfill packages, feature detection code
references/safari-css-workarounds.mdCSS bugs, vendor prefixes, viewport units, sticky positioning
references/nextjs-polyfill-config.mdinstrumentation-client.ts, browserslist, SWC, App/Pages Router setup
references/safari-react-bugs.mdDate parsing, input zoom, 100vh, scroll lock, modal bugs, PWA issues
references/polyfill-delivery.mdpolyfill.io alternative, feature detection, bundle impact, security
references/firefox-quirks.mdScrollbar styling, Houdini gaps, FormData quirks, late feature support

Command Palette

Search packages, docs, and navigate Tank