Material Icons vs Material Symbols: The Complete 2026 Guide (Variable Axes, Setup & Performance)
The State of Google Iconography: Google now maintains two icon systems with the same DNA but very different engineering: Material Symbols, the current variable-font set introduced in April 2022, and Material Icons, the classic set whose updates stopped in 2022. This guide covers every production method with verified numbers:
- The 2022 freeze: which set is current, which is legacy, and what that means for your next release.
- The four variable axes: FILL, wght, GRAD and opsz — with working
font-variation-settingscode for animated fill transitions. - Payload math: why the default stylesheet ships all 3,800+ icon variants at ~295 KB, and how one URL parameter cuts it to ~1.7 KB.
- Framework reality: Google's npm package stopped at v3 (2016) — the community
@marellapackages and a zero-font SVG workflow for React 19, Next.js App Router, Vue and Angular. - Self-hosting & FOUC: the
display=blockfix that stops raw ligature text flashing before the font loads. - The SVG alternative: skip the font entirely — browse all 18,547 Material Symbols, 15,969 Light variants and 14,001 Material Design Icons on IconStash with one-click SVG export.
1. Material Icons vs Material Symbols: What Google Actually Shipped
Google's icon ecosystem has two names that developers constantly conflate. Here is the precise terminology, straight from the official google/material-design-icons repository and Google Fonts documentation:
- Material Symbols is the current set, introduced in April 2022. It is designed as a variable font first, built on the 24px designs of Material Icons, and consolidates over 2,500 glyphs in a single font file.
- Material Icons is the classic set, no longer updated. Google halted new icon additions in 2022, and it will never receive variable fonts, extra weights, grades, or animated fill transitions.
- Material Design Icons is the historical name of the repository that hosts both sets — which is why three different search terms all lead to the same ecosystem.
On fonts.google.com/icons, Material Symbols is the default in the set selector; the classic Material Icons are reached via ?icon.set=Material+Icons. The set difference matters immediately when you plan a project:
| Property | Material Symbols (current) | Material Icons (classic) |
|---|---|---|
| Status in 2026 | Actively maintained by Google | Frozen — no new icons since 2022 |
| Technology | Variable font (4 axes), SVGs also available | Static fonts in 5 fixed styles |
| Glyphs | 2,500+ unique glyphs; default stylesheet serves all 3,800+ icon variants | 900+ icons |
| Styles | Outlined, Rounded, Sharp (fill via the FILL axis) | Filled, Outlined, Rounded, Sharp, Two tone |
| CSS class prefix | material-symbols-outlined / -rounded / -sharp |
material-icons / -outlined / -round / -sharp / -two-tone |
| Two-tone icons | Not available | Available (Two tone style) |
| Brand / logo icons | None — removed for legal reasons | None — third-party logos were removed |
| Classic font weight | ~295 KB default payload (all variants) | 42 KB woff2 / 56 KB woff |
Classic Material Icons uses the class material-icons-round ("round"), while Material Symbols uses material-symbols-rounded ("rounded"). Migration guides that search-and-replace "icons" to "symbols" silently break every rounded icon. Use the class mapping table in section 10 instead.
For brand or social media logos, neither set can help you: Google excludes third-party logos for legal reasons and has even removed ones that shipped historically. Use a dedicated brand set such as Simple Icons (3,714 CC0 brand marks on IconStash) instead — we cover that workflow in our free social media icons listicle.
2. The Four Variable Axes: FILL, wght, GRAD & opsz
Material Symbols is a variable font, so a single glyph file can render thousands of visual states. Four axes control the appearance, and you can animate any of them with plain CSS transitions:
| Axis | Range | Default | What it controls |
|---|---|---|---|
| FILL | 0 – 1 | 0 | 0 renders the outlined glyph, 1 renders a completely filled variant. There is no separate "filled" font — the axis is the fill, which also enables animated fill transitions. |
| wght | 100 – 700 | 400 | Stroke weight from Thin (100) through Regular (400) to Bold (700). |
| GRAD | −50 – 200 | 0 | Grade: optical compensation at the same size. Use −50 for reversed contrast (white icons on black backgrounds). |
| opsz | 20 – 48 | 24 | Optical size in dp — larger values thicken details for big touch targets; 20 and 24 are the pixel-grid-perfect designs. |
You address the axes with the standard CSS font-variation-settings property:
/* One icon, four axes — set once, transition at will */
.material-symbols-outlined {
font-variation-settings:
'FILL' 0,
'wght' 400,
'GRAD' 0,
'opsz' 24;
}
/* Active state: morph outline to fill on hover, no second file */
.nav-item:hover .material-symbols-outlined {
font-variation-settings:
'FILL' 1,
'wght' 500,
'GRAD' 0,
'opsz' 24;
transition: font-variation-settings 200ms ease;
}
/* Reversed contrast: white icons on a dark banner */
.on-dark .material-symbols-outlined {
font-variation-settings: 'FILL' 1, 'wght' 400, 'GRAD' -50, 'opsz' 24;
}
That hover example is the flagship capability classic Material Icons cannot deliver: because Symbols exposes fill as an axis, you can animate an outline-to-fill transition with a CSS transition instead of swapping two different icons. On the classic set you would need two glyphs and a cross-fade.
Google states that only the 20 and 24px versions are designed with perfect pixel-grid alignment. At opsz 28–48 the glyphs still render correctly, but if you need razor-sharp 1px strokes at exactly 20 or 24 device pixels, stick to the aligned sizes.
3. Google Fonts CDN Setup in Plain HTML (Ligatures, Codepoints & FOUC)
The fastest way to ship Material Symbols is the Google Fonts CSS API. One stylesheet request in <head>, then ligature names inside a <span>:
<!-- 1. Load the variable font (display=block prevents ligature flash) -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,[email protected],100..700,0..1,-50..200&display=block" />
<!-- 2. Reference any glyph by its ligature name -->
<span class="material-symbols-outlined">home</span>
<span class="material-symbols-outlined">search</span>
<span class="material-symbols-outlined">settings</span>
Ligatures vs codepoints
Ligatures (arrow_forward) are the primary addressing method and are supported by every modern browser; the numeric codepoint () is the documented fallback for browsers without ligature support. Prefer ligatures — they survive refactors and are grep-able in code review.
The FOUC rule everyone misses
Google's own guidance is blunt: the CSS request must include &display=block. Without it, the browser renders the raw ligature text — the literal words "home", "search", "settings" — until the font arrives. That flash of unstyled ligature text is the number-one Material Symbols bug reported on production sites, and it is a one-parameter fix.
The three style families are separate fonts, so pick the one you need rather than loading all of them:
Material+Symbols+Outlined— sharp corners, the workhorse for dense UIMaterial+Symbols+Rounded— 100% corner radii, friendlier consumer productsMaterial+Symbols+Sharp— zero corner radius, expressive brand moments
There is no Material+Symbols+Filled URL — filled rendering comes from the FILL axis at 1, in all three fonts. Classic Material Icons users note the difference: material-icons-round ("round") vs material-symbols-rounded ("rounded").
4. Performance: The 295 KB Problem and the 1.7 KB Fix
Here is the number most tutorials skip: the default Material Symbols stylesheet loads all 3,800+ icon variants and ships a ~295 KB font. If your navigation uses five icons, you are paying for 3,795 you never render — a payload 7× larger than the entire classic Material Icons font (42 KB woff2).
The Google Fonts CSS API solves this with the icon_names parameter. Subset to exactly the icons you use and the same font collapses to ~1.7 KB:
<!-- BEFORE: every icon Google ever drew, ~295 KB -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,[email protected],100..700,0..1,-50..200&display=block" />
<!-- AFTER: three icons, ~1.7 KB font -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,[email protected],100..700,0..1,-50..200&icon_names=home,search,menu&display=block" />
Exact payload scenarios (from Google's documentation)
| Request configuration | Font payload | Verdict |
|---|---|---|
| Default URL, all 3,800+ icons | 295 KB | Never ship this to production |
Same URL + icon_names=home,palette,settings |
1.7 KB | 99.4% smaller — use for icon-font builds |
Instanced axes + icon_names (e.g. FILL,[email protected],100) |
2.6 KB | Still tiny, adds fill animation range |
| Full variable axes with complete ranges | 7.9 MB | Labeled "not recommended" by Google itself |
| Classic Material Icons (all 900+, woff2) | 42 KB | Frozen set, but constant |
Keep the icon_names list as a template variable in your build (a JSON array of ligature names is ideal). Every design review that adds an icon updates the list, and the subset regenerates on the next deploy. For a deeper treatment of subsetting economics across icon fonts, see our icon font subsetting and variable glyphs guide.
One more trap: requesting the full ranges of all four axes produces a 7.9 MB font. Google's documentation explicitly labels that configuration "not recommended" — yet it is exactly what copy-pasting the "full flexibility" URL from older blog posts gives you. Subset the icon names, and request only the axis ranges you actually animate.
5. Self-Hosting Material Symbols (Without Google Fonts)
Privacy policies, CSP font-src restrictions, or air-gapped environments often require self-hosting. Two things surprise everyone who tries it with Material Symbols:
- You must re-declare the CSS rendering rules yourself. The
.material-symbols-outlinedclass that the Google Fonts stylesheet provides is not in the font file — it is generated CSS. When you self-host, you write it. - You may need multiple font formats. Modern browsers only need
woff2, but the variable file is the one that preserves all four axes — a static instance export loses the variation capability.
/* Self-hosted Material Symbols: font + the rules Google's CDN used to give you */
@font-face {
font-family: 'Material Symbols Outlined';
font-style: normal;
font-weight: 100 700; /* variable weight range */
src: url('/fonts/material-symbols-outlined.woff2') format('woff2-variations');
font-display: block; /* same FOUC rule as the CDN */
}
.material-symbols-outlined {
font-family: 'Material Symbols Outlined';
font-weight: normal;
font-style: normal;
font-size: 24px;
line-height: 1;
letter-spacing: normal;
text-transform: none;
display: inline-block;
white-space: nowrap;
word-wrap: normal;
direction: ltr;
-webkit-font-smoothing: antialiased;
font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
}
The commercial alternative to maintaining that CSS by hand: skip the font entirely and self-host plain SVG files, one per icon — section 8 shows why that is the most robust architecture for 2026 component frameworks, and it is how every pre-rendered Material Symbols page on IconStash exports its icons.
6. React, Next.js, Vue & Angular: The npm Reality
This is where Material Symbols differs from every other major icon system: Google does not maintain an npm package for the repository past version 3, published in 2016. Google's own README says it plainly, and points to the community @marella packages that are automatically built and published from the source repository via GitHub Actions — while noting Google does not monitor or vet them.
Option A: The community font package (@marella/material-symbols)
npm install material-symbols
// main.jsx / _app.tsx — import the ONE style you use
import 'material-symbols/outlined.css';
// ❌ import 'material-symbols/index.css'
// index.css includes CSS for ALL font styles. Webpack (and most
// bundlers) will copy every font into your build output even if
// you only render outlined icons — a classic bundle bloat bug.
The per-style imports are the documented workaround for the bundler behavior above: outlined.css, rounded.css, or sharp.css — never index.css.
Option B: SVG components (React 19 / Next.js App Router recommended)
Because Material Symbols ships the complete SVG set in its repository, the modern approach is to render SVG components and treat the font as unnecessary. In a Next.js App Router project the icons are pure server-rendered markup — zero 'use client' directives, zero font payload, no FOUC window at all:
// app/components/Icon.tsx — RSC-safe, no font, no client JS
import type { SVGProps } from 'react';
export function Icon({ name, size = 24, ...props }: {
name: 'home' | 'search' | 'settings' | 'menu';
size?: number;
} & SVGProps<SVGSVGElement>) {
return (
<svg
width={size} height={size}
viewBox="0 0 24 24"
fill="currentColor"
aria-hidden="true"
{...props}
>
{paths[name]}
</svg>
);
}
Tree-shaking then works the way it should: an app importing five icons ships exactly five glyphs' path data, not 3,800. This is the same zero-font architecture we detail in SVG sprites vs inline SVG vs icon components, and it is compatible with every accessibility pattern in section 9.
Vue and Angular
Vue 3 / Nuxt and Angular projects can use the same community package with a global stylesheet import in the app entry, or the SVG approach with a tiny wrapper component. The font-vs-SVG trade-offs are framework-independent — the icon fonts vs SVG in 2026 benchmark covers the measurable differences for Vue/Nuxt, Angular and React/Next.js.
7. Material Icons (Classic): When the Frozen Set Still Wins
Legacy is not useless. The classic set still ships the most compact Google icon font ever made — 42 KB woff2 / 56 KB woff for all 900+ icons — and it is the only Google set with a Two tone style. Two cases where it remains the right call:
- Existing design systems already on it. The font is a constant 42 KB, works with ligatures and codepoints, and will never surprise you with a re-render. Migrating for migration's sake is a cost without benefit.
- Two-tone art direction. Material Symbols has no two-tone icons, period. If your product's visual language depends on them, the classic set (or the Ionicons two-tone family) is the only Google-sanctioned source.
<!-- Classic Material Icons: 900+ icons, 42 KB woff2, five fixed styles -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<span class="material-icons">home</span> <!-- filled (default) -->
<span class="material-icons-outlined">home</span> <!-- outlined -->
<span class="material-icons-round">home</span> <!-- round (NOT "rounded") -->
<span class="material-icons-sharp">home</span> <!-- sharp -->
<span class="material-icons-two-tone">home</span> <!-- two tone -->
For reference, Google's documentation notes the classic SVG files compress to roughly 62 KB gzipped as a full set — but individual SVGs, or a compiled sprite of only the icons you use, reduce that dramatically. Every classic icon is also pre-rendered for instant download on the Material Design Icons library page (14,001 icons), including popular glyphs like material-home and material-search.
8. The SVG Workflow: Zero Font Payload, No FOUC, Perfect Tree-Shaking
A fact that surprises even experienced developers: official SVG downloads do exist. Google Fonts' icon library lets you browse and download individual icons in SVG or PNG, and the google/material-design-icons repository contains the complete SVG set. The friction is workflow, not availability — there is no maintained npm distribution, no per-icon URL scheme documented for production, and no live customization.
That is exactly the gap IconStash was built to fill. Every Material Symbols variant is pre-rendered as an individual page with instant search across all 28 indexed libraries:
- Material Symbols — 18,547 icons (Apache 2.0), including home, search, settings and favorite.
- Material Symbols Light — 15,969 lighter-weight variants for large-format layouts.
- Material Design Icons — 14,001 classic icons (Apache 2.0), the two-tone source of record.
- Cross-library comparison — the same concept rendered side by side, e.g. the Material Icons vs Material Symbols comparison page and the concept hubs for home icons and menu icons.
The practical workflow: search the ligature name, preview at any size with live recoloring, and copy production-ready output in one click — plain SVG, rasterized PNG at 16–512px, or ready-pasted React JSX. No account, no npm install, and 94.5% of the catalog is MIT/Apache/ISC/CC0 with zero attribution required (Material Symbols is Apache 2.0 — see our icon licensing guide for what that permits).
<!-- The output: a real SVG, not a font glyph -->
<svg viewBox="0 0 24 24" width="24" height="24" fill="currentColor" aria-hidden="true">
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
</svg>
<!-- Recolor with CSS alone — impossible with icon-font fill hacks -->
<style>
.brand-icon { color: #C1DD2D; }
.brand-icon:hover { color: #D2ED3E; }
</style>
Because the asset is an SVG element, all the techniques that font-based icons can only approximate work natively: currentColor theming, CSS mask-image stencils, gradient fills, and dark-mode recoloring with a single custom property. We cover the full technique matrix in how to change SVG icon color in CSS and React.
9. Accessibility: Screen Readers, Ligature Fallbacks & Contrast
Icon fonts have a specific accessibility profile that SVGs solve structurally. The rules for Material Symbols:
- Decorative icons (about 90% of UI icons) must be hidden from assistive tech. With ligature text, an un-annotated
<span>home</span>is read aloud as the word "home" by screen readers — noise in every navigation. Mark them:
<!-- Decorative: the adjacent text label already conveys meaning -->
<span class="material-symbols-outlined" aria-hidden="true">home</span> Home
- Standalone interactive icons need a real accessible name. An icon-only button (hamburger menu, close) must carry the label itself:
<button aria-label="Open navigation menu">
<span class="material-symbols-outlined" aria-hidden="true">menu</span>
</button>
- Internet Explorer-era ligature fallbacks leak. In browsers without ligature support, the raw codepoint is invisible but the ligature text is not — legacy
docsguidance recommends codepoints for those browsers. In 2026 the practical takeaway is different: if you must support ancient browsers, SVGs sidestep the entire class of font-support bugs. - Use the GRAD axis for reversed contrast. White icons on dark backgrounds optically shrink;
'GRAD' -50is Google's documented compensation. It is a legibility setting, not decoration — pair it with WCAG 1.4.11 non-text contrast checks (3:1 against adjacent colors for meaningful icons).
SVG components make all four rules mechanical: aria-hidden="true" on decorative glyphs, a <title> or aria-label on interactive ones, and no text content to leak. The full vocabulary is in our SVG accessibility & WCAG glossary.
10. Migration Guide: Material Icons → Material Symbols Class Mapping
When the freeze finally pushes your team to Material Symbols, do not search-and-replace the word "icons". Map the classes explicitly, audit the two-tone orphans, and re-measure the font payload:
| Classic (Material Icons) | Current (Material Symbols) | Migration note |
|---|---|---|
material-icons |
material-symbols-outlined + 'FILL' 1 |
Filled look now comes from the FILL axis, not a separate class |
material-icons-outlined |
material-symbols-outlined |
Direct rename |
material-icons-round |
material-symbols-rounded |
"round" → "rounded" — the classic silent-break trap |
material-icons-sharp |
material-symbols-sharp |
Direct rename |
material-icons-two-tone |
No equivalent exists | Material Symbols has no two-tone style — redesign or keep the classic set |
| Codepoint addresses | Ligature names | Both still work; ligatures are the primary method |
Migration checklist
- Inventory your icons: export the list of ligature names in use — it becomes your
icon_namessubset (section 4). - Replace the stylesheet URL with the Material Symbols family and add
&display=block. - Apply the class mapping table above; grep for
-roundspecifically. - Flag two-tone usage and decide per-surface: redesign in Symbols or keep classic for those components.
- Re-run Lighthouse: confirm the 295 KB → 1.7 KB difference and check the FOUC fix on a throttled 3G profile.
- Verify against originals: spot-check rendered icons on the Material vs Material Symbols comparison or the per-icon pages such as materialsymbols-favorite.
11. Frequently Asked Questions
What is the difference between Material Icons and Material Symbols?
Material Symbols is Google's current icon set, introduced in April 2022 and built on variable font technology. Material Icons is the classic set, which has not received new icons since updates were halted in 2022. Material Symbols consolidates over 2,500 glyphs in a single variable font with four adjustable axes (FILL, wght, GRAD, opsz), while Material Icons ships static fonts in five fixed styles: filled, outlined, rounded, sharp, and two-tone.
How do I reduce the Material Symbols font payload from 295 KB?
Add the icon_names parameter to your Google Fonts CSS request to subset the font to only the icons you actually use. Loading the default stylesheet ships all 3,800+ icon variants at roughly 295 KB, but a request like ...&icon_names=home,palette,settings serves a font of about 1.7 KB. Avoid requesting the full axis ranges of all four axes: that URL returns a 7.9 MB font, which Google itself labels as not recommended.
Is Material Icons still updated in 2026?
No. Google halted Material Icons updates in 2022 and considers it the legacy set. New icons, variable fonts, extra weights, grades, and animated fill transitions only exist in Material Symbols. Google also stopped maintaining the official npm package after version 3 (2016); the community packages published by @marella are automatically built from source but are not vetted by Google.
How do I use Material Symbols in React or Next.js?
There is no Google-maintained npm package. The two reliable routes are: (1) the community @marella/material-symbols package, importing the per-style CSS file such as material-symbols/outlined.css so bundlers only copy one font instead of all of them; or (2) skip the font entirely and render SVG components, which works natively in React Server Components with zero 'use client' directives and no font payload.
Where can I download individual Material Symbols SVGs?
Google Fonts lets you browse and download individual icons in SVG or PNG format from the icon library page, and the google/material-design-icons repository contains the complete SVG set. IconStash pre-renders all 18,547 Material Symbols, 15,969 Material Symbols Light, and 14,001 Material Design Icons as individual pages with one-click SVG, PNG and JSX export, so you can grab exactly the icons you need without downloading a font at all.
Why were brand logos removed from Material Icons?
Google does not include third-party logos in Material Symbols or Material Icons due to legal reasons, and some brand logos that shipped in earlier versions have since been removed. If you need social media or brand logos, use a dedicated brand-icon set such as Simple Icons (3,400+ brand marks, CC0), which you can search and download from the IconStash Simple Icons library page.