country-flag-emoji-polyfill

Restores color country flag emojis on Chromium browsers under Windows by injecting a tiny web font only when needed.

Library
npm
v0.1.10
229stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
42/100Fair
Development Activity40
Maintenance8
Community44
Maturity56
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
58/100Fair
Architecture70
Code Quality50
Innovation55
Learning Curve55

Recent Windows releases finally support color emojis natively, but Windows (and by extension every Chromium-based browser — Chrome, Edge, Brave) still does not render country flag emojis. Instead of a flag, users see a two-letter region code like “CH”. country-flag-emoji-polyfill fixes this with a single function call: it detects whether the browser supports color emojis but not country flags, and if so, injects a <style> tag that loads a subsetted web font scoped to exactly the country-flag unicode range via unicode-range, so it never affects any other character on the page.

The library is deliberately minimal — 0.7kB gzipped with zero runtime dependencies — and the 77kB font asset is only downloaded by browsers that actually need it, via a CDN-hosted .woff2 file. It ships as both an ESM and CJS build with TypeScript types, and is maintained by TalkJS, a chat API/UI vendor that uses it in production and sponsors its upkeep.

What You Get

  • A single polyfillCountryFlagEmojis() function that does feature detection and font injection in one call
  • A canvas-based emoji-support detector (supportsEmoji) that renders a glyph to a 1x1 canvas and compares colors to determine if it rendered as a real color emoji
  • A pre-built, subsetted “Twemoji Country Flags” WOFF2 font (77kB) containing only the glyphs needed for flag emojis, hosted on a CDN and lazy-loaded
  • A unicode-range-scoped @font-face injection so the fallback font never interferes with any other character on the page
  • Both ESM (dist/index.mjs) and CJS (dist/index.cjs) builds with bundled TypeScript type definitions
  • A no-build-tool usage path via a plain <script type="module"> tag served from the Skypack CDN

Common Use Cases

  • Web apps with country selectors or locale pickers that render flag emojis and need them to look right for Windows Chrome/Edge users
  • Chat and messaging products (its original use case at TalkJS) where users send flag emojis in conversations
  • E-commerce or SaaS dashboards showing country/region indicators next to user or currency data
  • Any site whose CSS already lists a color-emoji font stack and wants a drop-in fix for the Windows Chromium flag gap without extra tooling

Under The Hood

Architecture The library is two small TypeScript modules with a clean separation of concerns: src/emoji.ts owns feature detection (supportsEmoji), rendering a test glyph to a 1x1 canvas in both black and white fill and comparing the resulting pixel colors to infer whether the browser rendered a real color emoji or a fallback glyph; src/index.ts owns the side effect, calling that detector for a plain emoji and a flag emoji, and if the gap is confirmed, appending a <style> element with an @font-face rule scoped via unicode-range to just the flag codepoints. There is no state, no build-time configuration beyond two optional function parameters, and nothing would meaningfully change if the core abstraction changed — it is a single-purpose runtime check plus a single DOM mutation.

Tech Stack Written in TypeScript with zero runtime dependencies. Built with unbuild (unbuild --minify) into dual ESM/CJS output plus .d.ts types, matching modern npm dual-package conventions declared via the exports map in package.json. The only devDependencies are unbuild and nodemon (for a dev watch script). The accompanying WOFF2 font asset is generated out-of-band by a shell script (build/make-font.sh) that downloads the Twemoji Mozilla font and subsets it with Python’s fonttools/pyftsubset to just the flag-emoji unicode ranges, then that font is published to and served from a CDN (jsDelivr) rather than bundled into the npm package payload consumers execute.

Code Quality No automated test suite or CI configuration exists in the repository — correctness relies on manual verification and the small, easily-reasoned-about surface area of the code. What is there is clean: strict TypeScript typing throughout, no any usage in the reviewed source, small single-purpose functions, and unusually thorough inline comments explaining non-obvious browser behavior (e.g. why font-display: swap is used despite its downsides, and how the canvas-based color comparison avoids false positives from partially-transparent fallback glyphs).

API Design The public API is a single function with two optional parameters (fontName, fontUrl) and a boolean return value, requiring no configuration object, no initialization step, and no framework integration — call it once and it either injects a style tag or does nothing. Documentation is concentrated in the README with copy-pasteable snippets for both the npm and no-build-tool paths, and the required CSS change (prefixing font-family with the polyfill’s font name) is explained with a concrete before/after example, keeping the total integration effort at two small edits.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search