[{"data":1,"prerenderedAt":1110},["ShallowReactive",2],{"content:\u002Fframework-performance\u002Fnextjs-performance\u002Feliminating-font-cls-with-next-font":3,"surroundings:\u002Fframework-performance\u002Fnextjs-performance\u002Feliminating-font-cls-with-next-font":1101},{"id":4,"title":5,"body":6,"description":1080,"extension":1081,"meta":1082,"navigation":1094,"path":1095,"seo":1096,"stem":1099,"__hash__":1100},"content\u002Fframework-performance\u002Fnextjs-performance\u002Feliminating-font-cls-with-next-font\u002Findex.md","Eliminating Font CLS with next\u002Ffont",{"type":7,"value":8,"toc":1061},"minimark",[9,14,29,55,167,172,208,212,218,224,230,236,240,245,484,488,498,502,558,562,573,654,658,661,665,671,675,694,698,719,852,856,862,866,892,896,902,908,919,929,933,945,954,966,975,987,999,1008,1020,1024,1046,1051,1054,1057],[10,11,13],"h1",{"id":12},"how-to-eliminate-font-cls-with-nextfont","How to Eliminate Font CLS with next\u002Ffont",[15,16,17,18,23,24,28],"p",{},"This guide is part of ",[19,20,22],"a",{"href":21},"\u002Fframework-performance\u002Fnextjs-performance\u002F","Next.js Performance",", within ",[19,25,27],{"href":26},"\u002Fframework-performance\u002F","Framework Performance",". Web fonts cause two kinds of performance problems. Loaded from a third-party stylesheet (such as Google Fonts' CSS API), they add render-blocking CSS on another origin and delay text rendering. When they arrive, they replace the fallback font, and because fallback and web font have different metrics (character widths, ascent, line height), text reflows — a layout shift that counts towards CLS. On text-heavy pages, font swaps are one of the most common sources of CLS.",[15,30,31,35,36,39,40,43,44,43,47,50,51,54],{},[32,33,34],"code",{},"next\u002Ffont"," addresses both. It downloads Google Fonts (or uses local font files) at build time and self-hosts them with the app, so there is no third-party request. It preloads the font files, and it generates a fallback ",[32,37,38],{},"@font-face"," using ",[32,41,42],{},"size-adjust",", ",[32,45,46],{},"ascent-override",[32,48,49],{},"descent-override"," and ",[32,52,53],{},"line-gap-override",", so the fallback font occupies nearly the same space as the web font. When the web font loads, text barely moves.",[15,56,57],{},[58,59,65,66,65,73,65,77,65,80,65,89,65,95,65,104,65,110,65,115,65,120,65,123,65,126,65,129,65,132,65,135,65,138,65,143,65,146,65,148,65,152,65,154,65,157,65,159,65,162,65,164,65],"svg",{"viewBox":60,"width":61,"role":62,"ariaLabel":63,"style":64},"0 0 760 228","100%","img","Comparison of loading fonts from the Google Fonts CSS API with self-hosting them through next\u002Ffont.","height:auto;max-width:760px;display:block;margin:1.75rem auto;font-family:inherit;color:var(--fp-svg-ink)"," ",[67,68],"rect",{"className":69,"x":71,"y":71,"width":61,"height":61,"fill":72},[70],"svg-canvas","0","#ffffff",[74,75,76],"title",{},"Google Fonts stylesheet vs next\u002Ffont",[78,79,63],"desc",{},[67,81],{"x":82,"y":82,"width":83,"height":84,"rx":85,"fill":86,"stroke":87,"style":88},"1","758","226","10","none","currentColor","stroke-opacity:0.18",[90,91,76],"text",{"x":92,"y":93,"fill":87,"style":94},"28.0","34.0","font-size:16px;font-weight:700",[67,96],{"x":92,"y":97,"width":98,"height":99,"rx":100,"fill":101,"stroke":102,"style":103},"56.0","340.0","150.0","6","#ffc300","#b8860b","fill-opacity:0.24;stroke-opacity:0.9",[90,105,109],{"x":106,"y":107,"fill":87,"style":108},"42.0","82.0","font-size:14px;font-weight:700","Google Fonts stylesheet",[90,111,114],{"x":106,"y":112,"fill":87,"style":113},"108.0","font-size:12.5px;font-weight:700","•",[90,116,119],{"x":97,"y":112,"fill":87,"style":117,"textAnchor":118},"font-size:12.5px","start","Render-blocking CSS on another origin",[90,121,114],{"x":106,"y":122,"fill":87,"style":113},"132.0",[90,124,125],{"x":97,"y":122,"fill":87,"style":117,"textAnchor":118},"Extra DNS, TCP and TLS setup",[90,127,114],{"x":106,"y":128,"fill":87,"style":113},"156.0",[90,130,131],{"x":97,"y":128,"fill":87,"style":117,"textAnchor":118},"Fallback metrics differ from web font",[90,133,114],{"x":106,"y":134,"fill":87,"style":113},"180.0",[90,136,137],{"x":97,"y":134,"fill":87,"style":117,"textAnchor":118},"Text reflows when font loads (CLS)",[67,139],{"x":140,"y":97,"width":98,"height":99,"rx":100,"fill":141,"stroke":141,"style":142},"392.0","#0466c8","fill-opacity:0.14;stroke-opacity:0.9",[90,144,34],{"x":145,"y":107,"fill":87,"style":108},"406.0",[90,147,114],{"x":145,"y":112,"fill":87,"style":113},[90,149,151],{"x":150,"y":112,"fill":87,"style":117,"textAnchor":118},"420.0","Fonts self-hosted with the app",[90,153,114],{"x":145,"y":122,"fill":87,"style":113},[90,155,156],{"x":150,"y":122,"fill":87,"style":117,"textAnchor":118},"Preloaded, same origin",[90,158,114],{"x":145,"y":128,"fill":87,"style":113},[90,160,161],{"x":150,"y":128,"fill":87,"style":117,"textAnchor":118},"Size-adjusted fallback font-face",[90,163,114],{"x":145,"y":134,"fill":87,"style":113},[90,165,166],{"x":150,"y":134,"fill":87,"style":117,"textAnchor":118},"Minimal shift when font swaps",[168,169,171],"h2",{"id":170},"rapid-diagnosis","Rapid Diagnosis",[173,174,175,190,196,202],"ul",{},[176,177,178,185,186,189],"li",{},[179,180,181,182],"strong",{},"Check for ",[32,183,184],{},"fonts.googleapis.com"," links or ",[32,187,188],{},"@import"," in CSS.",[176,191,192,195],{},[179,193,194],{},"Check CLS attribution",": shifts of text blocks at the moment fonts load.",[176,197,198,201],{},[179,199,200],{},"Record a filmstrip",": visible text reflow when the web font appears.",[176,203,204,207],{},[179,205,206],{},"Check font file count and size",": many weights and styles add download time.",[168,209,211],{"id":210},"root-cause-analysis","Root Cause Analysis",[15,213,214,217],{},[179,215,216],{},"1. Third-party font CSS."," Render-blocking and late font discovery.",[15,219,220,223],{},[179,221,222],{},"2. Metric mismatch."," Fallback fonts take different space than web fonts.",[15,225,226,229],{},[179,227,228],{},"3. Too many font files."," Every weight and style is a separate download.",[15,231,232,235],{},[179,233,234],{},"4. No preload."," Fonts discovered only after CSS is parsed.",[168,237,239],{"id":238},"step-by-step-resolution","Step-by-Step Resolution",[241,242,244],"h3",{"id":243},"_1-load-fonts-with-nextfont","1. Load fonts with next\u002Ffont",[246,247,252],"pre",{"className":248,"code":249,"language":250,"meta":251,"style":251},"language-javascript shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","\u002F\u002F app\u002Flayout.js\nimport { Inter, Source_Serif_4 } from 'next\u002Ffont\u002Fgoogle';\nconst inter = Inter({ subsets: ['latin'], display: 'swap', variable: '--font-sans' });\nconst serif = Source_Serif_4({ subsets: ['latin'], weight: ['400', '600'], variable: '--font-serif' });\nexport default function RootLayout({ children }) {\n  return (\u003Chtml lang=\"en\" className={`${inter.variable} ${serif.variable}`}>\u003Cbody>{children}\u003C\u002Fbody>\u003C\u002Fhtml>);\n}\n\u002F\u002F trade-off: each additional family and weight adds preloaded bytes; prefer one\n\u002F\u002F variable font for the body text and limit display fonts to what pages use.\n","javascript","",[32,253,254,263,284,322,358,380,466,472,478],{"__ignoreMap":251},[255,256,259],"span",{"class":257,"line":258},"line",1,[255,260,262],{"class":261},"sjfSM","\u002F\u002F app\u002Flayout.js\n",[255,264,266,270,274,277,281],{"class":257,"line":265},2,[255,267,269],{"class":268},"sPARh","import",[255,271,273],{"class":272},"saISM"," { Inter, Source_Serif_4 } ",[255,275,276],{"class":268},"from",[255,278,280],{"class":279},"sZ8jY"," 'next\u002Ffont\u002Fgoogle'",[255,282,283],{"class":272},";\n",[255,285,287,290,294,297,301,304,307,310,313,316,319],{"class":257,"line":286},3,[255,288,289],{"class":268},"const",[255,291,293],{"class":292},"sPXB4"," inter",[255,295,296],{"class":268}," =",[255,298,300],{"class":299},"smZ65"," Inter",[255,302,303],{"class":272},"({ subsets: [",[255,305,306],{"class":279},"'latin'",[255,308,309],{"class":272},"], display: ",[255,311,312],{"class":279},"'swap'",[255,314,315],{"class":272},", variable: ",[255,317,318],{"class":279},"'--font-sans'",[255,320,321],{"class":272}," });\n",[255,323,325,327,330,332,335,337,339,342,345,347,350,353,356],{"class":257,"line":324},4,[255,326,289],{"class":268},[255,328,329],{"class":292}," serif",[255,331,296],{"class":268},[255,333,334],{"class":299}," Source_Serif_4",[255,336,303],{"class":272},[255,338,306],{"class":279},[255,340,341],{"class":272},"], weight: [",[255,343,344],{"class":279},"'400'",[255,346,43],{"class":272},[255,348,349],{"class":279},"'600'",[255,351,352],{"class":272},"], variable: ",[255,354,355],{"class":279},"'--font-serif'",[255,357,321],{"class":272},[255,359,361,364,367,370,373,377],{"class":257,"line":360},5,[255,362,363],{"class":268},"export",[255,365,366],{"class":268}," default",[255,368,369],{"class":268}," function",[255,371,372],{"class":299}," RootLayout",[255,374,376],{"class":375},"sQw3B","({ children }) ",[255,378,379],{"class":272},"{\n",[255,381,383,386,389,393,396,399,402,405,408,411,414,417,420,423,426,428,430,433,436,439,442,445,448,451,453,456,458,461,463],{"class":257,"line":382},6,[255,384,385],{"class":268},"  return",[255,387,388],{"class":272}," (\u003C",[255,390,392],{"class":391},"sZBmE","html",[255,394,395],{"class":292}," lang",[255,397,398],{"class":268},"=",[255,400,401],{"class":279},"\"en\"",[255,403,404],{"class":292}," className",[255,406,407],{"class":268},"={",[255,409,410],{"class":279},"`${",[255,412,413],{"class":272},"inter",[255,415,416],{"class":279},".",[255,418,419],{"class":272},"variable",[255,421,422],{"class":279},"} ${",[255,424,425],{"class":272},"serif",[255,427,416],{"class":279},[255,429,419],{"class":272},[255,431,432],{"class":279},"}`",[255,434,435],{"class":268},"}",[255,437,438],{"class":272},">\u003C",[255,440,441],{"class":391},"body",[255,443,444],{"class":272},">",[255,446,447],{"class":268},"{",[255,449,450],{"class":272},"children",[255,452,435],{"class":268},[255,454,455],{"class":272},"\u003C\u002F",[255,457,441],{"class":391},[255,459,460],{"class":272},">\u003C\u002F",[255,462,392],{"class":391},[255,464,465],{"class":272},">);\n",[255,467,469],{"class":257,"line":468},7,[255,470,471],{"class":272},"}\n",[255,473,475],{"class":257,"line":474},8,[255,476,477],{"class":261},"\u002F\u002F trade-off: each additional family and weight adds preloaded bytes; prefer one\n",[255,479,481],{"class":257,"line":480},9,[255,482,483],{"class":261},"\u002F\u002F variable font for the body text and limit display fonts to what pages use.\n",[241,485,487],{"id":486},"_2-use-css-variables-in-styles","2. Use CSS variables in styles",[15,489,490,491,50,494,497],{},"Reference ",[32,492,493],{},"var(--font-sans)",[32,495,496],{},"var(--font-serif)"," in your CSS or Tailwind configuration, so the generated font-face and fallback are used consistently.",[241,499,501],{"id":500},"_3-use-local-fonts-for-custom-typefaces","3. Use local fonts for custom typefaces",[246,503,505],{"className":248,"code":504,"language":250,"meta":251,"style":251},"import localFont from 'next\u002Ffont\u002Flocal';\nconst brand = localFont({ src: [{ path: '.\u002Ffonts\u002FBrand-Var.woff2', weight: '100 900' }], variable: '--font-brand', display: 'swap' });\n",[32,506,507,521],{"__ignoreMap":251},[255,508,509,511,514,516,519],{"class":257,"line":258},[255,510,269],{"class":268},[255,512,513],{"class":272}," localFont ",[255,515,276],{"class":268},[255,517,518],{"class":279}," 'next\u002Ffont\u002Flocal'",[255,520,283],{"class":272},[255,522,523,525,528,530,533,536,539,542,545,548,551,554,556],{"class":257,"line":265},[255,524,289],{"class":268},[255,526,527],{"class":292}," brand",[255,529,296],{"class":268},[255,531,532],{"class":299}," localFont",[255,534,535],{"class":272},"({ src: [{ path: ",[255,537,538],{"class":279},"'.\u002Ffonts\u002FBrand-Var.woff2'",[255,540,541],{"class":272},", weight: ",[255,543,544],{"class":279},"'100 900'",[255,546,547],{"class":272}," }], variable: ",[255,549,550],{"class":279},"'--font-brand'",[255,552,553],{"class":272},", display: ",[255,555,312],{"class":279},[255,557,321],{"class":272},[241,559,561],{"id":560},"_4-limit-subsets-weights-and-preloads","4. Limit subsets, weights and preloads",[15,563,564,565,568,569,572],{},"Load only the subsets you need (for example ",[32,566,567],{},"latin","), prefer variable fonts over multiple static weights, and set ",[32,570,571],{},"preload: false"," for fonts used only below the fold or on few pages.",[15,574,575],{},[58,576,65,579,65,582,65,585,65,587,65,590,65,592,65,601,65,608,65,616,65,621,65,625,65,630,65,634,65,638,65,643,65,647,65],{"viewBox":577,"width":61,"role":62,"ariaLabel":578,"style":64},"0 0 760 185","Bar chart comparing CLS at the 75th percentile with Google Fonts stylesheet loading and with next\u002Ffont.",[67,580],{"className":581,"x":71,"y":71,"width":61,"height":61,"fill":72},[70],[74,583,584],{},"CLS from font swap on an article template (p75)",[78,586,578],{},[67,588],{"x":82,"y":82,"width":83,"height":589,"rx":85,"fill":86,"stroke":87,"style":88},"183",[90,591,584],{"x":92,"y":93,"fill":87,"style":94},[257,593],{"x1":594,"y1":595,"x2":594,"y2":596,"stroke":102,"strokeWidth":597,"strokeDashArray":598,"style":600},"542.4","72.0","163.0","1.5",[599,599],"4","stroke-opacity:0.9",[90,602,607],{"x":603,"y":604,"fill":87,"style":605,"textAnchor":606},"216.3","92.0","font-size:13px","end","Google Fonts CSS, display swap",[67,609],{"x":610,"y":611,"width":612,"height":613,"rx":614,"fill":86,"stroke":87,"style":615},"228.3","78.0","439.7","19","3","fill-opacity:0.7;stroke-opacity:0.35",[90,617,620],{"x":618,"y":604,"fill":87,"style":619},"674.0","font-size:12px;font-weight:600","140CLS x 1000",[90,622,624],{"x":603,"y":623,"fill":87,"style":605,"textAnchor":606},"123.0","Self-hosted, no fallback adjust",[67,626],{"x":610,"y":627,"width":628,"height":613,"rx":614,"fill":141,"stroke":141,"style":629},"109.0","298.3","fill-opacity:0.55;stroke-opacity:0.9",[90,631,633],{"x":632,"y":623,"fill":87,"style":619},"532.7","95CLS x 1000",[90,635,637],{"x":603,"y":636,"fill":87,"style":605,"textAnchor":606},"154.0","next\u002Ffont (adjusted fallback)",[67,639],{"x":610,"y":640,"width":641,"height":613,"rx":614,"fill":101,"stroke":102,"style":642},"140.0","37.7","fill-opacity:0.7;stroke-opacity:0.9",[90,644,646],{"x":645,"y":636,"fill":87,"style":619},"272.0","12CLS x 1000",[90,648,653],{"x":594,"y":649,"fill":650,"style":651,"textAnchor":652},"68.0","#8a6608","font-size:12px;font-weight:700","middle","CLS good (0.1)",[168,655,657],{"id":656},"verification","Verification",[15,659,660],{},"In DevTools, confirm fonts load from your own origin and are preloaded (initiator: preload). Record the page with a slow connection and check the filmstrip: text should not visibly reflow when the font loads. Check the layout shift entries: no shifts attributed to text blocks at font load. In the field, CLS p75 for text-heavy templates should drop.",[168,662,664],{"id":663},"worked-example-a-blog-platform","Worked Example: A Blog Platform",[15,666,667,668,670],{},"A blog platform loaded two Google Fonts families (four weights each) through a stylesheet link. CLS p75 on article pages was 0.14, mostly from font swaps in headlines and body text, and the font CSS added 250ms of render-blocking time on mobile. Switching to ",[32,669,34],{}," with a variable body font and one display font weight cut font downloads from eight files to two, removed the third-party connection, and the generated fallbacks reduced font-related shifts to near zero. CLS p75 fell to 0.03 and FCP improved by 280ms.",[168,672,674],{"id":673},"how-the-fallback-adjustment-works","How the Fallback Adjustment Works",[15,676,677,679,680,682,683,685,686,689,690,693],{},[32,678,34],{}," computes metrics for the web font and generates a fallback ",[32,681,38],{}," that points at a system font (such as Arial or Times New Roman) with ",[32,684,42],{}," (scales glyph widths) and ascent\u002Fdescent\u002Fline-gap overrides (vertical metrics) chosen to match the web font. The fallback is listed after the web font in the generated ",[32,687,688],{},"font-family",". During loading, text renders in the adjusted fallback, occupying almost exactly the space it will take in the web font. The swap still changes the glyph shapes, but not the layout. For custom local fonts, ",[32,691,692],{},"adjustFontFallback"," can be configured, and for unusual typefaces, manual tuning may still be needed.",[168,695,697],{"id":696},"choosing-font-display","Choosing font-display",[15,699,700,703,704,707,708,711,712,715,716,718],{},[32,701,702],{},"display: 'swap'"," shows fallback text immediately and swaps when the font arrives — good for content, and with adjusted fallbacks, nearly shift-free. ",[32,705,706],{},"optional"," uses the web font only if it is available almost immediately (cached or very fast), otherwise sticks with the fallback for that page view, eliminating swaps entirely at the cost of sometimes not showing the web font. ",[32,709,710],{},"block"," hides text briefly while waiting, which can delay LCP for text elements. Most sites should use ",[32,713,714],{},"swap"," with adjusted fallbacks; ",[32,717,706],{}," suits sites that prioritise stability over brand typography on slow first visits.",[15,720,721],{},[58,722,65,724,65,727,65,730,65,732,65,734,65,736,65,741,65,746,65,750,65,754,65,757,65,761,65,764,65,768,65,772,65,775,65,777,65,781,65,783,65,786,65,788,65,791,65,794,65,797,65,799,65,801,65,803,65,805,65,807,65,810,65,813,65,816,65,818,65,821,65,823,65,826,65,828,65,831,65,834,65,838,65,840,65,843,65,845,65,847,65,849,65],{"viewBox":60,"width":61,"role":62,"ariaLabel":723,"style":64},"How font-display values behave and when to use them.",[67,725],{"className":726,"x":71,"y":71,"width":61,"height":61,"fill":72},[70],[74,728,729],{},"font-display options with next\u002Ffont",[78,731,723],{},[67,733],{"x":82,"y":82,"width":83,"height":84,"rx":85,"fill":86,"stroke":87,"style":88},[90,735,729],{"x":92,"y":93,"fill":87,"style":94},[67,737],{"x":92,"y":97,"width":738,"height":739,"rx":71,"fill":87,"stroke":87,"style":740},"66.8","30.0","fill-opacity:0.06;stroke-opacity:0.4",[90,742,745],{"x":743,"y":744,"fill":87,"style":113,"textAnchor":118},"38.0","75.5","Value",[67,747],{"x":748,"y":97,"width":749,"height":739,"rx":71,"fill":87,"stroke":87,"style":740},"94.8","212.4",[90,751,753],{"x":752,"y":744,"fill":87,"style":113,"textAnchor":652},"201.0","Text visible immediately",[67,755],{"x":756,"y":97,"width":749,"height":739,"rx":71,"fill":87,"stroke":87,"style":740},"307.2",[90,758,760],{"x":759,"y":744,"fill":87,"style":113,"textAnchor":652},"413.4","Swap shift risk",[67,762],{"x":763,"y":97,"width":749,"height":739,"rx":71,"fill":87,"stroke":87,"style":740},"519.6",[90,765,767],{"x":766,"y":744,"fill":87,"style":113,"textAnchor":652},"625.8","Use when",[67,769],{"x":92,"y":770,"width":738,"height":739,"rx":71,"fill":86,"stroke":87,"style":771},"86.0","stroke-opacity:0.35",[90,773,714],{"x":743,"y":774,"fill":87,"style":113,"textAnchor":118},"105.5",[67,776],{"x":748,"y":770,"width":749,"height":739,"rx":71,"fill":141,"stroke":141,"style":142},[90,778,780],{"x":752,"y":774,"fill":87,"style":779,"textAnchor":652},"font-size:12px","yes",[67,782],{"x":756,"y":770,"width":749,"height":739,"rx":71,"fill":87,"stroke":87,"style":740},[90,784,785],{"x":759,"y":774,"fill":87,"style":779,"textAnchor":652},"low with adjusted fallback",[67,787],{"x":763,"y":770,"width":749,"height":739,"rx":71,"fill":86,"stroke":87,"style":771},[90,789,790],{"x":766,"y":774,"fill":87,"style":779,"textAnchor":652},"most sites",[67,792],{"x":92,"y":793,"width":738,"height":739,"rx":71,"fill":86,"stroke":87,"style":771},"116.0",[90,795,706],{"x":743,"y":796,"fill":87,"style":113,"textAnchor":118},"135.5",[67,798],{"x":748,"y":793,"width":749,"height":739,"rx":71,"fill":141,"stroke":141,"style":142},[90,800,780],{"x":752,"y":796,"fill":87,"style":779,"textAnchor":652},[67,802],{"x":756,"y":793,"width":749,"height":739,"rx":71,"fill":141,"stroke":141,"style":142},[90,804,86],{"x":759,"y":796,"fill":87,"style":779,"textAnchor":652},[67,806],{"x":763,"y":793,"width":749,"height":739,"rx":71,"fill":86,"stroke":87,"style":771},[90,808,809],{"x":766,"y":796,"fill":87,"style":779,"textAnchor":652},"stability first",[67,811],{"x":92,"y":812,"width":738,"height":739,"rx":71,"fill":86,"stroke":87,"style":771},"146.0",[90,814,710],{"x":743,"y":815,"fill":87,"style":113,"textAnchor":118},"165.5",[67,817],{"x":748,"y":812,"width":749,"height":739,"rx":71,"fill":101,"stroke":102,"style":103},[90,819,820],{"x":752,"y":815,"fill":87,"style":779,"textAnchor":652},"briefly hidden",[67,822],{"x":756,"y":812,"width":749,"height":739,"rx":71,"fill":87,"stroke":87,"style":740},[90,824,825],{"x":759,"y":815,"fill":87,"style":779,"textAnchor":652},"low",[67,827],{"x":763,"y":812,"width":749,"height":739,"rx":71,"fill":86,"stroke":87,"style":771},[90,829,830],{"x":766,"y":815,"fill":87,"style":779,"textAnchor":652},"icon fonts (avoid)",[67,832],{"x":92,"y":833,"width":738,"height":739,"rx":71,"fill":86,"stroke":87,"style":771},"176.0",[90,835,837],{"x":743,"y":836,"fill":87,"style":113,"textAnchor":118},"195.5","fallback",[67,839],{"x":748,"y":833,"width":749,"height":739,"rx":71,"fill":141,"stroke":141,"style":142},[90,841,842],{"x":752,"y":836,"fill":87,"style":779,"textAnchor":652},"after short block",[67,844],{"x":756,"y":833,"width":749,"height":739,"rx":71,"fill":87,"stroke":87,"style":740},[90,846,825],{"x":759,"y":836,"fill":87,"style":779,"textAnchor":652},[67,848],{"x":763,"y":833,"width":749,"height":739,"rx":71,"fill":86,"stroke":87,"style":771},[90,850,851],{"x":766,"y":836,"fill":87,"style":779,"textAnchor":652},"compromise",[168,853,855],{"id":854},"auditing-fonts-across-an-app","Auditing Fonts Across an App",[15,857,858,859,861],{},"Font usage grows over time: a marketing page adds a display face, a component library brings its own font, a blog template uses a different weight. Each family and weight adds preloaded bytes or later downloads. Periodically list the fonts loaded on key pages (DevTools Network panel, filtered by Font) and compare with the design system. Consolidate to one variable font for text and at most one display font, define them once in the root layout, and expose them as CSS variables used everywhere. Remove stray ",[32,860,38],{}," rules and stylesheet links left from earlier implementations, which can quietly reintroduce third-party requests and unadjusted fallbacks.",[168,863,865],{"id":864},"common-mistakes","Common Mistakes",[173,867,868,874,880,886],{},[176,869,870,873],{},[179,871,872],{},"Keeping the Google Fonts link alongside next\u002Ffont."," Double downloads.",[176,875,876,879],{},[179,877,878],{},"Loading many static weights."," Use a variable font.",[176,881,882,885],{},[179,883,884],{},"Applying fonts via class names inconsistently."," Some text uses the unadjusted family.",[176,887,888,891],{},[179,889,890],{},"Preloading fonts used rarely."," Wastes bandwidth on every page.",[168,893,895],{"id":894},"edge-cases","Edge Cases",[15,897,898,901],{},[179,899,900],{},"Icon fonts."," Prefer SVG icons; icon fonts render boxes or wrong glyphs before loading.",[15,903,904,907],{},[179,905,906],{},"Multiple scripts (languages)."," Include the subsets you need; CJK fonts are large and may need unicode-range splitting.",[15,909,910,65,913,915,916,416],{},[179,911,912],{},"Pages Router.",[32,914,34],{}," works in both routers; apply the class in ",[32,917,918],{},"_app",[15,920,921,924,925,928],{},[179,922,923],{},"Tailwind."," Map the CSS variables in the Tailwind theme's ",[32,926,927],{},"fontFamily"," configuration.",[168,930,932],{"id":931},"faq","FAQ",[934,935,938,942],"details",{"className":936},[937],"faq-item",[939,940,941],"summary",{},"Does next\u002Ffont make requests to Google at runtime?",[15,943,944],{},"No. Fonts are downloaded at build time and served from your own deployment.",[934,946,948,951],{"className":947},[937],[939,949,950],{},"Why do I still see a small shift?",[15,952,953],{},"Adjusted fallbacks match metrics closely but not perfectly; kerning and specific glyph widths differ. Remaining shifts are usually tiny.",[934,955,957,960],{"className":956},[937],[939,958,959],{},"Should I use font-display: optional?",[15,961,962,963,965],{},"If layout stability matters more than always showing the brand font on first visits, yes. Otherwise use ",[32,964,714],{}," with the adjusted fallback.",[934,967,969,972],{"className":968},[937],[939,970,971],{},"Can I use variable fonts?",[15,973,974],{},"Yes, and they are recommended: one file covers all weights.",[934,976,978,981],{"className":977},[937],[939,979,980],{},"Does next\u002Ffont preload every font?",[15,982,983,984,986],{},"By default it preloads fonts used in the layout or page. Set ",[32,985,571],{}," for fonts that are not needed early.",[934,988,990,993],{"className":989},[937],[939,991,992],{},"How do I use next\u002Ffont with CSS modules?",[15,994,995,996,998],{},"Expose a CSS variable with the ",[32,997,419],{}," option, apply the class on a root element, and reference the variable in your CSS.",[934,1000,1002,1005],{"className":1001},[937],[939,1003,1004],{},"Does next\u002Ffont help LCP?",[15,1006,1007],{},"Yes, when the LCP element is text: removing third-party font CSS and preloading font files lets text render sooner.",[934,1009,1011,1014],{"className":1010},[937],[939,1012,1013],{},"Can I subset fonts further?",[15,1015,1016,1017,416],{},"Choosing subsets is supported; for custom fonts, subset the files yourself with tools like glyphhanger or fonttools before using ",[32,1018,1019],{},"next\u002Ffont\u002Flocal",[168,1021,1023],{"id":1022},"related","Related",[173,1025,1026,1032,1039],{},[176,1027,1028,1031],{},[19,1029,1030],{"href":21},"Next.js performance"," — the topic overview.",[176,1033,1034,1038],{},[19,1035,1037],{"href":1036},"\u002Fcore-web-vitals-measurement\u002Freducing-cumulative-layout-shift-cls\u002Ffixing-cls-from-skeleton-screens-that-resize\u002F","Fixing CLS from skeleton screens that resize"," — another CLS source.",[176,1040,1041,1045],{},[19,1042,1044],{"href":1043},"\u002Frendering-css-performance\u002Fcritical-css-and-render-blocking-resources\u002F","Critical CSS & render-blocking resources"," — font CSS as a blocking resource.",[1047,1048,1050],"script",{"type":1049},"application\u002Fld+json","\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"HowTo\",\n  \"name\": \"How to Eliminate Font CLS with next\u002Ffont\",\n  \"description\": \"How next\u002Ffont removes font-related layout shifts and render-blocking requests, and how to configure subsets, variables, display and fallbacks.\",\n  \"step\": [\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 1,\n      \"name\": \"Load fonts with next\u002Ffont\",\n      \"text\": \"Load fonts with next\u002Ffont\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 2,\n      \"name\": \"Use CSS variables in styles\",\n      \"text\": \"Reference var(--font-sans) and var(--font-serif) in your CSS or Tailwind configuration, so the generated font-face and fallback are used consistently.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 3,\n      \"name\": \"Use local fonts for custom typefaces\",\n      \"text\": \"Use local fonts for custom typefaces\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 4,\n      \"name\": \"Limit subsets, weights and preloads\",\n      \"text\": \"Load only the subsets you need (for example latin), prefer variable fonts over multiple static weights, and set preload: false for fonts used only below the fold or on few pages.\"\n    }\n  ]\n}\n",[1047,1052,1053],{"type":1049},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"TechArticle\",\n  \"headline\": \"How to Eliminate Font CLS with next\u002Ffont\",\n  \"description\": \"How next\u002Ffont removes font-related layout shifts and render-blocking requests, and how to configure subsets, variables, display and fallbacks.\",\n  \"datePublished\": \"2026-10-06\",\n  \"dateModified\": \"2026-10-06\",\n  \"author\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"publisher\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"mainEntityOfPage\": {\n    \"@type\": \"WebPage\",\n    \"@id\": \"https:\u002F\u002Ffrontend-performance.com\u002Fframework-performance\u002Fnextjs-performance\u002Feliminating-font-cls-with-next-font\u002F\"\n  }\n}\n",[1047,1055,1056],{"type":1049},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"BreadcrumbList\",\n  \"itemListElement\": [\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 1,\n      \"name\": \"Home\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 2,\n      \"name\": \"Framework Performance\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fframework-performance\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 3,\n      \"name\": \"Next.js Performance\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fframework-performance\u002Fnextjs-performance\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 4,\n      \"name\": \"Eliminating Font CLS with next\u002Ffont\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fframework-performance\u002Fnextjs-performance\u002Feliminating-font-cls-with-next-font\u002F\"\n    }\n  ]\n}\n",[1058,1059,1060],"style",{},"html pre.shiki code .sjfSM, html code.shiki .sjfSM{--shiki-default:#66707B;--shiki-dark:#BDC4CC;--shiki-light:#66707B}html pre.shiki code .sPARh, html code.shiki .sPARh{--shiki-default:#A0111F;--shiki-dark:#FF9492;--shiki-light:#A0111F}html pre.shiki code .saISM, html code.shiki .saISM{--shiki-default:#0E1116;--shiki-dark:#F0F3F6;--shiki-light:#0E1116}html pre.shiki code .sZ8jY, html code.shiki .sZ8jY{--shiki-default:#032563;--shiki-dark:#ADDCFF;--shiki-light:#032563}html pre.shiki code .sPXB4, html code.shiki .sPXB4{--shiki-default:#023B95;--shiki-dark:#91CBFF;--shiki-light:#023B95}html pre.shiki code .smZ65, html code.shiki .smZ65{--shiki-default:#622CBC;--shiki-dark:#DBB7FF;--shiki-light:#622CBC}html pre.shiki code .sQw3B, html code.shiki .sQw3B{--shiki-default:#702C00;--shiki-dark:#FFB757;--shiki-light:#702C00}html pre.shiki code .sZBmE, html code.shiki .sZBmE{--shiki-default:#024C1A;--shiki-dark:#72F088;--shiki-light:#024C1A}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}",{"title":251,"searchDepth":265,"depth":265,"links":1062},[1063,1064,1065,1071,1072,1073,1074,1075,1076,1077,1078,1079],{"id":170,"depth":265,"text":171},{"id":210,"depth":265,"text":211},{"id":238,"depth":265,"text":239,"children":1066},[1067,1068,1069,1070],{"id":243,"depth":286,"text":244},{"id":486,"depth":286,"text":487},{"id":500,"depth":286,"text":501},{"id":560,"depth":286,"text":561},{"id":656,"depth":265,"text":657},{"id":663,"depth":265,"text":664},{"id":673,"depth":265,"text":674},{"id":696,"depth":265,"text":697},{"id":854,"depth":265,"text":855},{"id":864,"depth":265,"text":865},{"id":894,"depth":265,"text":895},{"id":931,"depth":265,"text":932},{"id":1022,"depth":265,"text":1023},"How next\u002Ffont removes font-related layout shifts and render-blocking requests, and how to configure subsets, variables, display and fallbacks.","md",{"slug":1083,"type":1084,"breadcrumb":1085,"datePublished":1093,"dateModified":1093},"eliminating-font-cls-with-next-font","article",[1086,1089,1090,1091],{"name":1087,"url":1088},"Home","\u002F",{"name":27,"url":26},{"name":22,"url":21},{"name":5,"url":1092},"\u002Fframework-performance\u002Fnextjs-performance\u002Feliminating-font-cls-with-next-font\u002F","2026-10-06",true,"\u002Fframework-performance\u002Fnextjs-performance\u002Feliminating-font-cls-with-next-font",{"title":1097,"description":1098},"Eliminating Font Layout Shifts with next\u002Ffont","next\u002Ffont self-hosts Google and local fonts, preloads them and generates size-adjusted fallbacks so text does not shift when web fonts load. Configure it correctly.","framework-performance\u002Fnextjs-performance\u002Feliminating-font-cls-with-next-font\u002Findex","iV-oVDo9XFhOXku0DjddD1VluTsJQd92xurs1JnMJcI",[1102,1106],{"title":1103,"path":1104,"stem":1105,"children":-1},"Choosing next\u002Fscript Loading Strategies","\u002Fframework-performance\u002Fnextjs-performance\u002Fchoosing-next-script-loading-strategies","framework-performance\u002Fnextjs-performance\u002Fchoosing-next-script-loading-strategies\u002Findex",{"title":1107,"path":1108,"stem":1109,"children":-1},"Fixing Slow LCP with the Next.js Image Component","\u002Fframework-performance\u002Fnextjs-performance\u002Ffixing-slow-lcp-with-the-nextjs-image-component","framework-performance\u002Fnextjs-performance\u002Ffixing-slow-lcp-with-the-nextjs-image-component\u002Findex",1791308074631]