react-country-flag, react-flags, and react-world-flags are React components designed to render country flags using ISO country codes. They solve the common problem of displaying localized indicators without managing large asset bundles manually. react-country-flag focuses on performance by using emoji fonts by default and offering SVGs as an opt-in feature. react-flags provides a lightweight wrapper around flag icon sets, often relying on external CSS or SVG imports. react-world-flags is a dedicated SVG renderer that pulls vector assets directly, ensuring crisp scaling at any size but potentially increasing bundle weight if not tree-shaken correctly.
Displaying country flags seems simple until you consider bundle size, rendering consistency, and accessibility. The three main contendersโreact-country-flag, react-flags, and react-world-flagsโtake fundamentally different approaches to solving this. Let's break down how they work under the hood and when to use each.
The core difference lies in how these libraries draw the flag. This choice impacts your bundle size, load time, and visual consistency across devices.
react-country-flag defaults to Emoji rendering.
// react-country-flag: Default emoji mode
import ReactCountryFlag from 'react-country-flag';
// Renders ๐บ๐ธ using system font
<ReactCountryFlag countryCode="US" />
react-world-flags uses Inline SVGs.
<svg> element.// react-world-flags: Pure SVG mode
import Flag from 'react-world-flags';
// Renders a crisp <svg> element
<Flag code="US" style={{ width: '24px', height: '24px' }} />
react-flags often acts as a Wrapper.
// react-flags: Class-based or asset wrapper
import ReactFlags from 'react-flags';
// Might render an <img> or a <div> with a background class
<ReactFlags country="US" className="my-custom-flag" />
Bundle size is the hidden cost of flag libraries. Including 200+ country assets can bloat your JavaScript bundle significantly.
react-country-flag is the lightest option.
// react-country-flag: Optimized for lists
// Zero network request, instant paint
{countries.map(c => (
<ReactCountryFlag key={c.code} countryCode={c.code} />
))}
react-world-flags requires careful bundler configuration.
// react-world-flags: Ensure tree-shaking works
// Check your bundle analyzer to confirm unused codes are removed
<Flag code={dynamicCode} />
react-flags varies by implementation.
// react-flags: Potential network latency
// Each new country might trigger a fetch if not preloaded
<ReactFlags country={dynamicCountry} />
How much control do you have over the look and feel?
react-country-flag offers limited styling in emoji mode.
fontSize to scale the emoji, but you cannot recolor parts of the flag.// react-country-flag: SVG mode for custom colors
<ReactCountryFlag
countryCode="FR"
svg
style={{ fill: '#333', width: '32px' }}
/>
react-world-flags provides full SVG access.
// react-world-flags: Full CSS control
<Flag
code="DE"
className="hover:opacity-80 transition-opacity"
style={{ width: '100%', height: 'auto' }}
/>
react-flags depends on the underlying asset.
react-world-flags but might need to dig into the DOM structure.// react-flags: Filter-based customization
<ReactFlags
country="JP"
style={{ filter: 'grayscale(100%)' }}
/>
Flags are images, but screen readers need text descriptions.
react-country-flag handles accessibility automatically.
title prop that becomes the aria-label or tooltip.title.// react-country-flag: Accessible by default
<ReactCountryFlag
countryCode="CA"
title="Canada"
aria-label="Canada"
/>
react-world-flags requires manual aria management.
role="img" and a <title> element inside to be accessible.// react-world-flags: Manual accessibility props
<Flag
code="GB"
title="United Kingdom"
aria-label="United Kingdom"
role="img"
/>
react-flags varies.
<img>, you need an alt tag.<div>, you need aria-label.// react-flags: Verify alt text support
<ReactFlags
country="AU"
alt="Australia"
/>
You are displaying a table with 100 rows, each having a user's country.
react-country-flag (Emoji mode)// High-performance list
{users.map(user => (
<tr key={user.id}>
<td><ReactCountryFlag countryCode={user.country} /></td>
<td>{user.name}</td>
</tr>
))}
You are building a printed report or a high-DPI dashboard where flags must look crisp at large sizes.
react-world-flags// High-fidelity display
<div className="dashboard-card">
<Flag code="US" style={{ width: '64px', height: '64px' }} />
<h3>Sales Performance</h3>
</div>
You are working in an environment with strict asset hosting policies and cannot use external CDNs or dynamic imports.
react-flags (or self-hosted SVGs)// Controlled asset loading
<ReactFlags
country="BR"
src="/assets/flags/br.svg"
/>
| Feature | react-country-flag | react-world-flags | react-flags |
|---|---|---|---|
| Default Render | Emoji (Text) | Inline SVG | Wrapper (Img/CSS) |
| Bundle Size | Tiny (Emoji) / Medium (SVG) | Medium/Large (Vector Data) | Variable |
| Visual Consistency | Low (OS Dependent) | High (Vector) | Medium (Asset Dependent) |
| Styling Control | Limited (Emoji) / High (SVG) | High (Full CSS) | Medium |
| Accessibility | Auto (with title) | Manual (ARIA props) | Manual (Alt/ARIA) |
| Best Use Case | Lists, Tables, Mobile | Dashboards, Print, Branding | Legacy, Custom Assets |
react-country-flag is the pragmatic choice for most web apps. It solves the "I need a flag next to this text" problem with zero friction. Start with emoji mode for speed, and toggle SVG mode only if design requirements demand it.
react-world-flags is the specialist tool for visual fidelity. If your application sells a premium feel or needs to support large-scale prints, the vector precision is worth the extra bundle bytes. Just keep an eye on your build size.
react-flags serves niche cases where you need to bridge a gap with existing infrastructure. If you already have a folder of flag assets or a specific CSS framework requirement, this wrapper saves you from writing boilerplate code.
Final Thought: Don't over-engineer flag rendering. For 90% of use cases, the emoji approach in react-country-flag is sufficient. Only reach for SVGs when the visual quality directly impacts user trust or brand perception.
Choose react-country-flag if performance and bundle size are your top priorities. It defaults to emoji rendering, which requires zero network requests and minimal JavaScript, making it ideal for lists, tables, or high-frequency renders. Switch to SVG mode only when you need specific styling or consistent rendering across older operating systems that lack emoji support.
Choose react-flags if you are already using a specific icon ecosystem or need a simple wrapper around existing flag assets. This package is suitable for projects where you want to manage the underlying asset source manually or integrate with a specific design system that provides its own flag set. Avoid it if you need a zero-config solution with built-in SVG optimization.
Choose react-world-flags if visual fidelity and scalability are critical, such as in dashboards, printed reports, or high-DPI displays. Since it renders pure SVGs, you get crisp edges at any size without relying on the user's OS font support. Be prepared to handle slightly larger bundle sizes or configure tree-shaking to include only the countries your app actually uses.
React component for emoji/svg country flags.
npm install --save react-country-flag
v3.x NONE only Typescript Types were introduced, enjoy!
v2.x has breaking changes
code is now countryCodetitle and aria-label are not defined any more, it is up to the developer
to pass these instyleProps is now styleAll props are passed onto the element, everything can be overwritten.
import React from "react"
import ReactCountryFlag from "react-country-flag"
function ExampleComponent {
return (
<div>
<ReactCountryFlag countryCode="US" />
<ReactCountryFlag
className="emojiFlag"
countryCode="US"
style={{
fontSize: '2em',
lineHeight: '2em',
}}
aria-label="United States"
/>
<ReactCountryFlag countryCode="US" svg />
<ReactCountryFlag
countryCode="US"
svg
style={{
width: '2em',
height: '2em',
}}
title="US"
/>
<ReactCountryFlag
countryCode="US"
svg
cdnUrl="https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/3.4.3/flags/1x1/"
cdnSuffix="svg"
title="US"
/>
</div>
)
}
export default ExampleComponent
Try this out and conditionally render your country flag https://github.com/danalloway/detect-emoji-support
MIT ยฉ danalloway