Vanilla JS

@geoicons/vanilla brings GeoIcons to plain HTML and JavaScript with no framework required. Add data-geoicon to placeholder elements, register the icons you want to use, then call createGeoIcons() to replace each placeholder with a live <svg>. The package is fully tree-shakeable, so only registered icons are included in your bundle, while all visual styling is handled entirely through CSS.

Browser-only. Since it creates real DOM nodes, it requires document and runs in the browser. No framework peer dependencies are required.

Install

npm install @geoicons/vanilla

Use

Mark up placeholders with data-geoicon="<code>", then register the icons you use:

<i data-geoicon="us" class="flag"></i>
<i data-geoicon="jp" class="flag" aria-label="Japan"></i>

<nav>
  <i data-geoicon="africa"></i>
</nav>
import { createGeoIcons, Us, Jp } from '@geoicons/vanilla/countries';
import { Africa } from '@geoicons/vanilla/areas';

createGeoIcons({ us: Us, jp: Jp, africa: Africa });

Each <i data-geoicon="us"> is replaced by that icon's <svg>. Call createGeoIcons again after injecting new DOM (SPA route change, htmx swap) to hydrate fresh nodes. Options:

createGeoIcons(icons, {
  attr: 'data-geoicon',
  root: document,
});

The { us: Us } map is what keeps the bundle small: because you statically import { Us }, the bundler ships only that icon. An icon referenced in markup but never registered simply won't render, which is exactly what stops the whole catalog from being pulled in. Elements whose key isn't in the map are left untouched.

Styling: all CSS

Icons render at 24px by default with stroke-width="1", stroke="currentColor", and fill="none". These are standard SVG presentation attributes that can be overridden with CSS. Since CSS takes precedence, you can fully customize an icon's appearance using classes or inline styles.

.flag {
  width: 32px;
  height: 32px;
  color: #4f46e5; /* stroke follows currentColor */
  stroke-width: 1.5;
}

.flag:hover {
  color: crimson;
}

/* filled shape */
.solid {
  fill: currentColor;
}
Want to changeCSS property
sizewidth / height
colorcolor (via currentColor) or stroke
stroke weightstroke-width
fillfill

Accessibility

Icons are decorative by default (aria-hidden="true"). Add aria-label to the placeholder to make one meaningful: the <svg> gets role="img", a <title>, and aria-labelledby automatically:

<!-- decorative, skipped by screen readers -->
<i data-geoicon="us"></i>

<!-- announced -->
<i data-geoicon="us" aria-label="United States"></i>

License

If you're using GeoIcons with a commercial product, register your license once (before calling createGeoIcons). It verifies your commercial license key fully offline and waives the GPLv3 requirement, allowing use in proprietary applications under your commercial license.

import { initGeoiconsLicense } from '@geoicons/vanilla';

initGeoiconsLicense(process.env.GEOICONS_KEY);

initGeoiconsLicense resolves with the status ('commercial' | 'gpl' | 'unverified' | 'invalid') so you can reflect it in your own UI. Open-source projects can pass the GPL declaration string to silence the notice. See Licensing for more details.