{"record":{"id":"ddd8065e6ca121ff","repo":"oxc-project/oxc","slug":"a-font-display-parameter-is-missing-adding-disp","errorCode":null,"errorMessage":"A font-display parameter is missing (adding `&display=optional` is recommended).","messagePattern":"A font-display parameter is missing \\(adding `&display=optional` is recommended\\)\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/nextjs/google_font_display.rs","lineNumber":14,"sourceCode":"use oxc_ast::{AstKind, ast::JSXElementName};\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_span::{GetSpan, Span};\n\nuse crate::{\n    AstNode,\n    context::LintContext,\n    rule::Rule,\n    utils::{find_url_query_value, get_string_literal_prop_value, has_jsx_prop_ignore_case},\n};\n\nfn font_display_parameter_missing(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\n        \"A font-display parameter is missing (adding `&display=optional` is recommended).\",\n    )\n    .with_help(\"See https://nextjs.org/docs/messages/google-font-display\")\n    .with_label(span)\n}\n\nfn not_recommended_font_display_value(span: Span, font_display_value: &str) -> OxcDiagnostic {\n    OxcDiagnostic::warn(format!(\"`{font_display_value}` is not a recommended font-display value.\"))\n        .with_help(\"See https://nextjs.org/docs/messages/google-font-display\")\n        .with_label(span)\n}\n\n#[derive(Debug, Default, Clone)]\npub struct GoogleFontDisplay;\n\ndeclare_oxc_lint!(\n    /// ### What it does\n    ///","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/nextjs/google_font_display.rs#L1-L32","documentation":"This is the `nextjs/google-font-display` rule in oxlint. It fires when a `<link>` whose `href` starts with `https://fonts.googleapis.com/css` has no `display` query parameter. Without `display=`, the Google Fonts CSS defaults to `font-display: auto`/block behavior, risking invisible text (FOIT) and layout shift during font loading; `optional` avoids both.","triggerScenarios":"A JSX `<link>` element with a string-literal `href` beginning with `https://fonts.googleapis.com/css` where `find_url_query_value(href, \"display\")` returns None — e.g. `href=\"https://fonts.googleapis.com/css2?family=Krona+One\"` inside `next/head` or `next/document`.","commonSituations":"Adding Google Fonts via raw `<link>` tags instead of `next/font`; copying font snippets from Google Fonts' UI (which defaults to no display or `display=swap`); App Router/Docs examples pasted without the display param; CI lint gates failing on new font integrations.","solutions":["Append `&display=optional` (recommended) to the Google Fonts CSS URL.","If swapping in the font after load matters visually, use `&display=swap` (also passes this rule).","Better: switch to `next/font/google`, which handles font-display and self-hosting automatically."],"exampleFix":"// before\n<link href=\"https://fonts.googleapis.com/css2?family=Krona+One\" rel=\"stylesheet\" />\n\n// after\n<link href=\"https://fonts.googleapis.com/css2?family=Krona+One&display=optional\" rel=\"stylesheet\" />","handlingStrategy":"validation","validationCode":"npx oxlint --nextjs/google-font-display src/ # or: rg -n 'fonts\\.googleapis\\.com/css[^\"']*\"\\s' --glob '*.tsx' -P '(?<!display=[a-z]+)' src/","typeGuard":"const hasFontDisplay = (href: string) =>\n  /[?&]display=(optional|swap)/.test(href);","tryCatchPattern":null,"preventionTips":["Always end Google Fonts URLs with &display=optional (or swap).","Prefer next/font/google, which sets font-display and self-hosts fonts.","Add this rule to CI so new font links fail fast."],"tags":["nextjs","performance","fonts","core-web-vitals","lint"],"backgroundTag":"google-font-display","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}