no-font-face-in-selectors
Disallow @font-face rules nested inside regular CSS selectors.
Rule catalog ID: R034
Targeted pattern scopeโ
- Every
@font-faceblock that appears inside a regular CSS rule or selector.
What this rule reportsโ
@font-faceblocks that are nested inside selector contexts likebody {},.container {},#header {}, or similar.
This rule allows @font-face at the root level and inside at-rule blocks like
@media, @supports, @layer, and @container.
Why this rule existsโ
@font-face blocks should only appear at the root level (top of the stylesheet)
or inside at-rule blocks (@media, @supports, @layer, @container). When
nested inside a regular selector, critical issues occur:
-
Unexpected re-registration. Modern browsers may re-register or override the font family each time the selector matches, causing redundant work and potential rendering delays.
-
Scope confusion. Developers reading the code expect font definitions at the root. A nested
@font-faceis easy to miss and causes maintainability issues. -
CSS spec compliance. The CSS Fonts specification does not define behavior for
@font-faceinside selectors. Browsers may ignore the block, apply it inconsistently, or apply it with unexpected cascading side-effects. -
Performance impact. Each time a selector matches, the browser's CSS parser may re-evaluate the nested
@font-face, even though the registration should happen only once at load time.
Correct usage is to define all fonts at the stylesheet root or inside at-rules for conditional font loading.
โ Incorrectโ
/* @font-face nested inside a selector โ unpredictable behavior */
body {
@font-face {
font-family: "Inter";
src: url("./inter.woff2") format("woff2");
}
}
/* Nested inside a class selector */
.container {
@font-face {
font-family: "Roboto";
src: url("./roboto.woff2") format("woff2");
}
}
โ Correctโ
/* At the root level */
@font-face {
font-family: "Inter";
src: url("./inter.woff2") format("woff2");
}
body {
font-family: "Inter", sans-serif;
}
/* Inside an at-rule like @media */
@media (prefers-color-scheme: dark) {
@font-face {
font-family: "Inter Dark";
src: url("./inter-dark.woff2") format("woff2");
}
}
/* Inside @supports for conditional loading */
@supports (font-variation-settings: normal) {
@font-face {
font-family: "Inter Variable";
font-weight: 100 900;
src: url("./inter-variable.woff2") format("woff2-variations");
}
}
Stylelint config exampleโ
{ "font/no-font-face-in-selectors": true }