[{"data":1,"prerenderedAt":949},["ShallowReactive",2],{"content:\u002Fadvanced-caching-strategies-cdn-architecture\u002Fresource-hints-and-early-hints\u002Fpreloading-web-fonts-with-crossorigin":3,"surroundings:\u002Fadvanced-caching-strategies-cdn-architecture\u002Fresource-hints-and-early-hints\u002Fpreloading-web-fonts-with-crossorigin":940},{"id":4,"title":5,"body":6,"description":919,"extension":920,"meta":921,"navigation":933,"path":934,"seo":935,"stem":938,"__hash__":939},"content\u002Fadvanced-caching-strategies-cdn-architecture\u002Fresource-hints-and-early-hints\u002Fpreloading-web-fonts-with-crossorigin\u002Findex.md","Preloading Web Fonts with crossorigin",{"type":7,"value":8,"toc":902},"minimark",[9,14,29,41,154,159,199,203,211,217,223,229,300,304,309,391,394,398,499,503,506,510,521,631,635,638,642,651,655,681,685,713,717,725,731,748,760,764,776,785,799,812,829,838,847,860,864,887,892,895,898],[10,11,13],"h1",{"id":12},"how-to-preload-web-fonts-correctly-with-crossorigin","How to Preload Web Fonts Correctly with crossorigin",[15,16,17,18,23,24,28],"p",{},"This guide addresses one of the most common resource-hint bugs, within ",[19,20,22],"a",{"href":21},"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fresource-hints-and-early-hints\u002F","Resource Hints & Early Hints"," in ",[19,25,27],{"href":26},"\u002Fadvanced-caching-strategies-cdn-architecture\u002F","Advanced Caching Strategies & CDN Architecture",". Web fonts are discovered late — only after the CSS that references them is downloaded and parsed, and often only once the browser knows some text uses them. Preloading the font that renders your LCP heading lets the request start during HTML parsing instead, which can save several hundred milliseconds on mobile.",[15,30,31,32,36,37,40],{},"But fonts are always fetched in CORS mode, even from your own origin. A ",[33,34,35],"code",{},"\u003Clink rel=\"preload\" as=\"font\">"," without the ",[33,38,39],{},"crossorigin"," attribute fetches the file in no-CORS mode, the browser cannot reuse that response for the CSS's CORS request, and downloads the font a second time. The preload then wastes bandwidth on the critical path and the console warns about an unused preload. One attribute separates a useful hint from a harmful one.",[15,42,43],{},[44,45,51,52,51,59,51,63,51,66,51,75,51,81,51,90,51,96,51,101,51,106,51,109,51,112,51,115,51,118,51,121,51,124,51,129,51,133,51,135,51,139,51,141,51,144,51,146,51,149,51,151,51],"svg",{"viewBox":46,"width":47,"role":48,"ariaLabel":49,"style":50},"0 0 760 228","100%","img","Comparison of what happens when a font is preloaded without and with the crossorigin attribute.","height:auto;max-width:760px;display:block;margin:1.75rem auto;font-family:inherit;color:var(--fp-svg-ink)"," ",[53,54],"rect",{"className":55,"x":57,"y":57,"width":47,"height":47,"fill":58},[56],"svg-canvas","0","#ffffff",[60,61,62],"title",{},"Font preload with and without crossorigin",[64,65,49],"desc",{},[53,67],{"x":68,"y":68,"width":69,"height":70,"rx":71,"fill":72,"stroke":73,"style":74},"1","758","226","10","none","currentColor","stroke-opacity:0.18",[76,77,62],"text",{"x":78,"y":79,"fill":73,"style":80},"28.0","34.0","font-size:16px;font-weight:700",[53,82],{"x":78,"y":83,"width":84,"height":85,"rx":86,"fill":87,"stroke":88,"style":89},"56.0","340.0","150.0","6","#ffc300","#b8860b","fill-opacity:0.24;stroke-opacity:0.9",[76,91,95],{"x":92,"y":93,"fill":73,"style":94},"42.0","82.0","font-size:14px;font-weight:700","Missing crossorigin",[76,97,100],{"x":92,"y":98,"fill":73,"style":99},"108.0","font-size:12.5px;font-weight:700","•",[76,102,105],{"x":83,"y":98,"fill":73,"style":103,"textAnchor":104},"font-size:12.5px","start","Preload fetches in no-CORS mode",[76,107,100],{"x":92,"y":108,"fill":73,"style":99},"132.0",[76,110,111],{"x":83,"y":108,"fill":73,"style":103,"textAnchor":104},"@font-face request uses CORS mode",[76,113,100],{"x":92,"y":114,"fill":73,"style":99},"156.0",[76,116,117],{"x":83,"y":114,"fill":73,"style":103,"textAnchor":104},"Modes differ: second download",[76,119,100],{"x":92,"y":120,"fill":73,"style":99},"180.0",[76,122,123],{"x":83,"y":120,"fill":73,"style":103,"textAnchor":104},"Console: preload not used",[53,125],{"x":126,"y":83,"width":84,"height":85,"rx":86,"fill":127,"stroke":127,"style":128},"392.0","#0466c8","fill-opacity:0.14;stroke-opacity:0.9",[76,130,132],{"x":131,"y":93,"fill":73,"style":94},"406.0","With crossorigin",[76,134,100],{"x":131,"y":98,"fill":73,"style":99},[76,136,138],{"x":137,"y":98,"fill":73,"style":103,"textAnchor":104},"420.0","Preload fetches in CORS mode",[76,140,100],{"x":131,"y":108,"fill":73,"style":99},[76,142,143],{"x":137,"y":108,"fill":73,"style":103,"textAnchor":104},"@font-face request matches",[76,145,100],{"x":131,"y":114,"fill":73,"style":99},[76,147,148],{"x":137,"y":114,"fill":73,"style":103,"textAnchor":104},"Single download, reused",[76,150,100],{"x":131,"y":120,"fill":73,"style":99},[76,152,153],{"x":137,"y":120,"fill":73,"style":103,"textAnchor":104},"Font ready before CSS asks",[155,156,158],"h2",{"id":157},"rapid-diagnosis","Rapid Diagnosis",[160,161,162,170,176,189],"ul",{},[163,164,165,169],"li",{},[166,167,168],"strong",{},"Check the Network panel"," for the same font URL requested twice — once with initiator \"preload\", once from the stylesheet.",[163,171,172,175],{},[166,173,174],{},"Read the console."," \"The resource … was preloaded using link preload but not used within a few seconds\" for a font usually means a mode or URL mismatch.",[163,177,178,181,182,23,185,188],{},[166,179,180],{},"Compare URLs exactly."," The preloaded URL must match the ",[33,183,184],{},"src",[33,186,187],{},"@font-face",", including query strings and the chosen format.",[163,190,191,198],{},[166,192,193,194,197],{},"Check ",[33,195,196],{},"type=\"font\u002Fwoff2\"","."," Without it, browsers that do not support the format may still download it.",[155,200,202],{"id":201},"root-cause-analysis","Root Cause Analysis",[15,204,205,210],{},[166,206,207,208,197],{},"1. Missing ",[33,209,39],{}," The most common cause of double font downloads.",[15,212,213,216],{},[166,214,215],{},"2. URL mismatch."," The preload points at a different file than CSS uses (a different subset, version hash or format).",[15,218,219,222],{},[166,220,221],{},"3. Preloading too many fonts."," Several preloaded weights compete with CSS and the LCP image, delaying everything.",[15,224,225,228],{},[166,226,227],{},"4. Preloading fonts not used above the fold."," Bandwidth spent early for text the user cannot see yet.",[15,230,231],{},[44,232,51,235,51,238,51,241,51,243,51,246,51,248,51,255,51,262,51,267,51,271,51,276,51,280,51,283,51,287,51,291,51,295,51,298,51],{"viewBox":233,"width":47,"role":48,"ariaLabel":234,"style":50},"0 0 760 194","Bar chart of font bytes downloaded before the LCP paint for four preload configurations.",[53,236],{"className":237,"x":57,"y":57,"width":47,"height":47,"fill":58},[56],[60,239,240],{},"Font bytes on the critical path, LCP heading font",[64,242,234],{},[53,244],{"x":68,"y":68,"width":69,"height":245,"rx":71,"fill":72,"stroke":73,"style":74},"192",[76,247,240],{"x":78,"y":79,"fill":73,"style":80},[76,249,254],{"x":250,"y":251,"fill":73,"style":252,"textAnchor":253},"202.4","70.0","font-size:13px","end","No preload",[53,256],{"x":257,"y":83,"width":258,"height":259,"rx":260,"fill":127,"stroke":127,"style":261},"214.4","113.4","19","3","fill-opacity:0.55;stroke-opacity:0.9",[76,263,266],{"x":264,"y":251,"fill":73,"style":265},"333.8","font-size:12px;font-weight:600","24KB",[76,268,270],{"x":250,"y":269,"fill":73,"style":252,"textAnchor":253},"101.0","Preload without crossorigin",[53,272],{"x":257,"y":273,"width":274,"height":259,"rx":260,"fill":87,"stroke":88,"style":275},"87.0","226.8","fill-opacity:0.7;stroke-opacity:0.9",[76,277,279],{"x":278,"y":269,"fill":73,"style":265},"447.2","48KB",[76,281,282],{"x":250,"y":108,"fill":73,"style":252,"textAnchor":253},"Preload 4 weights",[53,284],{"x":257,"y":285,"width":286,"height":259,"rx":260,"fill":87,"stroke":88,"style":275},"118.0","453.6",[76,288,290],{"x":289,"y":108,"fill":73,"style":265},"674.0","96KB",[76,292,294],{"x":250,"y":293,"fill":73,"style":252,"textAnchor":253},"163.0","Preload 1 weight + crossorigin",[53,296],{"x":257,"y":297,"width":258,"height":259,"rx":260,"fill":127,"stroke":127,"style":261},"149.0",[76,299,266],{"x":264,"y":293,"fill":73,"style":265},[155,301,303],{"id":302},"step-by-step-resolution","Step-by-Step Resolution",[305,306,308],"h3",{"id":307},"_1-preload-only-the-font-the-lcp-text-needs-with-crossorigin","1. Preload only the font the LCP text needs, with crossorigin",[310,311,316],"pre",{"className":312,"code":313,"language":314,"meta":315,"style":315},"language-html shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","\u003Clink rel=\"preload\" href=\"\u002Ffonts\u002Fbrand-sans-700-latin.4c1a.woff2\" as=\"font\" type=\"font\u002Fwoff2\" crossorigin>\n\u003C!-- trade-off: crossorigin is required even for same-origin fonts because fonts\n     are always fetched in CORS mode. For cross-origin hosts, the font server must\n     also send Access-Control-Allow-Origin, or the font will be blocked. -->\n","html","",[33,317,318,372,379,385],{"__ignoreMap":315},[319,320,323,327,331,335,338,342,345,347,350,353,355,358,361,363,366,369],"span",{"class":321,"line":322},"line",1,[319,324,326],{"class":325},"saISM","\u003C",[319,328,330],{"class":329},"sZBmE","link",[319,332,334],{"class":333},"sPXB4"," rel",[319,336,337],{"class":325},"=",[319,339,341],{"class":340},"sZ8jY","\"preload\"",[319,343,344],{"class":333}," href",[319,346,337],{"class":325},[319,348,349],{"class":340},"\"\u002Ffonts\u002Fbrand-sans-700-latin.4c1a.woff2\"",[319,351,352],{"class":333}," as",[319,354,337],{"class":325},[319,356,357],{"class":340},"\"font\"",[319,359,360],{"class":333}," type",[319,362,337],{"class":325},[319,364,365],{"class":340},"\"font\u002Fwoff2\"",[319,367,368],{"class":333}," crossorigin",[319,370,371],{"class":325},">\n",[319,373,375],{"class":321,"line":374},2,[319,376,378],{"class":377},"sjfSM","\u003C!-- trade-off: crossorigin is required even for same-origin fonts because fonts\n",[319,380,382],{"class":321,"line":381},3,[319,383,384],{"class":377},"     are always fetched in CORS mode. For cross-origin hosts, the font server must\n",[319,386,388],{"class":321,"line":387},4,[319,389,390],{"class":377},"     also send Access-Control-Allow-Origin, or the font will be blocked. -->\n",[15,392,393],{},"Expected outcome: one font request, starting during HTML parsing.",[305,395,397],{"id":396},"_2-match-the-font-face-src-exactly","2. Match the @font-face src exactly",[310,399,403],{"className":400,"code":401,"language":402,"meta":315,"style":315},"language-css shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","@font-face {\n  font-family: \"Brand Sans\";\n  src: url(\"\u002Ffonts\u002Fbrand-sans-700-latin.4c1a.woff2\") format(\"woff2\");\n  font-weight: 700;\n  font-display: swap;\n}\n\u002F* trade-off: hashed filenames must be generated identically for the preload and\n   the CSS; let the build tool emit both from one source of truth. *\u002F\n","css",[33,404,405,413,427,456,468,481,487,493],{"__ignoreMap":315},[319,406,407,410],{"class":321,"line":322},[319,408,187],{"class":409},"sPARh",[319,411,412],{"class":325}," {\n",[319,414,415,418,421,424],{"class":321,"line":374},[319,416,417],{"class":333},"  font-family",[319,419,420],{"class":325},": ",[319,422,423],{"class":340},"\"Brand Sans\"",[319,425,426],{"class":325},";\n",[319,428,429,432,434,437,440,442,445,448,450,453],{"class":321,"line":381},[319,430,431],{"class":333},"  src",[319,433,420],{"class":325},[319,435,436],{"class":333},"url",[319,438,439],{"class":325},"(",[319,441,349],{"class":340},[319,443,444],{"class":325},") ",[319,446,447],{"class":333},"format",[319,449,439],{"class":325},[319,451,452],{"class":340},"\"woff2\"",[319,454,455],{"class":325},");\n",[319,457,458,461,463,466],{"class":321,"line":387},[319,459,460],{"class":333},"  font-weight",[319,462,420],{"class":325},[319,464,465],{"class":333},"700",[319,467,426],{"class":325},[319,469,471,474,476,479],{"class":321,"line":470},5,[319,472,473],{"class":333},"  font-display",[319,475,420],{"class":325},[319,477,478],{"class":333},"swap",[319,480,426],{"class":325},[319,482,484],{"class":321,"line":483},6,[319,485,486],{"class":325},"}\n",[319,488,490],{"class":321,"line":489},7,[319,491,492],{"class":377},"\u002F* trade-off: hashed filenames must be generated identically for the preload and\n",[319,494,496],{"class":321,"line":495},8,[319,497,498],{"class":377},"   the CSS; let the build tool emit both from one source of truth. *\u002F\n",[305,500,502],{"id":501},"_3-limit-preloads-to-one-or-two-files","3. Limit preloads to one or two files",[15,504,505],{},"Preload the weight and subset used by above-the-fold text (usually the heading weight), and let others load via CSS. Each additional preload pulls bandwidth from CSS and the LCP image.",[305,507,509],{"id":508},"_4-set-cors-headers-on-cross-origin-font-hosts","4. Set CORS headers on cross-origin font hosts",[15,511,512,513,516,517,520],{},"If fonts come from a separate host, it must send ",[33,514,515],{},"Access-Control-Allow-Origin"," (a specific origin or ",[33,518,519],{},"*","). Without it, fonts fail to load whether or not they are preloaded.",[15,522,523],{},[44,524,51,527,51,530,51,533,51,535,51,538,51,540,51,545,51,551,51,556,51,559,51,563,51,567,51,570,51,574,51,578,51,581,51,585,51,589,51,596,51,600,51,604,51,609,51,612,51,615,51,618,51,621,51,624,51,627,51],{"viewBox":525,"width":47,"role":48,"ariaLabel":526,"style":50},"0 0 760 318","Four checks for a correct, beneficial font preload.",[53,528],{"className":529,"x":57,"y":57,"width":47,"height":47,"fill":58},[56],[60,531,532],{},"Font preload checklist",[64,534,526],{},[53,536],{"x":68,"y":68,"width":69,"height":537,"rx":71,"fill":72,"stroke":73,"style":74},"316",[76,539,532],{"x":78,"y":79,"fill":73,"style":80},[53,541],{"x":542,"y":83,"width":543,"height":544,"rx":86,"fill":127,"stroke":127,"style":128},"72.0","660.0","51.0",[76,546,550],{"x":547,"y":548,"fill":73,"style":549,"textAnchor":104},"86.0","77.0","font-size:13px;font-weight:700","as=font, type=font\u002Fwoff2, crossorigin",[76,552,555],{"x":547,"y":553,"fill":73,"style":554,"textAnchor":104},"94.0","font-size:12px","All three attributes every time",[53,557],{"x":542,"y":558,"width":543,"height":544,"rx":86,"fill":127,"stroke":127,"style":128},"119.0",[76,560,562],{"x":547,"y":561,"fill":73,"style":549,"textAnchor":104},"140.0","Identical URL to @font-face src",[76,564,566],{"x":547,"y":565,"fill":73,"style":554,"textAnchor":104},"157.0","Same subset, hash and format",[53,568],{"x":542,"y":569,"width":543,"height":544,"rx":86,"fill":127,"stroke":127,"style":128},"182.0",[76,571,573],{"x":547,"y":572,"fill":73,"style":549,"textAnchor":104},"203.0","One or two files at most",[76,575,577],{"x":547,"y":576,"fill":73,"style":554,"textAnchor":104},"220.0","The weight used by the LCP text",[53,579],{"x":542,"y":580,"width":543,"height":544,"rx":86,"fill":127,"stroke":127,"style":128},"245.0",[76,582,584],{"x":547,"y":583,"fill":73,"style":549,"textAnchor":104},"266.0","CORS headers on the font host",[76,586,588],{"x":547,"y":587,"fill":73,"style":554,"textAnchor":104},"283.0","Access-Control-Allow-Origin present",[321,590],{"x1":591,"y1":592,"x2":591,"y2":593,"stroke":73,"strokeWidth":594,"style":595},"43.0","95.5","130.5","1.5","stroke-opacity:0.3",[321,597],{"x1":591,"y1":598,"x2":591,"y2":599,"stroke":73,"strokeWidth":594,"style":595},"158.5","193.5",[321,601],{"x1":591,"y1":602,"x2":591,"y2":603,"stroke":73,"strokeWidth":594,"style":595},"221.5","256.5",[605,606],"circle",{"cx":591,"cy":607,"r":608,"fill":127},"81.5","13",[76,610,68],{"x":591,"y":547,"fill":58,"style":549,"textAnchor":611},"middle",[605,613],{"cx":591,"cy":614,"r":608,"fill":127},"144.5",[76,616,617],{"x":591,"y":297,"fill":58,"style":549,"textAnchor":611},"2",[605,619],{"cx":591,"cy":620,"r":608,"fill":127},"207.5",[76,622,260],{"x":591,"y":623,"fill":58,"style":549,"textAnchor":611},"212.0",[605,625],{"cx":591,"cy":626,"r":608,"fill":127},"270.5",[76,628,630],{"x":591,"y":629,"fill":58,"style":549,"textAnchor":611},"275.0","4",[155,632,634],{"id":633},"verification","Verification",[15,636,637],{},"The Network panel should show each preloaded font once, initiated by the preload, with no second request from CSS. The console should be free of unused-preload warnings for fonts. In a throttled trace, the font should finish before or around the time CSS finishes, and text LCP should improve — typically by 100–400ms on mobile when the font was previously discovered late.",[155,639,641],{"id":640},"worked-example-double-font-downloads","Worked Example: Double Font Downloads",[15,643,644,645,647,648,650],{},"A SaaS landing page preloaded three font weights without ",[33,646,39],{},". Every page view downloaded six font files on the critical path — 140KB — and LCP on mobile was 3.1s. Adding ",[33,649,39],{}," removed the duplicates; reducing preloads to the single heading weight removed another 48KB from the critical path. LCP p75 fell to 2.3s, and the console warnings disappeared.",[155,652,654],{"id":653},"preloading-vs-inlining-vs-font-display","Preloading vs Inlining vs Font-Display",[15,656,657,658,661,662,664,665,668,669,672,673,676,677,197],{},"Preloading is one of three font tools, and they interact. ",[33,659,660],{},"font-display"," decides what users see while the font loads (",[33,663,478],{}," shows fallback text immediately; ",[33,666,667],{},"optional"," uses the font only if it arrives very quickly). Preloading makes the font arrive sooner. Inlining small fonts as data URIs in CSS removes the request entirely but bloats render-blocking CSS and prevents separate caching — rarely worth it except for tiny icon subsets. A common robust combination: preload the heading font, ",[33,670,671],{},"font-display: swap"," with metric-matched fallbacks for headings, and ",[33,674,675],{},"font-display: optional"," for body text — see ",[19,678,680],{"href":679},"\u002Fcore-web-vitals-measurement\u002Ffont-loading-and-text-rendering-performance\u002Ffont-display-swap-vs-optional-for-lcp\u002F","font-display swap vs optional for LCP",[155,682,684],{"id":683},"common-mistakes","Common Mistakes",[160,686,687,695,701,707],{},[163,688,689,694],{},[166,690,691,692,197],{},"Omitting ",[33,693,39],{}," Double downloads.",[163,696,697,700],{},[166,698,699],{},"Preloading WOFF and WOFF2."," Modern browsers only need WOFF2; preloading both wastes bytes.",[163,702,703,706],{},[166,704,705],{},"Preloading from Google Fonts' CSS URL."," The font file URLs are not known until the CSS loads; self-host to preload reliably.",[163,708,709,712],{},[166,710,711],{},"Preloading on every page."," Only templates where the font is used above the fold benefit.",[155,714,716],{"id":715},"edge-cases","Edge Cases",[15,718,719,724],{},[166,720,721,197],{},[33,722,723],{},"crossorigin=\"use-credentials\""," Only needed if the font server requires credentials, which is rare and needs matching CORS headers.",[15,726,727,730],{},[166,728,729],{},"Variable fonts."," One file covers all weights, so a single preload serves every heading; weigh its larger size against the LCP benefit.",[15,732,733,736,737,740,741,743,744,747],{},[166,734,735],{},"Early Hints."," Font preloads work in 103 Early Hints ",[33,738,739],{},"Link"," headers too, with ",[33,742,39],{}," expressed as an attribute in the header (",[33,745,746],{},"; crossorigin",").",[15,749,750,756,757,759],{},[166,751,752,755],{},[33,753,754],{},"unicode-range"," subsets."," Preload ignores ",[33,758,754],{},"; preload only the subset the page's language needs.",[155,761,763],{"id":762},"faq","FAQ",[765,766,769,773],"details",{"className":767},[768],"faq-item",[770,771,772],"summary",{},"Why do same-origin fonts need crossorigin?",[15,774,775],{},"The CSS Fonts specification requires fonts to be fetched in CORS mode regardless of origin. The preload must use the same mode for the browser to match the two requests.",[765,777,779,782],{"className":778},[768],[770,780,781],{},"Does preloading a font hurt if it is not used?",[15,783,784],{},"Yes — it consumes bandwidth during the most critical part of the load, and Chrome warns about it. Preload only fonts used above the fold on that template.",[765,786,788,791],{"className":787},[768],[770,789,790],{},"Should I preload icon fonts?",[15,792,793,794,798],{},"Better to replace icon fonts with SVG; see ",[19,795,797],{"href":796},"\u002Fimage-media-optimization\u002Fsvg-and-icon-optimization\u002Fmigrating-from-icon-fonts-to-svg\u002F","migrating from icon fonts to SVG",". If you keep one, preload it only if icons render in the first viewport.",[765,800,802,805],{"className":801},[768],[770,803,804],{},"Does fetchpriority apply to font preloads?",[15,806,807,808,811],{},"Font preloads are already high priority. Adding ",[33,809,810],{},"fetchpriority=\"high\""," changes little; lowering it can make sense for fonts used only below the fold that you still want early.",[765,813,815,818],{"className":814},[768],[770,816,817],{},"How do I preload fonts in Next.js or Nuxt?",[15,819,820,821,824,825,828],{},"Framework font modules (",[33,822,823],{},"next\u002Ffont",", ",[33,826,827],{},"@nuxt\u002Ffonts",") self-host and preload fonts automatically with the correct attributes; prefer them over hand-written links.",[765,830,832,835],{"className":831},[768],[770,833,834],{},"Is preconnect enough instead of preload for third-party fonts?",[15,836,837],{},"Preconnect saves connection time but the font request still waits for CSS. Preload starts the request immediately. For the LCP font, preload (with self-hosting) wins.",[765,839,841,844],{"className":840},[768],[770,842,843],{},"How do I preload fonts referenced by a third-party stylesheet?",[15,845,846],{},"You cannot reliably preload what you do not know the URL of. Self-host the fonts so URLs are stable and known at build time, then preload them; this is the main reason self-hosting usually beats preconnecting to a font CDN.",[765,848,850,853],{"className":849},[768],[770,851,852],{},"What does a correct font preload look like in the Network panel?",[15,854,855,856,859],{},"One request per font file, with the Initiator column showing the preload link (or the Early Hints response), priority High, status 200, and no second request for the same URL when the stylesheet is parsed. If you see the font twice, compare the request modes in the Headers tab — ",[33,857,858],{},"Sec-Fetch-Mode: cors"," must appear on the preload too.",[155,861,863],{"id":862},"related","Related",[160,865,866,873,880],{},[163,867,868,872],{},[19,869,871],{"href":870},"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fresource-hints-and-early-hints\u002Ffixing-unused-preload-warnings-in-the-console\u002F","Fixing unused preload warnings in the console"," — the broader class of preload mismatches.",[163,874,875,879],{},[19,876,878],{"href":877},"\u002Fcore-web-vitals-measurement\u002Ffont-loading-and-text-rendering-performance\u002Fsubsetting-web-fonts-with-unicode-range\u002F","Subsetting web fonts with unicode-range"," — making the preloaded file small.",[163,881,882,886],{},[19,883,885],{"href":884},"\u002Fcore-web-vitals-measurement\u002Fmeasuring-lcp-with-chrome-devtools\u002Ffixing-lcp-when-the-h1-is-the-lcp-element\u002F","Fixing LCP when the H1 is the LCP element"," — where font timing decides LCP.",[888,889,891],"script",{"type":890},"application\u002Fld+json","\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"HowTo\",\n  \"name\": \"How to Preload Web Fonts Correctly with crossorigin\",\n  \"description\": \"Why font preloads need the crossorigin attribute even on the same origin, how mismatches cause double downloads, and how to preload only what helps LCP.\",\n  \"step\": [\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 1,\n      \"name\": \"Preload only the font the LCP text needs, with crossorigin\",\n      \"text\": \"Expected outcome: one font request, starting during HTML parsing.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 2,\n      \"name\": \"Match the @font-face src exactly\",\n      \"text\": \"Match the @font-face src exactly\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 3,\n      \"name\": \"Limit preloads to one or two files\",\n      \"text\": \"Preload the weight and subset used by above-the-fold text (usually the heading weight), and let others load via CSS.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 4,\n      \"name\": \"Set CORS headers on cross-origin font hosts\",\n      \"text\": \"If fonts come from a separate host, it must send Access-Control-Allow-Origin (a specific origin or *).\"\n    }\n  ]\n}\n",[888,893,894],{"type":890},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"TechArticle\",\n  \"headline\": \"How to Preload Web Fonts Correctly with crossorigin\",\n  \"description\": \"Why font preloads need the crossorigin attribute even on the same origin, how mismatches cause double downloads, and how to preload only what helps LCP.\",\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\u002Fadvanced-caching-strategies-cdn-architecture\u002Fresource-hints-and-early-hints\u002Fpreloading-web-fonts-with-crossorigin\u002F\"\n  }\n}\n",[888,896,897],{"type":890},"\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\": \"Advanced Caching Strategies & CDN Architecture\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fadvanced-caching-strategies-cdn-architecture\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 3,\n      \"name\": \"Resource Hints & Early Hints\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fadvanced-caching-strategies-cdn-architecture\u002Fresource-hints-and-early-hints\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 4,\n      \"name\": \"Preloading Web Fonts with crossorigin\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fadvanced-caching-strategies-cdn-architecture\u002Fresource-hints-and-early-hints\u002Fpreloading-web-fonts-with-crossorigin\u002F\"\n    }\n  ]\n}\n",[899,900,901],"style",{},"html pre.shiki code .saISM, html code.shiki .saISM{--shiki-default:#0E1116;--shiki-dark:#F0F3F6;--shiki-light:#0E1116}html pre.shiki code .sZBmE, html code.shiki .sZBmE{--shiki-default:#024C1A;--shiki-dark:#72F088;--shiki-light:#024C1A}html pre.shiki code .sPXB4, html code.shiki .sPXB4{--shiki-default:#023B95;--shiki-dark:#91CBFF;--shiki-light:#023B95}html pre.shiki code .sZ8jY, html code.shiki .sZ8jY{--shiki-default:#032563;--shiki-dark:#ADDCFF;--shiki-light:#032563}html pre.shiki code .sjfSM, html code.shiki .sjfSM{--shiki-default:#66707B;--shiki-dark:#BDC4CC;--shiki-light:#66707B}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);}html pre.shiki code .sPARh, html code.shiki .sPARh{--shiki-default:#A0111F;--shiki-dark:#FF9492;--shiki-light:#A0111F}",{"title":315,"searchDepth":374,"depth":374,"links":903},[904,905,906,912,913,914,915,916,917,918],{"id":157,"depth":374,"text":158},{"id":201,"depth":374,"text":202},{"id":302,"depth":374,"text":303,"children":907},[908,909,910,911],{"id":307,"depth":381,"text":308},{"id":396,"depth":381,"text":397},{"id":501,"depth":381,"text":502},{"id":508,"depth":381,"text":509},{"id":633,"depth":374,"text":634},{"id":640,"depth":374,"text":641},{"id":653,"depth":374,"text":654},{"id":683,"depth":374,"text":684},{"id":715,"depth":374,"text":716},{"id":762,"depth":374,"text":763},{"id":862,"depth":374,"text":863},"Why font preloads need the crossorigin attribute even on the same origin, how mismatches cause double downloads, and how to preload only what helps LCP.","md",{"slug":922,"type":923,"breadcrumb":924,"datePublished":932,"dateModified":932},"preloading-web-fonts-with-crossorigin","article",[925,928,929,930],{"name":926,"url":927},"Home","\u002F",{"name":27,"url":26},{"name":22,"url":21},{"name":5,"url":931},"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fresource-hints-and-early-hints\u002Fpreloading-web-fonts-with-crossorigin\u002F","2026-10-06",true,"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fresource-hints-and-early-hints\u002Fpreloading-web-fonts-with-crossorigin",{"title":936,"description":937},"Preloading Web Fonts Correctly with crossorigin","A font preload without crossorigin downloads the font twice. Why fonts use CORS mode, how to match preloads to @font-face, and which fonts are worth preloading.","advanced-caching-strategies-cdn-architecture\u002Fresource-hints-and-early-hints\u002Fpreloading-web-fonts-with-crossorigin\u002Findex","LxE6LL7UCmmUfuilZd3SPOdQvmVS_iXR9Y4ncV26Kys",[941,945],{"title":942,"path":943,"stem":944},"Preload vs Preconnect: When to Use Each","\u002Fadvanced-caching-strategies-cdn-architecture\u002Fresource-hints-and-early-hints\u002Fpreload-vs-preconnect-when-to-use-each","advanced-caching-strategies-cdn-architecture\u002Fresource-hints-and-early-hints\u002Fpreload-vs-preconnect-when-to-use-each\u002Findex",{"title":946,"path":947,"stem":948},"Using 103 Early Hints Behind a CDN","\u002Fadvanced-caching-strategies-cdn-architecture\u002Fresource-hints-and-early-hints\u002Fusing-103-early-hints-behind-a-cdn","advanced-caching-strategies-cdn-architecture\u002Fresource-hints-and-early-hints\u002Fusing-103-early-hints-behind-a-cdn\u002Findex",1791308076977]