IcoMoon Icons logo

IcoMoon CDN: Load the Free Icon Font from jsDelivr

IcoMoon has no official CDN — nothing is served from any cdn.icomoon.io, and the premium packs are paid files you host yourself. The free 491-icon set is the exception: it sits in a public GitHub repository, and jsDelivr can serve any file from that repo over a global CDN. The working font URL is cdn.jsdelivr.net/gh/Keyamoon/IcoMoon-Free/Font/IcoMoon-Free.ttf — full copy-paste setup, version pinning, caching caveats and the honest case for self-hosting below.

Why there is no official CDN

The app at icomoon.io is a generator: you pick glyphs and it builds a font that exists only in your export, so there is no canonical file for a CDN to host. The one stable artifact is the free starter set — 491 icons that Keyamoon publishes on GitHub under GPL / CC BY 4.0. jsDelivr's gh/ endpoint mirrors raw files from any public GitHub repository behind proper edge caching and CORS headers, which makes it the closest thing to an official CDN this ecosystem has.

Step 1 — Declare the font with @font-face

Drop the following into your page, or move the CSS into a stylesheet. One warning up front: the repository ships the font only as a 130 KB TTF — no WOFF2 build is committed there, which matters for the self-hosting comparison later.

<style>
  @font-face {
    font-family: "IcoMoon-Free";
    src: url("https://cdn.jsdelivr.net/gh/Keyamoon/IcoMoon-Free/Font/IcoMoon-Free.ttf")
      format("truetype");
    font-display: block;
  }

  [class^="icon-"],
  [class*=" icon-"] {
    font-family: "IcoMoon-Free";
    speak: never;
    font-style: normal;
    font-weight: normal;
    line-height: 1;
  }

  .icon-home::before {
    content: "\e900";
  }
</style>

<span class="icon-home" aria-hidden="true"></span>

font-display: block is deliberate: with an icon font you would rather show nothing for a moment than flash a meaningless \e900 code point as fallback text. Each glyph needs its own ::before rule — every class-to-unicode mapping is listed on the cheat sheet.

Step 2 — Preload it with a link tag

Fonts referenced from CSS are discovered late: the browser has to download and parse the stylesheet before it even learns the font exists. A preload in the <head> starts the fetch immediately:

<link
  rel="preload"
  href="https://cdn.jsdelivr.net/gh/Keyamoon/IcoMoon-Free/Font/IcoMoon-Free.ttf"
  as="font"
  type="font/ttf"
  crossorigin
/>

The crossorigin attribute is not optional. Font preloads are always CORS-mode requests — even for same-origin files — so if you omit it, the browser discards the preloaded copy and downloads the font a second time.

Step 3 — Pin a version, never ship the floating URL

Without a version, jsDelivr serves whatever the repository's default branch currently contains. If a future commit renames a glyph or shifts a code point, your icons change with it — silently. jsDelivr accepts any git ref after an @, and a full commit hash is the only truly immutable choice:

<!-- floats with the default branch — fine for a prototype -->
https://cdn.jsdelivr.net/gh/Keyamoon/IcoMoon-Free/Font/IcoMoon-Free.ttf

<!-- pinned to an immutable commit — what production should use -->
https://cdn.jsdelivr.net/gh/Keyamoon/IcoMoon-Free@<commit-sha>/Font/IcoMoon-Free.ttf

Grab the latest commit SHA from the IcoMoon-Free repository and bake it into the URL. A pinned URL never changes, so every cache in the chain — jsDelivr's edges and your users' browsers — can hold it essentially forever.

Caching and SRI: what you control, what you don't

Cache behaviour

An unversioned URL floats: when the branch moves, jsDelivr picks up the change on its own refresh cycle, and you cannot force a purge on a repository you don't own. During a rollover, different edge nodes can briefly serve different bytes. Commit-pinned URLs sidestep the whole problem, which is reason enough to use them.

Subresource integrity

SRI protects stylesheet links and <script> tags only. A font requested through @font-face cannot carry an integrity hash — no browser verifies fonts that way — so the commit pin from Step 3 is your integrity story. If you ever hotlink a third-party stylesheet instead, add integrity plus crossorigin="anonymous" to that link tag, and remember the hash only matches the exact pinned bytes.

Common pitfalls

404 from a lower-cased path

The path is case-sensitive: Font/IcoMoon-Free.ttf with a capital F in the folder and capital letters in the filename. Request font/icomoon-free.ttf and you get a 404 that looks maddeningly like a CDN outage.

Blank squares instead of glyphs

The font loaded, but your content value doesn't match the glyph's real code point. The GitHub build's assignments start at \e900 in the Private Use Area — verify each icon against the cheat sheet rather than copying mappings from an unrelated export.

Mixing the CDN font with a generator export

If you also run a custom selection through the app (see the app tutorial), that export's code points are yours, not the repo's. Don't point a CDN @font-face and a local export at the same font-family name, or glyphs resolve against whichever file loaded last.

When you should self-host instead

jsDelivr is a legitimate choice for prototypes, CodePens, internal tools and low-traffic pages. For production, self-hosting usually wins on three counts. Size: the repo offers only the 130 KB TTF, while a self-hosted WOFF2 of the same set is 49 KB — roughly 62% smaller. Cache reality: browsers have partitioned HTTP caches per site since around 2020, so the old "your visitors already have the CDN copy cached" argument no longer applies, and every first visit pays the extra DNS, TLS and download cost of a third-party origin. Control: no external dependency that can fail, and no user request leaving your domain.

The download page has the ready-made WOFF2, WOFF and CSS files — copy them into your project and swap the URL in your @font-face; nothing else changes. If your toolchain prefers a package manager over static files, the npm guide covers the vendoring workflows that hold up in CI.

CDN or self-hosted, the free set caps out at 491 glyphs. When a project needs broader coverage in one consistent style, the Ultimate pack is a $59 one-time purchase with 1,500+ icons and SVG sources — the pricing breakdown compares it against the subscriptions.