react-country-flag and vue-country-flag-next are specialized components designed to render country flags efficiently in modern web applications. react-country-flag is a lightweight React component that supports rendering flags as either SVGs or emojis, offering features like automatic lazy loading and responsive sizing. vue-country-flag-next serves the Vue 3 ecosystem, providing a similar declarative interface to display flags using ISO country codes, with a focus on performance and ease of integration into the Composition API.
When adding country flags to a web application, developers often face a choice between using raw image assets, CSS sprites, or dedicated components. react-country-flag and vue-country-flag-next solve this problem for their respective ecosystems by wrapping the complexity of flag rendering into simple, declarative components. While they share the same goal, their implementation details reflect the specific strengths and patterns of React and Vue.
Both libraries offer two primary modes for displaying flags: Scalable Vector Graphics (SVG) and Emoji. The choice between these modes impacts bundle size, visual fidelity, and cross-platform consistency.
react-country-flag allows you to toggle between these modes using a simple prop. When using SVG, it fetches the vector file on demand. When using emoji, it renders the text character, which relies on the user's operating system font.
// react-country-flag: Rendering modes
import ReactCountryFlag from "react-country-flag";
// SVG Mode: Crisp vectors, larger bundle if not optimized
<ReactCountryFlag countryCode="US" svg />
// Emoji Mode: Tiny bundle, depends on OS font support
<ReactCountryFlag countryCode="US" emoji />
vue-country-flag-next follows a similar pattern but adapts the syntax to Vue's binding system. It defaults to SVG for high-quality rendering but supports emoji for lightweight implementations.
<!-- vue-country-flag-next: Rendering modes -->
<script setup>
import VueCountryFlagNext from 'vue-country-flag-next';
</script>
<!-- SVG Mode: High fidelity -->
<vue-country-flag-next country="US" format="svg" />
<!-- Emoji Mode: Low footprint -->
<vue-country-flag-next country="US" format="emoji" />
Handling images in web performance is critical. Loading dozens of flag icons can trigger a waterfall of network requests if not managed correctly. Both packages address this, but their approaches differ slightly due to framework capabilities.
react-country-flag includes built-in lazy loading for SVGs. It does not request the image file until the component mounts or becomes visible. This prevents unnecessary network traffic for flags that are off-screen.
// react-country-flag: Automatic lazy loading
// The SVG for 'FR' is only fetched when this component renders
<ReactCountryFlag countryCode="FR" svg />
// You can also force eager loading if the flag is above the fold
<ReactCountryFlag countryCode="DE" svg loadAfterMount={false} />
vue-country-flag-next relies on Vue's reactivity system to manage rendering. While it optimizes the SVG usage, the explicit lazy-loading behavior found in the React counterpart is often handled by the developer using Vue's native <Suspense> or intersection observers if strict control is needed. The component itself focuses on efficient reactive updates.
<!-- vue-country-flag-next: Reactive updates -->
<template>
<!-- The flag updates automatically when 'currentCountry' changes -->
<vue-country-flag-next :country="currentCountry" format="svg" />
</template>
<script setup>
import { ref } from 'vue';
import VueCountryFlagNext from 'vue-country-flag-next';
const currentCountry = ref('JP');
</script>
Flags often need to fit into complex layouts, such as data tables, navigation bars, or user profiles. Both components provide props to handle sizing, but they integrate with their framework's styling conventions differently.
react-country-flag accepts standard React style objects or className props. It allows you to set a specific size or let it fill its container. The SVG mode scales naturally without losing quality.
// react-country-flag: Styling
<ReactCountryFlag
countryCode="GB"
svg
style={{ width: '2em', height: 'auto' }}
className="rounded-sm shadow-sm"
/>
vue-country-flag-next uses Vue's binding syntax for styles and classes. It supports the same responsive behavior, ensuring that flags look sharp on high-DPI screens when using the SVG format.
<!-- vue-country-flag-next: Styling -->
<vue-country-flag-next
country="CA"
format="svg"
:style="{ width: '2em', height: 'auto' }"
class="rounded-sm shadow-sm"
/>
In dynamic applications, country codes often change based on user selection or data fetching. How each library handles these updates reflects the underlying reactivity model of its framework.
react-country-flag relies on React's reconciliation process. When the countryCode prop changes, React re-renders the component, and the library handles swapping the underlying image source or emoji character efficiently.
// react-country-flag: Handling state changes
function CountrySelector({ code }) {
return (
<div>
<p>Selected: {code}</p>
<ReactCountryFlag countryCode={code} svg />
</div>
);
}
vue-country-flag-next leverages Vue's fine-grained reactivity. When the bound country property updates, Vue triggers the minimal necessary DOM updates. This is particularly useful in lists where only one flag might change at a time.
<!-- vue-country-flag-next: Handling state changes -->
<template>
<div>
<p>Selected: {{ code }}</p>
<vue-country-flag-next :country="code" format="svg" />
</div>
</template>
<script setup>
import { ref } from 'vue';
const code = ref('IT');
</script>
Despite targeting different frameworks, these libraries share several core philosophies and features:
Both packages use the ISO 3166-1 alpha-2 standard (e.g., "US", "FR", "JP") as the primary input. This ensures consistency across different parts of an application and makes it easy to integrate with backend APIs that also use these codes.
// Both use the same 2-letter codes
// React
<ReactCountryFlag countryCode="BR" />
// Vue
<vue-country-flag-next country="BR" />
Both libraries understand the importance of accessibility. They allow developers to add titles or aria-labels to ensure screen readers can identify the country being displayed, rather than just reading "image" or the emoji character.
// React: Title prop adds a tooltip and accessibility label
<ReactCountryFlag countryCode="US" svg title="United States" />
<!-- Vue: Title prop works similarly -->
<vue-country-flag-next country="US" format="svg" title="United States" />
Neither package requires you to import a massive CSS file containing hundreds of flag classes. They render the graphics directly (SVG) or use system fonts (Emoji), keeping your global styles clean and reducing the risk of style conflicts.
| Feature | react-country-flag | vue-country-flag-next |
|---|---|---|
| Framework | ⚛️ React | 🟢 Vue 3 |
| Primary Prop | countryCode | country |
| Mode Prop | svg / emoji (boolean/prop) | format ("svg" / "emoji") |
| Lazy Loading | Built-in (loadAfterMount) | Managed via Vue reactivity |
| Styling | style object / className | :style binding / class |
| Reactivity | React Reconciliation | Vue Fine-grained Reactivity |
react-country-flag is a mature, "batteries-included" solution for React developers. Its built-in lazy loading and straightforward boolean props make it incredibly fast to implement. It abstracts away the performance pitfalls of loading many images, making it safe to drop into large lists or tables without extra configuration.
vue-country-flag-next is the go-to choice for the Vue 3 ecosystem. It mirrors the functionality of its React counterpart but feels native to Vue. Its use of the format prop and standard Vue bindings makes it easy to compose with other Vue components. It is ideal for projects that rely on Vue's reactivity system for dynamic data dashboards or internationalization switches.
Final Thought: The decision here is rarely about feature parity, as both libraries solve the same problem effectively. The choice is strictly dictated by your framework. If you are in React, react-country-flag is the definitive standard. If you are in Vue 3, vue-country-flag-next provides the same level of polish and performance tailored to your stack.
Choose react-country-flag if you are building an application with React. It is the standard choice for this ecosystem, offering a simple API that handles both SVG and emoji rendering modes. Select this package when you need a zero-config solution that automatically manages image loading states and supports responsive design without extra CSS.
Choose vue-country-flag-next if your project is built on Vue 3. This package is specifically maintained for the Vue 3 composition API and ensures compatibility with the latest Vue reactivity system. It is the ideal choice when you need a native Vue component that avoids React dependencies while providing reliable flag rendering via SVG or emoji.
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