Skip to main content

no-hardcoded-docusaurus-breakpoint-values

Disallow hardcoded pixel values in @media queries that match Docusaurus/Infima documented breakpoints.

Targeted pattern scopeโ€‹

This rule inspects every @media at-rule's query parameters and flags any literal px value that matches one of the documented Docusaurus/Infima breakpoints:

ValueDocusaurus meaning
576pxInfima small breakpoint (--ifm-breakpoint-sm)
768pxInfima medium breakpoint (--ifm-breakpoint-md)
992pxInfima large breakpoint (--ifm-breakpoint-lg)
996pxJS MOBILE_TOGGLE_BREAKPOINT โ€” where the navbar switches from mobile to desktop layout
997pxInternal docusaurusDesktopNavbarMinWidthPx โ€” CSS counterpart to the JS toggle
1200pxInfima extra-large breakpoint (--ifm-breakpoint-xl)
1400pxInfima extra-extra-large breakpoint (--ifm-breakpoint-xxl)

The rule flags both min-width and max-width usage as well as modern range-syntax queries.

What this rule reportsโ€‹

Any @media at-rule whose query string contains one of the above hardcoded pixel values triggers a warning โ€” unless the value appears in the ignoreBreakpoints secondary option.

Why this rule existsโ€‹

Hardcoding these values creates a silent regression vector. The most dangerous example is 992px vs 996px: both look like plausible "large screen" breakpoints, but Docusaurus's JavaScript fires the mobile-toggle logic at exactly 996px. A CSS rule written at 992px will visually desync from the JS behavior โ€” the CSS will switch layout 4px before the sidebar/navbar JavaScript does, causing a brief flash where CSS and JS are out of step.

Centralizing breakpoints in a SCSS variable, custom property, or a shared design-token avoids this class of bug entirely.

โŒ Incorrectโ€‹

/* 996px is the Docusaurus JS mobile-toggle boundary โ€” hardcoded here */
@media (max-width: 996px) {
.custom-nav {
display: none;
}
}
/* 768px matches the Infima medium breakpoint โ€” fragile hardcode */
@media screen and (min-width: 768px) {
.sidebar {
width: 300px;
}
}
/* Dangerous: 992px is NOT the Docusaurus breakpoint (996px is) */
@media (max-width: 992px) {
.navbar__toggle {
display: block;
}
}

โœ… Correctโ€‹

// SCSS: extract to a variable
$breakpoint-mobile: 996px;

@media (max-width: #{$breakpoint-mobile}) {
.custom-nav {
display: none;
}
}
/* Container query โ€” not a Docusaurus breakpoint */
@media (min-width: 600px) {
.widget {
flex-direction: row;
}
}
/* @media that does not reference a known breakpoint value */
@media (prefers-reduced-motion: reduce) {
* {
transition: none;
}
}

Behavior and migration notesโ€‹

  • Only literal px values are checked; em and rem equivalents are not flagged (they do not appear in Docusaurus's documented breakpoint table).
  • The rule is report-only; no autofix rewrites @media parameters.
  • All 7 breakpoint values in the set have a documented Docusaurus/Infima meaning.

Additional examplesโ€‹

Exempting a specific breakpoint with ignoreBreakpointsโ€‹

An array of breakpoint strings to exempt from reporting. Useful when you intentionally need to match a Docusaurus breakpoint and have documented the reasoning.

// stylelint.config.mjs
export default {
rules: {
"docusaurus/no-hardcoded-docusaurus-breakpoint-values": [
true,
{ ignoreBreakpoints: ["768px"] }
]
}
};

โœ… Correct โ€” modern range syntax without a known breakpoint valueโ€‹

@media (width <= 600px) {
.widget {
flex-direction: column;
}
}

โŒ Incorrect โ€” modern range syntax with a known breakpoint valueโ€‹

@media (width <= 996px) {
.mobile-panel {
display: block;
}
}

Stylelint config exampleโ€‹

import { docusaurusPluginConfigs } from "stylelint-plugin-docusaurus";

export default {
plugins: ["stylelint-plugin-docusaurus"],
rules: {
"docusaurus/no-hardcoded-docusaurus-breakpoint-values": true
}
};

When not to use itโ€‹

Disable this rule if your project intentionally duplicates Docusaurus breakpoint values and has a build-time mechanism (for example a design-token pipeline) that guarantees they stay in sync.

Further readingโ€‹

Rule catalog ID: R028