Tree-shakeable, zero-dependency React flag components. 307 flags — 252 countries, 5 organizations, 50 US states + DC. One flag ≈ 2kB gzip. No postinstall, no public/ copying, no CSS import. Works on the web and in React Native / Expo.
- Docs & playground: https://flags.matterdevelopment.com/
- npm: https://www.npmjs.com/package/matter-flags
- Source: https://github.com/mbdev3/matter-flags
- Single
<Flag code="ma" />withcircle | rounded | squareshapes and pixel or CSS sizes <DuoFlag>fuses two flags: verticalsplit,diagonaltriangles, or overlappingstack- Direct per-flag imports for the smallest possible bundle (RSC-safe)
- Borders, drop shadows, and gloss gradients via inline styles — zero CSS files
- White
<FallbackFlag />for unknown codes (never crashes),role="img"+ labels built in - Case-insensitive codes with sensible aliases (
uk→ Union Jack,arab,africa) - Every flag also exports its raw
svgstring — React Native / Expo, data URIs,<img src>
pnpm add matter-flags
# npm install matter-flags | yarn add matter-flags | bun add matter-flagsRequires react ^18 || ^19. Zero runtime dependencies.
// 1. Easiest — code-split <Flag> (only the requested chunk loads)
import { Flag } from 'matter-flags';
<Flag code="ma" shape="circle" size={32} bordered dropShadow gradient="linear" />;
// 2. Smallest — direct import (only MA enters your bundle)
import MA from 'matter-flags/flags/ma';
<MA size={24} shape="circle" />;
// 3. Two flags, one badge
import { DuoFlag } from 'matter-flags';
<DuoFlag a="us" b="gb" layout="split" size={48} shape="circle" bordered />;import { Flag } from 'matter-flags' — client component. Loads the requested flag as a separate chunk (code-split), renders a correct-size placeholder while loading (no layout shift, SSR-safe).
| Prop | Type | Default | Description |
|---|---|---|---|
code |
string |
— | Case-insensitive code, e.g. "ma", "US", "us-tx", "eu" |
shape |
'circle' | 'rounded' | 'square' |
'rounded' |
rounded ≈ 18% radius |
size |
number | string |
24 |
Number = px, or any CSS size ("2rem", "100%") |
bordered |
boolean |
true |
1px outline |
borderColor |
string |
'rgba(0,0,0,0.15)' |
Any CSS color |
borderWidth |
number | string |
1 |
Number = px |
dropShadow |
boolean |
false |
Soft 0 1px 3px shadow |
gradient |
'none' | 'top-down' | 'linear' | 'circular' |
'none' |
Gloss overlay |
title |
string |
country name | Tooltip + accessible label |
fallback |
ReactNode |
white flag | Shown while the chunk loads |
className / style |
— | — | Passed to the wrapper |
Examples:
// Avatar
<Flag code="jp" shape="circle" size={40} bordered dropShadow />
// Flag + name row
<span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}>
<Flag code="br" shape="rounded" size={20} />
Brazil
</span>
// Custom border, no border-radius look via square
<Flag code="ch" shape="square" size={28} bordered borderColor="#000" borderWidth={2} />Every flag is its own module — ideal for lists, tables, and React Server Components (no client JS needed):
import MA from 'matter-flags/flags/ma';
import US from 'matter-flags/flags/us';
import USTX from 'matter-flags/flags/us-tx';
// Named imports also work and tree-shake:
import { MA, US, GB } from 'matter-flags/flags';Each module also exports the flag's raw artwork and name, so you can use it without React DOM at all (see React Native / Expo):
import MA, { svg, name } from 'matter-flags/flags/ma';
svg; // '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 24">…</svg>'
name; // 'Morocco'Same visual props as <Flag /> minus code/fallback:
// Language picker row (server component)
import FR from 'matter-flags/flags/fr';
<FR size={18} shape="circle" title="Français" />;import { DuoFlag } from 'matter-flags' — two flags in one badge. Same visual props as <Flag />, plus:
| Prop | Type | Default | Description |
|---|---|---|---|
a / b |
string |
— | Left/top-left/first and right/bottom-right/second codes |
layout |
'split' | 'diagonal' | 'stack' |
'split' |
split = left/right halves, diagonal = top-left/bottom-right triangles, stack = overlapping badges |
overlap |
number |
35 |
Overlap % for stack |
// The classic split circle
<DuoFlag a="us" b="gb" layout="split" size={96} shape="circle" bordered borderColor="#7a4a2b" borderWidth={3} dropShadow />
// Diagonal energies
<DuoFlag a="fr" b="ma" layout="diagonal" size={64} shape="circle" bordered />
// Versus / language-pair badge
<DuoFlag a="en" b="es" layout="stack" size={32} /> // (use real codes: gb/es, fr/ma…)import { FallbackFlag } from 'matter-flags' — plain white flag in any shape/size. Rendered automatically by <Flag /> and <DuoFlag /> for unknown codes; use directly for skeletons and empty states:
<FallbackFlag size={24} shape="circle" />Case-insensitive. uk/gb → Union Jack (gb-ukm); British nations (gb-sct, gb-wls, gb-nir) available directly; el → gr.
Organizations (short codes included): eu, un, nato, arab/arab-league, africa/african-union.
US states + DC: us-al … us-wy, us-dc (e.g. us-tx, us-ca, us-oh). No short aliases — al, ca, ar belong to Albania, Canada, Argentina. Mississippi is excluded: its 2020 flag is not public domain.
All 252 country codes
ad— Andorraae— United Arab Emiratesaf— Afghanistanag— Antigua and Barbudaai— Anguillaal— Albaniaam— Armeniaao— Angolaaq— Antarcticaar— Argentinaas— American Samoaat— Austriaau— Australiaaw— Arubaax— Åland Islandsaz— Azerbaijanba— Bosnia and Herzegovinabb— Barbadosbd— Bangladeshbe— Belgiumbf— Burkina Fasobg— Bulgariabh— Bahrainbi— Burundibj— Beninbl— Saint Barthélemybm— Bermudabn— Bruneibo— Boliviabq-bo— Bonairebq-sa— Sababq-se— Sint Eustatiusbr— Brazilbs— Bahamasbt— Bhutanbv— Bouvet Islandbw— Botswanaby— Belarusbz— Belizeca— Canadacc— Cocos Islandscd— Democratic Republic of Congocf— Central African Republiccg— Congoch— Switzerlandci— Côte d'Ivoireck— Cook Islandcl— Chilecm— Camerooncn— Chinaco— Colombiacr— Costa Ricacu— Cubacv— Cape Verdecw— Curaçaocx— Christmas Islandcy— Cypruscz— Czech Republicde— Germanydj— Djiboutidk— Denmarkdm— Dominicado— Dominican Republicdz— Algeriaec— Ecuadoree— Estoniaeg— Egypter— Eritreaes— Spainet— Ethiopiafi— Finlandfj— Fijifk— Falkland Islandsfm— Micronesia (Federated States of)fo— Faroe Islandfr— Francega— Gabongb-nir— Northern Irelandgb-sct— Scotlandgb-ukm— United Kingdomgb-wls— Walesgd— Grenadage— Georgiagf— French Guianagg— Guernseygh— Ghanagi— Gibraltargl— Greenlandgm— Gambiagn— Guineagp— Guadeloupegq— Equatorial Guineagr— Greecegs— South Georgia and the South Sandwich Islandsgt— Guatemalagu— Guamgw— Guinea-Bissaugy— Guyanahk— Hong Konghm— Heard Island and McDonald Islandshn— Hondurashr— Croatiaht— Haitihu— Hungaryid— Indonesiaie— Irelandim— Isle of Manin— Indiaio— British Indian Ocean Territoryiq— Iraqir— Iranis— Icelandit— Italyje— Jerseyjm— Jamaicajo— Jordanjp— Japanke— Kenyakg— Kyrgyzstankh— Cambodiaki— Kiribatikm— Comoroskn— Saint Kitts and Neviskp— Korea (the Democratic People's Republic of)kr— Korea (the Republic of)kw— Kuwaitky— Cayman Islandskz— Kazakhstanla— Lao People's Democratic Republic (the)lb— Lebanonlc— Saint Luciali— Liechtensteinlk— Sri Lankalr— Liberials— Lesotholt— Lithuanialu— Luxembourglv— Latvialy— Libyama— Moroccomc— Monacomd— Moldova (the Republic of)me— Montenegromf— Saint Martinmg— Madagascarmh— Marshall Islands (the)mk— North Macedoniaml— Malimm— Myanmarmn— Mongoliamo— Macaomp— Northern Mariana Islands (the)mq— Martiniquemr— Mauritaniams— Montserratmt— Maltamu— Mauritiusmv— Maldivesmw— Malawimx— Mexicomy— Malaysiamz— Mozambiquena— Namibianc— New Caledoniane— Nigernf— Norfolk Islandng— Nigeriani— Nicaraguanl— Netherlandsno— Norwaynp— Nepalnr— Naurunu— Niuenz— New Zealandom— Omanpa— Panamape— Perupf— French Polyesiapg— Papua New Guineaph— Philippines (the)pk— Pakistanpl— Polandpm— Saint Pierre and Miquelonpn— Pitcairnpr— Puerto Ricops— Palestine, State ofpt— Portugalpw— Palaupy— Paraguayqa— Qatarre— Réunionro— Romaniars— Serbiaru— Russian Federation (the)rw— Rwandasa— Saudi Arabiasb— Solomon Islandssc— Seychellessd— Sudan (the)se— Swedensg— Singaporesh— Saint Helena, Ascension Island, Traistan da Cunhasi— Sloveniasj— Svalbard, Jan Mayensk— Slovakiasl— Sierra Leonesm— San Marinosn— Senegalso— Somaliasr— Surinamess— South Sudanst— Sao Tome and Principesv— El Salvadorsx— Sint Maartensy— Syrian Arab Republic (the)sz— Eswatinitc— Turks and Caicos Islands (the)td— Chadtf— French Southern Territoriestg— Togoth— Thailandtj— Tajikistantk— Tokelautl— Timor-Lestetm— Turkmenistantn— Tunisiato— Tongatr— Turkeytt— Trinidad and Tobagotv— Tuvalutw— Taiwantz— Tanzania, the United Republic ofua— Ukraineug— Ugandaum— United States Minor Outlying Islands (the)us— United States of Americauy— Uruguayuz— Uzbekistanva— Holy Seevc— Saint Vincent and the Grenadinesve— Venezuela (Bolivarian Republic of)vg— Virgin Islands (British)vi— Virgin Islands (U.S.)vn— Vietnamvu— Vanuatuwf— Wallis and Futunaws— Samoaye— Yemenyt— Mayotteza— South Africazm— Zambiazw— Zimbabwe
All 5 organization codes
african-union— African Unionarab-league— Arab Leagueeu— European Unionnato— NATOun— United Nations
All 50 US state + DC codes
us-ak— Alaskaus-al— Alabamaus-ar— Arkansasus-az— Arizonaus-ca— Californiaus-co— Coloradous-ct— Connecticutus-dc— District of Columbiaus-de— Delawareus-fl— Floridaus-ga— Georgiaus-hi— Hawaiius-ia— Iowaus-id— Idahous-il— Illinoisus-in— Indianaus-ks— Kansasus-ky— Kentuckyus-la— Louisianaus-ma— Massachusettsus-md— Marylandus-me— Maineus-mi— Michiganus-mn— Minnesotaus-mo— Missourius-mt— Montanaus-nc— North Carolinaus-nd— North Dakotaus-ne— Nebraskaus-nh— New Hampshireus-nj— New Jerseyus-nm— New Mexicous-nv— Nevadaus-ny— New Yorkus-oh— Ohious-ok— Oklahomaus-or— Oregonus-pa— Pennsylvaniaus-ri— Rhode Islandus-sc— South Carolinaus-sd— South Dakotaus-tn— Tennesseeus-tx— Texasus-ut— Utahus-va— Virginiaus-vt— Vermontus-wa— Washingtonus-wi— Wisconsinus-wv— West Virginiaus-wy— Wyoming
The React components render HTML, so they don't run on native — but every flag module also exports its artwork as a plain svg string. Pair it with react-native-svg (npx expo install react-native-svg) and there is nothing else to add:
import { SvgXml } from 'react-native-svg';
import { svg, name } from 'matter-flags/flags/ma';
<SvgXml xml={svg} width={32} height={24} accessibilityLabel={name} />;svg is a complete, standalone <svg viewBox="0 0 32 24"> document — no wrapper needed, and it carries xmlns:xlink on the flags that require it. It has no intrinsic width/height, so you size it entirely with props.
Importing only svg/name leaves the React component behind. Bundled with esbuild, one flag is ~0.8kB with no react import at all, against ~4.8kB when you import the component. Any bundler that honours sideEffects: false (Vite/Rollup, webpack, esbuild) does this automatically; Metro's tree-shaking is still experimental, so a default Expo build may also carry the unused component wrapper — a few hundred bytes, and nothing that renders.
A reusable native component is a few lines:
// Flag.native.tsx
import { SvgXml } from 'react-native-svg';
export function Flag({ svg, name, size = 24, radius = 4 }) {
return (
<SvgXml
xml={svg}
width={size}
height={size * 0.75}
accessibilityLabel={name}
style={{ borderRadius: radius, overflow: 'hidden' }}
/>
);
}The same svg string also works anywhere a standalone SVG does — a data URI, an <img src>, or a server-side rasteriser:
import { svg } from 'matter-flags/flags/fr';
const href = `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`;- Every module ships with
'use client'.FlagFramecallsReact.useId(), which React'sreact-serverbuild does not provide, so a flag cannot render inside a Server Component itself — importing one from an RSC is fine and simply opens a client boundary. <Flag />,<DuoFlag />,<FallbackFlag />load chunks withuseEffect. On the server they render a correct-size placeholder, so there is no hydration mismatch or layout shift.- Direct imports (
matter-flags/flags/xx) stay the cheapest option for lists and tables: no loader map, nouseEffect, and the markup is in the SSR output.
sideEffects: false, ESM only, one module per flag.
| Usage | Cost |
|---|---|
import MA from 'matter-flags/flags/ma' |
~0.5kB gzip flag + ~1.4kB shared runtime (once) |
<Flag code="ma"> |
same, code-split per flag |
import { svg } from 'matter-flags/flags/ma' |
artwork only — no React, no shared runtime |
Core (matter-flags) |
~6kB gzip, zero flags bundled |
Seal-heavy flags (some US states, up to ~50kB gzip) cost what their artwork costs — you only pay for flags you import. pnpm size enforces the budget in CI.
Every flag renders role="img" with aria-label (country/organization name, or your title), and a matching title tooltip. Purely decorative? Hide it from assistive tech: <span aria-hidden="true"><Flag … /></span>.
- Countries: Yummygum flagpack-core (MIT) — see
NOTICE. Singlelsource, SVGO-optimized. - Organizations & US states: Wikimedia Commons, all verified Public Domain — see
assets/orgs/SOURCES.jsonandassets/states/SOURCES.json. - Brand icons on the docs site: SVGL.
pnpm install
pnpm build:flags # regenerate src/flags + README.md code tables
pnpm typecheck
pnpm build
pnpm sizeEdit
scripts/manual.template.md, notREADME.md— the code tables are generated byscripts/build-readme.mjs.
Docs site: pnpm --filter matter-flags-site dev → http://localhost:4321/.
MIT — Matter Development. Flag artwork remains under its original licenses (see NOTICE, assets/*/SOURCES.json).