Skip to content

Replace icon font with SVG sprite - #1028

Open
tessaluniki wants to merge 5 commits into
Null-Signal-Games:mainfrom
tessaluniki:feature/svg-sprites
Open

tessaluniki wants to merge 5 commits into
Null-Signal-Games:mainfrom
tessaluniki:feature/svg-sprites

Conversation

@tessaluniki

Copy link
Copy Markdown

Summary

Netrunner icons were rendered through an IcoMoon icon font (netrunner.eot/.ttf/.woff/.svg) loaded via netrunnerfont.css. This commit replaces that font with a single SVG sprite (web/images/netrunner.svg) whose symbols are referenced from markup through <svg><use xlink:href="…#icon-…">.

Why it is useful

  • The font shipped icons as binary glyphs mapped to private text codepoints. Font binaries are not reviewable in a diff and require a font-generation tool (IcoMoon) to change. SVG sources are plain text: every icon is inspectable, diffable, and changed by editing one file.
  • Icons rendered as text glyphs inherit font metrics (baseline, line-height, hinting), which required per-site CSS hacks to size and align. SVG icons are boxes with predictable width/height and vertical-align.
  • A font loads asynchronously and can flash invisible/fallback glyphs until loaded; the sprite is preloaded and referenced deterministically.

Contents

Build tooling (added)

  • package.json / package-lock.json: add the svg-sprite dependency and an svg-sprite npm script.
  • Makefile: web/netrunner.svg target that regenerates the sprite from web/images/icons/*.svg.

Icon sources and sprite (added)

  • 56 individual source SVGs under web/images/icons/ extracted from /web/selection.json.
  • Replaced click, credit, interrupt, link, mu, recurring-credit, subroutine and trash with the newer versions from https://rules.nullsignal.games/.
  • Generated sprite web/images/netrunner.svg (56 symbols, icon-* ids).

Rendering helpers (added/refactored)

  • New Twig function icon(name, className, title) in AppExtension (is_safe: html), emitting the <svg class="icon icon-…"><use …></svg> markup in one place.
  • New JS helper NRDB.format.icon(name, {className, fallback}) in nrdb.format.js; fallback appends a .icon-fallback span for screen readers.
  • CardsData::replaceSymbols() rewritten to build its token map from an [icon, title] table instead of a hand-written HTML map, emitting the same <svg><use> markup plus a .icon-fallback span.

Template and script migration

  • Converted every Twig template (layout, Decklist, Formats, Prebuilt, Rulings, Search/*, Tools/demo) from <span class="icon icon-…"> to {{ icon(…) }}.
  • Converted the JS scripts card-text, deck, decklist, decks, zoom, rulings, publish, rotation, and user to use NRDB.format.icon().
  • Updated Card::getCost() to emit the <svg><use> markup directly.

Styles

  • Added an .icon rule: inline-block, 1em box, fill: currentColor, stroke: currentColor, vertical-align middle.
  • Added per-icon tweaks (.icon-credit margin, .icon-subroutine baseline).
  • Removed the font-size overrides for .card-text abbr[class*="icon icon-"] that only applied to font glyphs.

Asset loading

  • Removed the <link rel="stylesheet" href="/netrunnerfont.css"> from the layout head and added <link rel="preload" href="/images/netrunner.svg" as="image" type="image/svg+xml"> alongside the existing icons.svg preload.

Removed

  • web/netrunnerfont.css and web/fonts/netrunner.{eot,ttf,woff,svg}.

Summary

Netrunner icons were rendered through an IcoMoon icon font (netrunner.eot/.ttf/.woff/.svg) loaded via netrunnerfont.css. This commit replaces that font with a single SVG sprite (web/images/netrunner.svg) whose symbols are referenced from markup through `<svg><use xlink:href="…#icon-…">`.

Why it is useful

- The font shipped icons as binary glyphs mapped to private text codepoints. Font binaries are not reviewable in a diff and require a font-generation tool (IcoMoon) to change. SVG sources are plain text: every icon is inspectable, diffable, and changed by editing one file.
- Icons rendered as text glyphs inherit font metrics (baseline, line-height, hinting), which required per-site CSS hacks to size and align. SVG icons are boxes with predictable width/height and vertical-align.
- A font loads asynchronously and can flash invisible/fallback glyphs until loaded; the sprite is preloaded and referenced deterministically.

Contents

Build tooling (added)
- package.json / package-lock.json: add the `svg-sprite` dependency and an `svg-sprite` npm script.
- Makefile: `web/netrunner.svg` target that regenerates the sprite from `web/images/icons/*.svg`.

Icon sources and sprite (added)
- 56 individual source SVGs under web/images/icons/ extracted from /web/selection.json.
- Replaced click, credit, interrupt, link, mu, recurring-credit, subroutine and trash with the newer versions from https://rules.nullsignal.games/.
- Generated sprite web/images/netrunner.svg (56 symbols, `icon-*` ids).

Rendering helpers (added/refactored)
- New Twig function `icon(name, className, title)` in AppExtension (`is_safe: html`), emitting the `<svg class="icon icon-…"><use …></svg>` markup in one place.
- New JS helper `NRDB.format.icon(name, {className, fallback})` in nrdb.format.js; `fallback` appends a `.icon-fallback` span for screen readers.
- `CardsData::replaceSymbols()` rewritten to build its token map from an `[icon, title]` table instead of a hand-written HTML map, emitting the same `<svg><use>` markup plus a `.icon-fallback` span.

Template and script migration
- Converted every Twig template (layout, Decklist, Formats, Prebuilt, Rulings, Search/*, Tools/demo) from `<span class="icon icon-…">` to `{{ icon(…) }}`.
- Converted the JS scripts card-text, deck, decklist, decks, zoom, rulings, publish, rotation, and user to use `NRDB.format.icon()`.
- Updated `Card::getCost()` to emit the `<svg><use>` markup directly.

Styles
- Added an `.icon` rule: inline-block, 1em box, `fill: currentColor`, `stroke: currentColor`, vertical-align middle.
- Added per-icon tweaks (`.icon-credit` margin, `.icon-subroutine` baseline).
- Removed the font-size overrides for `.card-text abbr[class*="icon icon-"]` that only applied to font glyphs.

Asset loading
- Removed the `<link rel="stylesheet" href="/netrunnerfont.css">` from the layout head and added `<link rel="preload" href="/images/netrunner.svg" as="image" type="image/svg+xml">` alongside the existing icons.svg preload.

Removed
- web/netrunnerfont.css and web/fonts/netrunner.{eot,ttf,woff,svg}.
@NoahTheDuke

Copy link
Copy Markdown
Collaborator

this is a great idea. if y'all pick it up, we'll borrow it for jnet

@migueldlr

Copy link
Copy Markdown
Contributor

Thanks for this PR! It'll take some time to review but after checking out and testing locally I'm noticing a slight visual regression with the inline position of some icons:

Before After
Screenshot 2026-09-10 at 11 07 39 AM Screenshot 2026-09-10 at 11 07 43 AM
Screenshot 2026-09-10 at 11 09 32 AM Screenshot 2026-09-10 at 11 09 29 AM

@qt-dork

qt-dork commented Sep 10, 2026

Copy link
Copy Markdown

A very large number of the icons look incorrect. I haven’t checked if they render correctly on the site itself, but the svgs have a number of errors (see vantage point, jinteki), and mix and match more modern nsg icons (credits, trash ability, click) with older ffg icons (runner faction icons)

@tessaluniki

tessaluniki commented Sep 10, 2026

Copy link
Copy Markdown
Author

I do not have access to the latest version of the icons. First I extracted svg files from the font and then replaced what I could find from rules.nullsignal.games

So the correct versions should be added instead and positioning has to be adjusted afterwards.

@migueldlr

Copy link
Copy Markdown
Contributor

I do not have access to the latest version of the icons. First I extracted svg files from the font and then replaced what I could find from rules.nullsignal.games

So the correct versions should be added instead and positioning has to be adjusted afterwards.

We have SVGs available publicly here:

https://nullsignal.games/about/nsg-visual-assets/

@tessaluniki

Copy link
Copy Markdown
Author

Thank you. I have updated the icons:

First extracted https://github.com/Null-Signal-Games/netrunnerdb/blob/f76f66b02008294ed4d622de79c88664ce170818/web/fonts/netrunner.svg using https://icomoon.io

Then updated icons using visual assets from https://nullsignal.games/about/nsg-visual-assets/

The visual assets do not contain all the icons. For example the Vantage Point icon is missing from the visual assets.

The visual assets icons are too large and not intended as monochrome icons in card text. Revert them back to the icomoon versions.
@tessaluniki

Copy link
Copy Markdown
Author

I had to revert some of the icons to the font versions. The visual assets icons for factions and sets are much larger and not suited to replace monochrome icons in card text etc. (The Haas Bioroid icon is 3.9 MB for example.)

The font contains faction symbols, set symbols and game symbols:

  • faction symbols are extracted from the font
  • set symbols are extracted from the font
  • game symbols are copied from the visual assets

I do not know which versions are best suited as monochrome icons.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrong anarch, we need nsg not ffg

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this the wrong size?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants