<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rushan</title>
    <description>The latest articles on DEV Community by Rushan (@rushan123).</description>
    <link>https://dev.to/rushan123</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F316291%2F178e59ff-4dcf-4a4b-baf9-27600b6ebc07.png</url>
      <title>DEV Community: Rushan</title>
      <link>https://dev.to/rushan123</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rushan123"/>
    <language>en</language>
    <item>
      <title>Make your icons follow dark mode automatically with currentColor</title>
      <dc:creator>Rushan</dc:creator>
      <pubDate>Thu, 16 Jul 2026 15:00:00 +0000</pubDate>
      <link>https://dev.to/rushan123/make-your-icons-follow-dark-mode-automatically-with-currentcolor-5ed5</link>
      <guid>https://dev.to/rushan123/make-your-icons-follow-dark-mode-automatically-with-currentcolor-5ed5</guid>
      <description>&lt;p&gt;Most icon sets bake a color into the SVG. The fill is set to &lt;code&gt;#111&lt;/code&gt; in the file, so the icon looks right on a white page and then disappears the moment you switch to a dark background. You end up passing a color prop to every icon, or writing theme-specific overrides for each one.&lt;/p&gt;

&lt;p&gt;GeoIcons take the other approach. Each icon draws its outline with &lt;code&gt;stroke="currentColor"&lt;/code&gt;, so it reads the CSS &lt;code&gt;color&lt;/code&gt; of whatever wraps it. Set the text color for your light and dark themes once, and every icon on the page follows along:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Jp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Fr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;De&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@geoicons/react/countries&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;EuropeanUnionEu&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@geoicons/react/areas&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// None of these set a color. They all inherit the text color of the wrapper.&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-slate-900 dark:text-slate-100"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Jp&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; 
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Fr&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; 
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;De&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; 
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;EuropeanUnionEu&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every GeoIcon draws with &lt;code&gt;stroke="currentColor"&lt;/code&gt;, so it inherits the CSS &lt;code&gt;color&lt;/code&gt; of its parent.&lt;/li&gt;
&lt;li&gt;To support dark mode, set &lt;code&gt;color&lt;/code&gt; for each theme in CSS. You never touch the icon.&lt;/li&gt;
&lt;li&gt;A Tailwind class like &lt;code&gt;dark:text-slate-100&lt;/code&gt; works directly on the icon or on any ancestor.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What does currentColor do?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;currentColor&lt;/code&gt; is a CSS keyword that means "the computed value of this element's &lt;code&gt;color&lt;/code&gt; property." A GeoIcon sets &lt;code&gt;stroke="currentColor"&lt;/code&gt; on its &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt;, so the outline paints in whatever &lt;code&gt;color&lt;/code&gt; the icon inherits. Change the &lt;code&gt;color&lt;/code&gt; anywhere up the tree, and the stroke changes with it.&lt;/p&gt;

&lt;p&gt;That is the whole mechanism. There is no theme context, no provider, no color prop threaded through your components. The icon is a piece of text as far as color is concerned.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#e11d48&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Fr&lt;/span&gt; &lt;span class="na"&gt;aria-hidden&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; France
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;&amp;lt;Fr /&amp;gt;&lt;/code&gt; outline turns rose because it inherits &lt;code&gt;color: #e11d48&lt;/code&gt; from the paragraph.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do hardcoded icon colors break in dark mode?
&lt;/h2&gt;

&lt;p&gt;An icon with a fixed &lt;code&gt;fill="#111827"&lt;/code&gt; in its SVG cannot respond to a theme. Dark mode flips your background to near-black, and the icon stays near-black on top of it, so it vanishes. Your only fixes are to override the fill per theme or swap in a second icon file for dark backgrounds.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;currentColor&lt;/code&gt; removes that work. The icon holds no color, so there is nothing to override. You style the container, and the icon inherits the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I switch icons for a dark theme?
&lt;/h2&gt;

&lt;p&gt;Pick the color for each theme and let the icon inherit it. If you toggle dark mode with a class on &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; (the common pattern in Tailwind and most CSS setups), scope the &lt;code&gt;color&lt;/code&gt; to that class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#0f172a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* slate-900 for light mode */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.dark&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#e2e8f0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* slate-200 for dark mode */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every icon under &lt;code&gt;&amp;lt;html class="dark"&amp;gt;&lt;/code&gt; now paints in &lt;code&gt;#e2e8f0&lt;/code&gt;. With Tailwind you can skip the CSS and put the two colors on the icon itself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;De&lt;/span&gt;
  &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-slate-900 dark:text-slate-100"&lt;/span&gt;
  &lt;span class="na"&gt;aria-label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Germany"&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;text-*&lt;/code&gt; utilities set &lt;code&gt;color&lt;/code&gt;, and the icon's &lt;code&gt;currentColor&lt;/code&gt; stroke picks it up. One element, both themes.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I follow the system setting instead?
&lt;/h2&gt;

&lt;p&gt;Read the operating system preference with the &lt;code&gt;prefers-color-scheme&lt;/code&gt; media query and set &lt;code&gt;color&lt;/code&gt; from it. This needs no JavaScript and no class toggle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#0f172a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-color-scheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#e2e8f0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the icons track the user's system theme. Someone on a phone that flips to dark at sunset sees the lighter outline without any work from you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can I recolor an icon on hover?
&lt;/h2&gt;

&lt;p&gt;Yes. Because the icon follows &lt;code&gt;color&lt;/code&gt;, any state that changes &lt;code&gt;color&lt;/code&gt; also changes the icon. A hover on the button recolors the outline inside it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.icon-button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#64748b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* slate-500 at rest */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.icon-button&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#2563eb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* blue-600 on hover */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"icon-button"&lt;/span&gt; &lt;span class="na"&gt;aria-label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Filter by France"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Fr&lt;/span&gt; &lt;span class="na"&gt;aria-hidden&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same idea covers focus rings and disabled states. You style the button, and the icon comes along.&lt;/p&gt;

&lt;h2&gt;
  
  
  Outline or solid: stroke versus fill
&lt;/h2&gt;

&lt;p&gt;GeoIcons render as outlines. The &lt;code&gt;stroke&lt;/code&gt; is &lt;code&gt;currentColor&lt;/code&gt; and the &lt;code&gt;fill&lt;/code&gt; is &lt;code&gt;none&lt;/code&gt;, which is why theming runs through the stroke. If you want a solid glyph, set &lt;code&gt;fill&lt;/code&gt; yourself and keep it on &lt;code&gt;currentColor&lt;/code&gt; so it still follows the theme:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Fr&lt;/span&gt; &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"currentColor"&lt;/span&gt; &lt;span class="na"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt; &lt;span class="na"&gt;aria-label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"France"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both the stroke path and a &lt;code&gt;currentColor&lt;/code&gt; fill respect the same inherited &lt;code&gt;color&lt;/code&gt;, so a solid icon themes exactly like an outline one.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How do I make an icon change color in dark mode?
&lt;/h3&gt;

&lt;p&gt;Set the CSS color property for your dark theme, either on a .dark class or through a prefers-color-scheme media query. GeoIcons draw with stroke='currentColor', so each icon inherits that color automatically. You do not pass a color prop to the icon itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do I need a color prop on every GeoIcon?
&lt;/h3&gt;

&lt;p&gt;No. Each icon borrows the CSS color of its container through currentColor. Set color once per theme and every icon follows. Pass an explicit stroke or fill only when a single icon needs to break from the surrounding text color.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I give one icon a different color from the surrounding text?
&lt;/h3&gt;

&lt;p&gt;Yes. Pass an explicit stroke (or fill) on that single icon, such as stroke='#2563eb', or wrap it in an element that sets its own color. currentColor only applies when you leave the color unset, so an override on one icon does not touch the rest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get started
&lt;/h2&gt;

&lt;p&gt;Install the package and let your theme drive the color:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i @geoicons/react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Jp&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@geoicons/react/countries&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-slate-900 dark:text-slate-100"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Jp&lt;/span&gt; &lt;span class="na"&gt;aria-label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Japan"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For every prop each icon accepts, see &lt;a href="https://geoicons.io/docs/api" rel="noopener noreferrer"&gt;the GeoIcons API reference&lt;/a&gt;. To learn why importing icons this way keeps your bundle small, read &lt;a href="https://geoicons.io/blog/tree-shaking-icons" rel="noopener noreferrer"&gt;why an icon library doesn't have to bloat your bundle&lt;/a&gt;. New here? Start with &lt;a href="https://geoicons.io/blog/add-country-icons-react" rel="noopener noreferrer"&gt;adding your first country icon&lt;/a&gt; or &lt;a href="https://geoicons.io/icons/countries" rel="noopener noreferrer"&gt;browse all 422 icons&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>darkmode</category>
      <category>currentcolor</category>
      <category>svgicons</category>
      <category>theming</category>
    </item>
    <item>
      <title>Introducing GeoIcons: 422 tree-shakable geographic icons</title>
      <dc:creator>Rushan</dc:creator>
      <pubDate>Wed, 15 Jul 2026 06:27:44 +0000</pubDate>
      <link>https://dev.to/rushan123/introducing-geoicons-422-tree-shakable-geographic-icons-43i</link>
      <guid>https://dev.to/rushan123/introducing-geoicons-422-tree-shakable-geographic-icons-43i</guid>
      <description>&lt;p&gt;GeoIcons is a library of geographic map icons for the web: &lt;strong&gt;255 countries and 167 areas&lt;/strong&gt;, 422 icons in total at the time of this post, built for React, Vue, Angular, and vanilla JS. More is on the way, including subdivisions and flags. Every icon is a named export, so your bundler keeps only the ones you import. Here are three of them, inheriting the current text color:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;422 icons: 255 countries (ISO 3166) + 167 areas (regions, continents, landforms, subdivisions).&lt;/li&gt;
&lt;li&gt;Tree-shakable by design. One import ships one icon, not the catalog.&lt;/li&gt;
&lt;li&gt;Themed with &lt;code&gt;currentColor&lt;/code&gt; and an adjustable &lt;code&gt;strokeWidth&lt;/code&gt;. Accessible out of the box.&lt;/li&gt;
&lt;li&gt;React, Vue, Angular, and vanilla JS. Free under GPLv3, commercial license available.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What ships in the box
&lt;/h2&gt;

&lt;p&gt;The set covers &lt;strong&gt;255 country icons&lt;/strong&gt;, named by their ISO 3166 alpha-2 code, and &lt;strong&gt;167 area icons&lt;/strong&gt; for regions, continents, landforms, and subdivisions. Enough to build a country picker or label a map legend without a second asset library.&lt;/p&gt;

&lt;p&gt;Every icon is a single SVG component. No sprite sheet to host and no font to load.&lt;/p&gt;

&lt;h2&gt;
  
  
  One import ships one icon
&lt;/h2&gt;

&lt;p&gt;GeoIcons has no central registry and no &lt;code&gt;&amp;lt;Icon name="us" /&amp;gt;&lt;/code&gt; string API. Each icon is its own named export, which is what lets bundlers drop everything you never reference:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Us&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Fr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Jp&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@geoicons/react/countries&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Legend&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Us&lt;/span&gt; &lt;span class="na"&gt;aria-label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"United States"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; United States&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Fr&lt;/span&gt; &lt;span class="na"&gt;aria-label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"France"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; France&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Jp&lt;/span&gt; &lt;span class="na"&gt;aria-label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Japan"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; Japan&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Import three icons and your build includes three icons. The other 419 never touch your bundle. For the mechanics behind that, read &lt;a href="https://geoicons.io/blog/tree-shaking-icons" rel="noopener noreferrer"&gt;why an icon library doesn't have to bloat your bundle&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Themeable with currentColor
&lt;/h2&gt;

&lt;p&gt;Icons paint with &lt;code&gt;currentColor&lt;/code&gt;, so they follow the text color of whatever wraps them. Change weight with &lt;code&gt;strokeWidth&lt;/code&gt;, or fill them solid. No CSS overrides, no per-icon color props to thread through your components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Default, colored, heavier stroke, filled&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Ng&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Ng&lt;/span&gt; &lt;span class="na"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"#2563eb"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Ng&lt;/span&gt; &lt;span class="na"&gt;strokeWidth&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Ng&lt;/span&gt; &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"currentColor"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because color is inherited, the same icon works in light mode, dark mode, and on a colored button without any extra styling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accessible by default
&lt;/h2&gt;

&lt;p&gt;Icons are decorative unless you say otherwise. Add a label and the icon becomes meaningful to screen readers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Us&lt;/span&gt; &lt;span class="na"&gt;aria-label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"United States"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under the hood each icon namespaces its &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; id with React's &lt;code&gt;useId()&lt;/code&gt;, so rendering the same icon twice on a page never produces duplicate ids.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four frameworks, one icon set
&lt;/h2&gt;

&lt;p&gt;The same icons ship for every major framework, imported the same way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Us&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@geoicons/react/countries&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// React&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Us&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@geoicons/vue/countries&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// Vue&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Us&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@geoicons/angular/countries&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Angular&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Us&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@geoicons/vanilla/countries&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Vanilla JS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;@geoicons/core&lt;/code&gt; holds the shared pieces the framework packages build on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Naming you can guess
&lt;/h2&gt;

&lt;p&gt;Countries use their ISO 3166 alpha-2 code in PascalCase: &lt;code&gt;Us&lt;/code&gt;, &lt;code&gt;Fr&lt;/code&gt;, &lt;code&gt;Jp&lt;/code&gt;, &lt;code&gt;De&lt;/code&gt;, &lt;code&gt;Br&lt;/code&gt;. Areas use a slug in PascalCase, such as &lt;code&gt;EuropeanUnionEu&lt;/code&gt;. If you know the country code, you know the import name, so autocomplete does most of the work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Licensing
&lt;/h2&gt;

&lt;p&gt;GeoIcons is dual-licensed. It is &lt;strong&gt;free under GPLv3&lt;/strong&gt; for open-source and GPL-compatible projects, and a &lt;strong&gt;commercial license&lt;/strong&gt; covers everything else. Icons render the same either way. An unlicensed commercial use logs an offline console warning and nothing else, so nothing breaks at runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get started
&lt;/h2&gt;

&lt;p&gt;Install the package for your framework and import your first icon:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i @geoicons/react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Us&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@geoicons/react/countries&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Us&lt;/span&gt; &lt;span class="na"&gt;aria-label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"United States"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full API, styling, and accessibility docs live in &lt;a href="https://geoicons.io/docs/api" rel="noopener noreferrer"&gt;the docs&lt;/a&gt;, or &lt;a href="https://geoicons.io/icons/countries" rel="noopener noreferrer"&gt;browse all 422 icons&lt;/a&gt; to find what you need.&lt;/p&gt;

</description>
      <category>announcement</category>
      <category>geoicons</category>
      <category>react</category>
      <category>svgicons</category>
    </item>
  </channel>
</rss>
