DEV Community

Cover image for Why Your SVG Icons Break When Converted to Web Fonts (And How to Fix Inverted Glyphs)
Muhammad Umair | DevOmniTools
Muhammad Umair | DevOmniTools

Posted on Originally published at devomnitools.com

Why Your SVG Icons Break When Converted to Web Fonts (And How to Fix Inverted Glyphs)

Converting SVGs into custom icon fonts sounds straightforward until you compile your first glyph set. You export ten clean icons from Figma or Illustrator, feed them into an icon font generator, and open the preview. Half the icons are upside down. Two icons have solid black fills where transparent cutouts should be. And one icon has blurry, clipped strokes.

If you have run into this, you are not alone. These issues are not random bugs in your font compiler; they stem from fundamental mathematical differences between how browser SVGs render vector coordinates and how OpenType/TrueType font engines parse glyph contours. Here is what actually breaks under the hood, and how to fix your vectors so they compile cleanly every time.


1. The Y-Axis Inversion Trap (Why Your Icons Turn Upside Down)

In modern web graphics, SVGs use a top-left origin:

(0,0) Converting SVGs into custom icon fonts sounds straightforward until you compile your first glyph set. You export ten clean icons from Figma or Illustrator, feed them into an icon font generator, and open the preview. Half the icons are upside down. Two icons have solid black fills where transparent cutouts should be. And one icon has blurry, clipped strokes.

If you have run into this, you are not alone. These issues are not random bugs in your font compiler; they stem from fundamental mathematical differences between how browser SVGs render vector coordinates and how OpenType/TrueType font engines parse glyph contours. Here is what actually breaks under the hood, and how to fix your vectors so they compile cleanly every time.

---

## 1. The Y-Axis Inversion Trap (Why Your Icons Turn Upside Down)

In modern web graphics, SVGs use a **top-left origin**:

Enter fullscreen mode Exit fullscreen mode

(0,0) ------- +X
|
|
+Y


Increasing `y` values push coordinates downwards. TrueType and OpenType font systems use a **Cartesian bottom-left origin**:

Enter fullscreen mode Exit fullscreen mode

+Y
|
|
(0,0) ------- +X


Increasing `y` values push coordinates upwards. When a compiler parses an SVG path like:

Enter fullscreen mode Exit fullscreen mode


xml


It reads `(10, 20)` and `(50, 80)` as points in a Cartesian space unless the coordinate transform explicitly mirrors the Y-axis across the font's unit box. If your build pipeline or converter omits an affine matrix inversion (`scale(1, -1)` + `translate(0, -baseline)`), the glyph compiles upside down.

### The Fix

Before compiling, ensure your vector compiler normalizes coordinates against the standard Units Per Em (UPM) grid (typically **1000 UPM** or **1024 UPM**). If converting manually or via script, apply the vertical reflection transformation matrix:

Enter fullscreen mode Exit fullscreen mode


plaintext
[x'] [1 0] [x] [ 0 ]
[y'] = [0 -1] [y] + [ascender]


---

## 2. Non-Zero Winding vs Even-Odd: The Black Cutout Problem

Ever convert a search icon or a badge with a hole in the middle, only to find the hole filled with solid black? This happens because SVGs often rely on `fill-rule="evenodd"`, whereas TrueType font interpreters rely strictly on the **Non-Zero Winding Rule**:

* **SVG `evenodd`:** Draws a ray from any point to infinity. If the ray crosses an odd number of path segments, the point is inside (filled). If even, it is outside (hollow). Path direction does not matter.
* **TrueType Non-Zero Rule:** Clockwise contours define solid shapes; counter-clockwise contours define holes (or vice versa depending on winding mode). If an inner circle and an outer circle in your SVG both travel clockwise, TrueType considers both of them solid fills. The hole disappears.

Enter fullscreen mode Exit fullscreen mode


plaintext
SVG (Even-Odd) TrueType (Winding Order)
Outer: Clockwise Outer: Clockwise (+)
Inner: Clockwise Inner: Counter-Clockwise (-)
Result: Hole preserved Result: Hole preserved ONLY IF reversed!


### The Fix

In Figma or Illustrator, run **Outline Stroke** followed by **Simplify Path / Flatten**. Alternatively, run an SVG pre-processor or a dedicated client-side converter that normalizes path direction before generating TTF curves.

---

## 3. B## 3. Bezier Curve Degree Mismatch (Cubic vs Quadratic)

SVG paths use **Cubic Bezier curves** (`C` or `S` path commands): each segment has two control points (CP1 and CP2). TrueType fonts (`.ttf`) natively support **Quadratic Bezier curves**: each segment has only **one** control point (CP).

Enter fullscreen mode Exit fullscreen mode


plaintext
SVG Cubic Curve: Start --- CP1 ------- CP2 --- End
TTF Quadratic Curve: Start ------- CP ------------ End


When converting Cubic to Quadratic:
1. The compiler must approximate every cubic curve by splitting it into multiple quadratic arcs.
2. If your SVG has redundant anchor points, sub-pixel curves, or complex clipping masks, this approximation explodes in size and introduces visual artifacts.

### Rules for Clean Conversion:
* Convert all strokes to outlined fills (`stroke-width` is ignored by font glyph tables).
* Keep your viewbox square (e.g., `24x24`, `32x32`, or `512x512`).
* Strip hidden `<defs>`, empty `<clipPath>`, and inline styling before compiling.

---

## 4. Production `@font-face` Integration

Once compiled to `.ttf` and converted to `.woff2` for web delivery, load your custom icon font with `font-display: block` to prevent layout shift:

Enter fullscreen mode Exit fullscreen mode


css
@font-face {
font-family: 'DevOmniIcons';
src: url('/fonts/devomni-icons.woff2') format('woff2'),
url('/fonts/devomni-icons.ttf') format('truetype');
font-weight: normal;
font-style: normal;
font-display: block;
}

.icon {
font-family: 'DevOmniIcons', sans-serif;
speak: never;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

/* Individual Glyphs mapped via Unicode PUA (Private Use Area) */
.icon-search:before { content: "\e900"; }
.icon-terminal:before { content: "\e901"; }
.icon-lock:before { content: "\e902"; }




Using the Unicode Private Use Area (`\e900` to `\f8ff`) prevents screen readers from trying to pronounce random alphanumeric characters when encountering icons.

---

## Testing Your SVGs in the Browser

If you need to batch-convert SVG icons into `.ttf` or `.woff2` without uploading your proprietary vectors to third-party cloud servers, test them directly in-browser:

-> **[SVG to Font Converter (Free & Private) - DevOmniTools](https://www.devomnitools.com/en/tools/svg-to-font/)**

It handles Y-axis inversion, path winding normalization, and 1000 UPM grid scaling entirely in client-side memory. You get instant live previews and copy-pasteable CSS code.
Enter fullscreen mode Exit fullscreen mode

Top comments (0)