Skip to main content

no-unused-font-face

Disallow @font-face blocks whose font-family name is never referenced in any font-family declaration.

Rule catalog ID: R040

Targeted pattern scopeโ€‹

  • @font-face at-rules whose declared font-family is never used.

What this rule reportsโ€‹

This rule reports @font-face blocks where the font-family value is not referenced by any font-family declaration in the same stylesheet. Unreferenced @font-face blocks waste bandwidth because the font file will still be loaded by some browsers even when the family is never applied.

The check is file-scoped: it only compares @font-face declarations and font-family properties within the same CSS file. Cross-file references (from HTML, JavaScript, or other stylesheets) are not visible to a static CSS linter.

Declarations that use CSS custom properties (var(...)) are excluded from the reference check because their runtime values cannot be statically resolved.

Why this rule existsโ€‹

Unused @font-face blocks accumulate over time as designs change but old declarations are not cleaned up. Even a single unused @font-face can add hundreds of kilobytes to a page's font payload. A lint rule catches these regressions before they ship.

โŒ Incorrectโ€‹

/* @font-face is declared but no rule ever sets font-family: "Inter" */
@font-face {
font-family: "Inter";
src: url("./inter.woff2") format("woff2");
}

.title {
font-family: "Roboto", system-ui;
}
/* Standalone @font-face file with no matching usage */
@font-face {
font-family: "Old Font";
src: url("./old-font.woff2") format("woff2");
}

โœ… Correctโ€‹

@font-face {
font-family: "Inter";
src: url("./inter.woff2") format("woff2");
}

.title {
font-family: "Inter", system-ui;
}
/* CSS custom property โ€” the variable may resolve to "Inter" at runtime,
so the @font-face block is not flagged */
@font-face {
font-family: "Inter";
src: url("./inter.woff2") format("woff2");
}

:root {
--brand-font: "Inter";
}

.title {
font-family: var(--brand-font), system-ui;
}

Stylelint config exampleโ€‹

import fontPlugin from "stylelint-plugin-font";

export default {
plugins: [...fontPlugin],
rules: {
"font/no-unused-font-face": true,
},
};

When not to use itโ€‹

Disable this rule when:

  • You maintain dedicated font-face definition files that are @imported into other stylesheets where the families are used. The rule only sees declarations within a single file.
  • Fonts are loaded via a CSS-in-JS solution, design token system, or CMS where font-family references never appear as plain CSS property declarations.
  • You intentionally preload fonts for future use (though removing the preload when removing the @font-face is still recommended).

Further readingโ€‹