[{"data":1,"prerenderedAt":2244},["ShallowReactive",2],{"blog-astro-image-optimization/":3},{"id":4,"title":5,"body":6,"description":2200,"extension":2201,"faqs":2202,"image":2213,"imageAlt":2214,"imageCaption":2215,"meta":2216,"navigation":170,"path":2217,"publishedAt":2218,"readingTime":393,"references":2219,"seo":2235,"stem":2236,"tags":2237,"updatedAt":2218,"__hash__":2243},"blog/blog/astro-image-optimization.md","Astro Image Optimization: Fix LCP Without the Guesswork",{"type":7,"value":8,"toc":2159},"minimark",[9,19,22,28,31,34,99,102,107,110,126,131,184,190,210,213,217,282,285,305,312,316,323,421,431,435,484,487,491,500,503,538,541,544,600,611,615,618,667,670,673,717,721,724,727,781,784,788,798,852,862,865,911,921,984,988,1044,1047,1050,1097,1101,1107,1110,1113,1154,1157,1284,1294,1320,1327,1330,1333,1419,1422,1426,1429,1432,1490,1512,1515,1587,1590,1594,1612,1615,1655,1658,1705,1709,1712,1800,1803,1900,1914,1918,1921,2020,2024,2028,2042,2046,2062,2066,2078,2082,2094,2098,2133,2137,2148,2155],[10,11,12,13,18],"p",{},"Your Astro site ships zero JavaScript. Your Lighthouse performance score is green. And your ",[14,15,17],"a",{"href":16},"/blog/how-to-improve-lcp/","LCP"," is still 4.2 seconds.",[10,20,21],{},"The problem isn't Astro. It's your images.",[10,23,24,25,27],{},"Astro's zero-JS architecture eliminates the most common cause of slow sites — render-blocking JavaScript. But ",[14,26,17],{"href":16}," measures when the largest visible element finishes rendering, and that element is almost always an image. A 1.8MB uncompressed JPEG doesn't care how little JavaScript you ship. It's still going to take 3 seconds to download on a 4G connection.",[10,29,30],{},"This guide walks through the five image mistakes that most commonly hurt LCP on Astro sites, including a default behavior that works against you out of the box. Every fix includes before-and-after measurements so you can prioritize based on impact.",[10,32,33],{},"Here's what a typical unoptimized Astro site looks like:",[35,36,37,50],"table",{},[38,39,40],"thead",{},[41,42,43,47],"tr",{},[44,45,46],"th",{},"Metric",[44,48,49],{},"Value",[51,52,53,61,72,83,91],"tbody",{},[41,54,55,58],{},[56,57,17],"td",{},[56,59,60],{},"4.2s",[41,62,63,69],{},[56,64,65],{},[14,66,68],{"href":67},"/blog/fix-cumulative-layout-shift/","CLS",[56,70,71],{},"0.14",[41,73,74,80],{},[56,75,76],{},[14,77,79],{"href":78},"/blog/improve-inp-score/","INP",[56,81,82],{},"45ms",[41,84,85,88],{},[56,86,87],{},"Hero image size",[56,89,90],{},"1.8MB",[41,92,93,96],{},[56,94,95],{},"PageSpeed mobile",[56,97,98],{},"52",[10,100,101],{},"Notice the INP is already excellent — that's Astro's zero-JS advantage. But the LCP and CLS scores are dragging the overall score down, and both are caused entirely by images.",[103,104,106],"h2",{"id":105},"fix-1-the-lazy-loading-trap-saved-14s-lcp","Fix 1: The lazy loading trap (saved 1.4s LCP)",[10,108,109],{},"This is the most impactful fix, and it catches almost everyone.",[10,111,112,113,117,118,121,122,125],{},"Astro's ",[114,115,116],"code",{},"\u003CImage />"," component defaults to ",[114,119,120],{},"loading=\"lazy\""," and ",[114,123,124],{},"decoding=\"async\"",". For below-the-fold images, this is exactly right. For your hero image — the one that's almost always your LCP element — it's a performance killer.",[127,128,130],"h3",{"id":129},"the-problem","The problem",[132,133,138],"pre",{"className":134,"code":135,"language":136,"meta":137,"style":137},"language-astro shiki shiki-themes github-light github-dark","---\nimport { Image } from 'astro:assets';\nimport heroImage from '../assets/hero.jpg';\n---\n\n\u003C!-- This looks correct but hurts LCP -->\n\u003CImage src={heroImage} alt=\"Product hero shot\" />\n","astro","",[114,139,140,148,154,160,165,172,178],{"__ignoreMap":137},[141,142,145],"span",{"class":143,"line":144},"line",1,[141,146,147],{},"---\n",[141,149,151],{"class":143,"line":150},2,[141,152,153],{},"import { Image } from 'astro:assets';\n",[141,155,157],{"class":143,"line":156},3,[141,158,159],{},"import heroImage from '../assets/hero.jpg';\n",[141,161,163],{"class":143,"line":162},4,[141,164,147],{},[141,166,168],{"class":143,"line":167},5,[141,169,171],{"emptyLinePlaceholder":170},true,"\n",[141,173,175],{"class":143,"line":174},6,[141,176,177],{},"\u003C!-- This looks correct but hurts LCP -->\n",[141,179,181],{"class":143,"line":180},7,[141,182,183],{},"\u003CImage src={heroImage} alt=\"Product hero shot\" />\n",[10,185,186,187,189],{},"With ",[114,188,120],{},", the browser won't start fetching the image until it enters the viewport. Since the hero image is above the fold, the browser has to:",[191,192,193,197,200,203],"ol",{},[194,195,196],"li",{},"Download the HTML",[194,198,199],{},"Parse the DOM",[194,201,202],{},"Run layout to determine the image is in the viewport",[194,204,205,209],{},[206,207,208],"em",{},"Then"," start the image request",[10,211,212],{},"That layout step adds 200-400ms before the image download even begins. On a mid-tier mobile device, it's worse.",[127,214,216],{"id":215},"the-fix","The fix",[132,218,220],{"className":134,"code":219,"language":136,"meta":137,"style":137},"---\nimport { Image } from 'astro:assets';\nimport heroImage from '../assets/hero.jpg';\n---\n\n\u003C!-- Explicitly override defaults for LCP images -->\n\u003CImage\n  src={heroImage}\n  alt=\"Product hero shot\"\n  loading=\"eager\"\n  fetchpriority=\"high\"\n/>\n",[114,221,222,226,230,234,238,242,247,252,258,264,270,276],{"__ignoreMap":137},[141,223,224],{"class":143,"line":144},[141,225,147],{},[141,227,228],{"class":143,"line":150},[141,229,153],{},[141,231,232],{"class":143,"line":156},[141,233,159],{},[141,235,236],{"class":143,"line":162},[141,237,147],{},[141,239,240],{"class":143,"line":167},[141,241,171],{"emptyLinePlaceholder":170},[141,243,244],{"class":143,"line":174},[141,245,246],{},"\u003C!-- Explicitly override defaults for LCP images -->\n",[141,248,249],{"class":143,"line":180},[141,250,251],{},"\u003CImage\n",[141,253,255],{"class":143,"line":254},8,[141,256,257],{},"  src={heroImage}\n",[141,259,261],{"class":143,"line":260},9,[141,262,263],{},"  alt=\"Product hero shot\"\n",[141,265,267],{"class":143,"line":266},10,[141,268,269],{},"  loading=\"eager\"\n",[141,271,273],{"class":143,"line":272},11,[141,274,275],{},"  fetchpriority=\"high\"\n",[141,277,279],{"class":143,"line":278},12,[141,280,281],{},"/>\n",[10,283,284],{},"Two attributes change everything:",[286,287,288,297],"ul",{},[194,289,290,296],{},[291,292,293],"strong",{},[114,294,295],{},"loading=\"eager\""," tells the browser to start fetching immediately, not wait for layout",[194,298,299,304],{},[291,300,301],{},[114,302,303],{},"fetchpriority=\"high\""," tells the browser this image is more important than other resources, so it should be prioritized in the network queue",[10,306,307,308,311],{},"Unlike Next.js, Astro doesn't have a ",[114,309,310],{},"priority"," prop that handles both of these for you. You need to set them manually.",[127,313,315],{"id":314},"add-a-preload-hint-for-maximum-speed","Add a preload hint for maximum speed",[10,317,318,319,322],{},"For the absolute fastest LCP, add a preload link in your layout's ",[114,320,321],{},"\u003Chead>",":",[132,324,326],{"className":134,"code":325,"language":136,"meta":137,"style":137},"---\n// src/layouts/Layout.astro\n---\n\n\u003Chtml>\n  \u003Chead>\n    \u003Clink\n      rel=\"preload\"\n      href=\"/optimized-hero.webp\"\n      as=\"image\"\n      type=\"image/webp\"\n      fetchpriority=\"high\"\n    />\n  \u003C/head>\n  \u003Cbody>\n    \u003Cslot />\n  \u003C/body>\n\u003C/html>\n",[114,327,328,332,337,341,345,350,355,360,365,370,375,380,385,391,397,403,409,415],{"__ignoreMap":137},[141,329,330],{"class":143,"line":144},[141,331,147],{},[141,333,334],{"class":143,"line":150},[141,335,336],{},"// src/layouts/Layout.astro\n",[141,338,339],{"class":143,"line":156},[141,340,147],{},[141,342,343],{"class":143,"line":162},[141,344,171],{"emptyLinePlaceholder":170},[141,346,347],{"class":143,"line":167},[141,348,349],{},"\u003Chtml>\n",[141,351,352],{"class":143,"line":174},[141,353,354],{},"  \u003Chead>\n",[141,356,357],{"class":143,"line":180},[141,358,359],{},"    \u003Clink\n",[141,361,362],{"class":143,"line":254},[141,363,364],{},"      rel=\"preload\"\n",[141,366,367],{"class":143,"line":260},[141,368,369],{},"      href=\"/optimized-hero.webp\"\n",[141,371,372],{"class":143,"line":266},[141,373,374],{},"      as=\"image\"\n",[141,376,377],{"class":143,"line":272},[141,378,379],{},"      type=\"image/webp\"\n",[141,381,382],{"class":143,"line":278},[141,383,384],{},"      fetchpriority=\"high\"\n",[141,386,388],{"class":143,"line":387},13,[141,389,390],{},"    />\n",[141,392,394],{"class":143,"line":393},14,[141,395,396],{},"  \u003C/head>\n",[141,398,400],{"class":143,"line":399},15,[141,401,402],{},"  \u003Cbody>\n",[141,404,406],{"class":143,"line":405},16,[141,407,408],{},"    \u003Cslot />\n",[141,410,412],{"class":143,"line":411},17,[141,413,414],{},"  \u003C/body>\n",[141,416,418],{"class":143,"line":417},18,[141,419,420],{},"\u003C/html>\n",[10,422,423,424,427,428,430],{},"Preloading starts the image download before the browser even encounters the ",[114,425,426],{},"\u003Cimg>"," tag in the DOM. Combined with ",[114,429,295],{},", this eliminates all unnecessary delay.",[127,432,434],{"id":433},"results","Results",[35,436,437,452],{},[38,438,439],{},[41,440,441,443,446,449],{},[44,442,46],{},[44,444,445],{},"Before",[44,447,448],{},"After",[44,450,451],{},"Change",[51,453,454,468],{},[41,455,456,458,460,463],{},[56,457,17],{},[56,459,60],{},[56,461,462],{},"2.8s",[56,464,465],{},[291,466,467],{},"-1.4s",[41,469,470,473,476,479],{},[56,471,472],{},"Image load start",[56,474,475],{},"1.2s",[56,477,478],{},"0.3s",[56,480,481],{},[291,482,483],{},"-900ms",[10,485,486],{},"1.4 seconds from two HTML attributes. This single fix is often the difference between a \"poor\" and \"needs improvement\" LCP score.",[103,488,490],{"id":489},"fix-2-use-picture-for-format-negotiation-saved-340kb","Fix 2: Use Picture for format negotiation (saved 340KB)",[10,492,112,493,495,496,499],{},[114,494,116],{}," component outputs WebP by default. That's good — WebP is 25-30% smaller than JPEG. But AVIF is 20-30% smaller than ",[206,497,498],{},"WebP",", and 93% of browsers now support it.",[127,501,130],{"id":502},"the-problem-1",[132,504,506],{"className":134,"code":505,"language":136,"meta":137,"style":137},"---\nimport { Image } from 'astro:assets';\nimport heroImage from '../assets/hero.jpg';\n---\n\n\u003C!-- Only serves WebP — misses AVIF savings -->\n\u003CImage src={heroImage} alt=\"Product hero shot\" loading=\"eager\" />\n",[114,507,508,512,516,520,524,528,533],{"__ignoreMap":137},[141,509,510],{"class":143,"line":144},[141,511,147],{},[141,513,514],{"class":143,"line":150},[141,515,153],{},[141,517,518],{"class":143,"line":156},[141,519,159],{},[141,521,522],{"class":143,"line":162},[141,523,147],{},[141,525,526],{"class":143,"line":167},[141,527,171],{"emptyLinePlaceholder":170},[141,529,530],{"class":143,"line":174},[141,531,532],{},"\u003C!-- Only serves WebP — misses AVIF savings -->\n",[141,534,535],{"class":143,"line":180},[141,536,537],{},"\u003CImage src={heroImage} alt=\"Product hero shot\" loading=\"eager\" />\n",[10,539,540],{},"This outputs a single WebP file. Browsers that support AVIF (Chrome, Firefox, Safari 16+) still get the larger WebP.",[127,542,216],{"id":543},"the-fix-1",[132,545,547],{"className":134,"code":546,"language":136,"meta":137,"style":137},"---\nimport { Picture } from 'astro:assets';\nimport heroImage from '../assets/hero.jpg';\n---\n\n\u003CPicture\n  src={heroImage}\n  formats={['avif', 'webp']}\n  alt=\"Product hero shot\"\n  loading=\"eager\"\n  fetchpriority=\"high\"\n/>\n",[114,548,549,553,558,562,566,570,575,579,584,588,592,596],{"__ignoreMap":137},[141,550,551],{"class":143,"line":144},[141,552,147],{},[141,554,555],{"class":143,"line":150},[141,556,557],{},"import { Picture } from 'astro:assets';\n",[141,559,560],{"class":143,"line":156},[141,561,159],{},[141,563,564],{"class":143,"line":162},[141,565,147],{},[141,567,568],{"class":143,"line":167},[141,569,171],{"emptyLinePlaceholder":170},[141,571,572],{"class":143,"line":174},[141,573,574],{},"\u003CPicture\n",[141,576,577],{"class":143,"line":180},[141,578,257],{},[141,580,581],{"class":143,"line":254},[141,582,583],{},"  formats={['avif', 'webp']}\n",[141,585,586],{"class":143,"line":260},[141,587,263],{},[141,589,590],{"class":143,"line":266},[141,591,269],{},[141,593,594],{"class":143,"line":272},[141,595,275],{},[141,597,598],{"class":143,"line":278},[141,599,281],{},[10,601,602,603,606,607,610],{},"This generates a ",[114,604,605],{},"\u003Cpicture>"," element with multiple ",[114,608,609],{},"\u003Csource>"," tags. The browser picks AVIF if it can, falls back to WebP, and uses the original format as a last resort.",[127,612,614],{"id":613},"real-file-sizes","Real file sizes",[10,616,617],{},"For a 1600x900 hero image at default quality:",[35,619,620,633],{},[38,621,622],{},[41,623,624,627,630],{},[44,625,626],{},"Format",[44,628,629],{},"File size",[44,631,632],{},"vs Original JPEG",[51,634,635,646,656],{},[41,636,637,640,643],{},[56,638,639],{},"JPEG (original)",[56,641,642],{},"485KB",[56,644,645],{},"baseline",[41,647,648,650,653],{},[56,649,498],{},[56,651,652],{},"192KB",[56,654,655],{},"-60%",[41,657,658,661,664],{},[56,659,660],{},"AVIF",[56,662,663],{},"145KB",[56,665,666],{},"-70%",[10,668,669],{},"The AVIF version is 340KB smaller than the original and 47KB smaller than WebP. On a 4G connection, that's roughly 200ms faster to download.",[127,671,434],{"id":672},"results-1",[35,674,675,687],{},[38,676,677],{},[41,678,679,681,683,685],{},[44,680,46],{},[44,682,445],{},[44,684,448],{},[44,686,451],{},[51,688,689,703],{},[41,690,691,693,696,699],{},[56,692,87],{},[56,694,695],{},"485KB (JPEG)",[56,697,698],{},"145KB (AVIF)",[56,700,701],{},[291,702,666],{},[41,704,705,707,709,712],{},[56,706,17],{},[56,708,462],{},[56,710,711],{},"2.4s",[56,713,714],{},[291,715,716],{},"-400ms",[103,718,720],{"id":719},"fix-3-responsive-images-for-mobile-saved-600ms-lcp-on-mobile","Fix 3: Responsive images for mobile (saved 600ms LCP on mobile)",[10,722,723],{},"A 1600px-wide hero image is perfect for desktop. On a 375px-wide phone screen, you're downloading 4x more pixels than the screen can display. That's wasted bytes and wasted time.",[127,725,130],{"id":726},"the-problem-2",[132,728,730],{"className":134,"code":729,"language":136,"meta":137,"style":137},"---\nimport { Image } from 'astro:assets';\nimport heroImage from '../assets/hero.jpg';\n---\n\n\u003C!-- Same large image sent to all devices -->\n\u003CImage\n  src={heroImage}\n  alt=\"Product hero shot\"\n  loading=\"eager\"\n  fetchpriority=\"high\"\n/>\n",[114,731,732,736,740,744,748,752,757,761,765,769,773,777],{"__ignoreMap":137},[141,733,734],{"class":143,"line":144},[141,735,147],{},[141,737,738],{"class":143,"line":150},[141,739,153],{},[141,741,742],{"class":143,"line":156},[141,743,159],{},[141,745,746],{"class":143,"line":162},[141,747,147],{},[141,749,750],{"class":143,"line":167},[141,751,171],{"emptyLinePlaceholder":170},[141,753,754],{"class":143,"line":174},[141,755,756],{},"\u003C!-- Same large image sent to all devices -->\n",[141,758,759],{"class":143,"line":180},[141,760,251],{},[141,762,763],{"class":143,"line":254},[141,764,257],{},[141,766,767],{"class":143,"line":260},[141,768,263],{},[141,770,771],{"class":143,"line":266},[141,772,269],{},[141,774,775],{"class":143,"line":272},[141,776,275],{},[141,778,779],{"class":143,"line":278},[141,780,281],{},[10,782,783],{},"Without responsive sizing, every device downloads the full-resolution image.",[127,785,787],{"id":786},"the-fix-astro-510","The fix (Astro 5.10+)",[10,789,790,791,121,794,797],{},"Astro's responsive image layout generates ",[114,792,793],{},"srcset",[114,795,796],{},"sizes"," automatically:",[132,799,801],{"className":134,"code":800,"language":136,"meta":137,"style":137},"---\nimport { Image } from 'astro:assets';\nimport heroImage from '../assets/hero.jpg';\n---\n\n\u003CImage\n  src={heroImage}\n  alt=\"Product hero shot\"\n  loading=\"eager\"\n  fetchpriority=\"high\"\n  layout=\"full-width\"\n/>\n",[114,802,803,807,811,815,819,823,827,831,835,839,843,848],{"__ignoreMap":137},[141,804,805],{"class":143,"line":144},[141,806,147],{},[141,808,809],{"class":143,"line":150},[141,810,153],{},[141,812,813],{"class":143,"line":156},[141,814,159],{},[141,816,817],{"class":143,"line":162},[141,818,147],{},[141,820,821],{"class":143,"line":167},[141,822,171],{"emptyLinePlaceholder":170},[141,824,825],{"class":143,"line":174},[141,826,251],{},[141,828,829],{"class":143,"line":180},[141,830,257],{},[141,832,833],{"class":143,"line":254},[141,834,263],{},[141,836,837],{"class":143,"line":260},[141,838,269],{},[141,840,841],{"class":143,"line":266},[141,842,275],{},[141,844,845],{"class":143,"line":272},[141,846,847],{},"  layout=\"full-width\"\n",[141,849,850],{"class":143,"line":278},[141,851,281],{},[10,853,854,855,858,859,861],{},"The ",[114,856,857],{},"layout=\"full-width\""," prop tells Astro to generate multiple sizes and let the browser pick the right one based on the viewport. No manual ",[114,860,793],{}," needed.",[10,863,864],{},"Enable the global responsive styles in your config:",[132,866,870],{"className":867,"code":868,"language":869,"meta":137,"style":137},"language-javascript shiki shiki-themes github-light github-dark","// astro.config.mjs\nimport { defineConfig } from 'astro/config';\n\nexport default defineConfig({\n  image: {\n    responsiveStyles: true,\n  },\n});\n","javascript",[114,871,872,877,882,886,891,896,901,906],{"__ignoreMap":137},[141,873,874],{"class":143,"line":144},[141,875,876],{},"// astro.config.mjs\n",[141,878,879],{"class":143,"line":150},[141,880,881],{},"import { defineConfig } from 'astro/config';\n",[141,883,884],{"class":143,"line":156},[141,885,171],{"emptyLinePlaceholder":170},[141,887,888],{"class":143,"line":162},[141,889,890],{},"export default defineConfig({\n",[141,892,893],{"class":143,"line":167},[141,894,895],{},"  image: {\n",[141,897,898],{"class":143,"line":174},[141,899,900],{},"    responsiveStyles: true,\n",[141,902,903],{"class":143,"line":180},[141,904,905],{},"  },\n",[141,907,908],{"class":143,"line":254},[141,909,910],{},"});\n",[10,912,913,914,917,918,322],{},"For more control over breakpoints, use the ",[114,915,916],{},"widths"," prop with ",[114,919,920],{},"\u003CPicture>",[132,922,924],{"className":134,"code":923,"language":136,"meta":137,"style":137},"---\nimport { Picture } from 'astro:assets';\nimport heroImage from '../assets/hero.jpg';\n---\n\n\u003CPicture\n  src={heroImage}\n  formats={['avif', 'webp']}\n  widths={[400, 800, 1200, 1600]}\n  sizes=\"(max-width: 600px) 400px, (max-width: 1024px) 800px, (max-width: 1400px) 1200px, 1600px\"\n  alt=\"Product hero shot\"\n  loading=\"eager\"\n  fetchpriority=\"high\"\n/>\n",[114,925,926,930,934,938,942,946,950,954,958,963,968,972,976,980],{"__ignoreMap":137},[141,927,928],{"class":143,"line":144},[141,929,147],{},[141,931,932],{"class":143,"line":150},[141,933,557],{},[141,935,936],{"class":143,"line":156},[141,937,159],{},[141,939,940],{"class":143,"line":162},[141,941,147],{},[141,943,944],{"class":143,"line":167},[141,945,171],{"emptyLinePlaceholder":170},[141,947,948],{"class":143,"line":174},[141,949,574],{},[141,951,952],{"class":143,"line":180},[141,953,257],{},[141,955,956],{"class":143,"line":254},[141,957,583],{},[141,959,960],{"class":143,"line":260},[141,961,962],{},"  widths={[400, 800, 1200, 1600]}\n",[141,964,965],{"class":143,"line":266},[141,966,967],{},"  sizes=\"(max-width: 600px) 400px, (max-width: 1024px) 800px, (max-width: 1400px) 1200px, 1600px\"\n",[141,969,970],{"class":143,"line":272},[141,971,263],{},[141,973,974],{"class":143,"line":278},[141,975,269],{},[141,977,978],{"class":143,"line":387},[141,979,275],{},[141,981,982],{"class":143,"line":393},[141,983,281],{},[127,985,987],{"id":986},"mobile-impact","Mobile impact",[35,989,990,1004],{},[38,991,992],{},[41,993,994,997,1000,1002],{},[44,995,996],{},"Device",[44,998,999],{},"Image downloaded",[44,1001,445],{},[44,1003,448],{},[51,1005,1006,1018,1031],{},[41,1007,1008,1011,1014,1016],{},[56,1009,1010],{},"Desktop (1440px)",[56,1012,1013],{},"1600w AVIF",[56,1015,663],{},[56,1017,663],{},[41,1019,1020,1023,1026,1028],{},[56,1021,1022],{},"Tablet (768px)",[56,1024,1025],{},"800w AVIF",[56,1027,663],{},[56,1029,1030],{},"62KB",[41,1032,1033,1036,1039,1041],{},[56,1034,1035],{},"Phone (375px)",[56,1037,1038],{},"400w AVIF",[56,1040,663],{},[56,1042,1043],{},"28KB",[10,1045,1046],{},"On mobile, the image is 80% smaller. That translates directly to LCP improvement.",[127,1048,434],{"id":1049},"results-2",[35,1051,1052,1066],{},[38,1053,1054],{},[41,1055,1056,1058,1061,1064],{},[44,1057,46],{},[44,1059,1060],{},"Before (mobile)",[44,1062,1063],{},"After (mobile)",[44,1065,451],{},[51,1067,1068,1082],{},[41,1069,1070,1073,1075,1077],{},[56,1071,1072],{},"Hero image (mobile)",[56,1074,663],{},[56,1076,1043],{},[56,1078,1079],{},[291,1080,1081],{},"-80%",[41,1083,1084,1087,1089,1092],{},[56,1085,1086],{},"LCP (mobile)",[56,1088,711],{},[56,1090,1091],{},"1.8s",[56,1093,1094],{},[291,1095,1096],{},"-600ms",[103,1098,1100],{"id":1099},"fix-4-astro-61-codec-specific-sharp-defaults-saved-18-site-wide","Fix 4: Astro 6.1 codec-specific Sharp defaults (saved 18% site-wide)",[10,1102,1103,1104,1106],{},"Before Astro 6.1, tuning image encoding meant setting options on every single ",[114,1105,116],{}," component. If you wanted MozJPEG compression for all JPEG fallbacks or higher AVIF effort for better compression, you'd repeat yourself across dozens of files.",[10,1108,1109],{},"Astro 6.1 introduced global codec-specific defaults. Configure once, apply everywhere.",[127,1111,130],{"id":1112},"the-problem-3",[132,1114,1116],{"className":134,"code":1115,"language":136,"meta":137,"style":137},"---\n// Without global config, you'd repeat this everywhere\nimport { Image } from 'astro:assets';\nimport photo from '../assets/photo.jpg';\n---\n\n\u003C!-- No way to set MozJPEG or AVIF effort globally before 6.1 -->\n\u003CImage src={photo} alt=\"Team photo\" quality={75} />\n",[114,1117,1118,1122,1127,1131,1136,1140,1144,1149],{"__ignoreMap":137},[141,1119,1120],{"class":143,"line":144},[141,1121,147],{},[141,1123,1124],{"class":143,"line":150},[141,1125,1126],{},"// Without global config, you'd repeat this everywhere\n",[141,1128,1129],{"class":143,"line":156},[141,1130,153],{},[141,1132,1133],{"class":143,"line":162},[141,1134,1135],{},"import photo from '../assets/photo.jpg';\n",[141,1137,1138],{"class":143,"line":167},[141,1139,147],{},[141,1141,1142],{"class":143,"line":174},[141,1143,171],{"emptyLinePlaceholder":170},[141,1145,1146],{"class":143,"line":180},[141,1147,1148],{},"\u003C!-- No way to set MozJPEG or AVIF effort globally before 6.1 -->\n",[141,1150,1151],{"class":143,"line":254},[141,1152,1153],{},"\u003CImage src={photo} alt=\"Team photo\" quality={75} />\n",[127,1155,216],{"id":1156},"the-fix-2",[132,1158,1160],{"className":867,"code":1159,"language":869,"meta":137,"style":137},"// astro.config.mjs\nimport { defineConfig } from 'astro/config';\n\nexport default defineConfig({\n  image: {\n    service: {\n      config: {\n        jpeg: {\n          mozjpeg: true,         // Better compression at same quality\n        },\n        webp: {\n          effort: 6,             // Higher effort = smaller files, slower builds\n          alphaQuality: 80,      // Quality for transparent WebP\n        },\n        avif: {\n          effort: 4,             // Balance between size and build speed\n          chromaSubsampling: '4:2:0',  // Standard subsampling for photos\n        },\n        png: {\n          compressionLevel: 9,   // Maximum PNG compression\n        },\n      },\n    },\n  },\n});\n",[114,1161,1162,1166,1170,1174,1178,1182,1187,1192,1197,1202,1207,1212,1217,1222,1226,1231,1236,1241,1245,1251,1257,1262,1268,1274,1279],{"__ignoreMap":137},[141,1163,1164],{"class":143,"line":144},[141,1165,876],{},[141,1167,1168],{"class":143,"line":150},[141,1169,881],{},[141,1171,1172],{"class":143,"line":156},[141,1173,171],{"emptyLinePlaceholder":170},[141,1175,1176],{"class":143,"line":162},[141,1177,890],{},[141,1179,1180],{"class":143,"line":167},[141,1181,895],{},[141,1183,1184],{"class":143,"line":174},[141,1185,1186],{},"    service: {\n",[141,1188,1189],{"class":143,"line":180},[141,1190,1191],{},"      config: {\n",[141,1193,1194],{"class":143,"line":254},[141,1195,1196],{},"        jpeg: {\n",[141,1198,1199],{"class":143,"line":260},[141,1200,1201],{},"          mozjpeg: true,         // Better compression at same quality\n",[141,1203,1204],{"class":143,"line":266},[141,1205,1206],{},"        },\n",[141,1208,1209],{"class":143,"line":272},[141,1210,1211],{},"        webp: {\n",[141,1213,1214],{"class":143,"line":278},[141,1215,1216],{},"          effort: 6,             // Higher effort = smaller files, slower builds\n",[141,1218,1219],{"class":143,"line":387},[141,1220,1221],{},"          alphaQuality: 80,      // Quality for transparent WebP\n",[141,1223,1224],{"class":143,"line":393},[141,1225,1206],{},[141,1227,1228],{"class":143,"line":399},[141,1229,1230],{},"        avif: {\n",[141,1232,1233],{"class":143,"line":405},[141,1234,1235],{},"          effort: 4,             // Balance between size and build speed\n",[141,1237,1238],{"class":143,"line":411},[141,1239,1240],{},"          chromaSubsampling: '4:2:0',  // Standard subsampling for photos\n",[141,1242,1243],{"class":143,"line":417},[141,1244,1206],{},[141,1246,1248],{"class":143,"line":1247},19,[141,1249,1250],{},"        png: {\n",[141,1252,1254],{"class":143,"line":1253},20,[141,1255,1256],{},"          compressionLevel: 9,   // Maximum PNG compression\n",[141,1258,1260],{"class":143,"line":1259},21,[141,1261,1206],{},[141,1263,1265],{"class":143,"line":1264},22,[141,1266,1267],{},"      },\n",[141,1269,1271],{"class":143,"line":1270},23,[141,1272,1273],{},"    },\n",[141,1275,1277],{"class":143,"line":1276},24,[141,1278,905],{},[141,1280,1282],{"class":143,"line":1281},25,[141,1283,910],{},[10,1285,1286,1287,1293],{},"Each codec option maps directly to ",[14,1288,1292],{"href":1289,"rel":1290},"https://sharp.pixelplumbing.com/api-output",[1291],"nofollow","Sharp's encoding API",". The most impactful settings:",[286,1295,1296,1304,1312],{},[194,1297,1298,1303],{},[291,1299,1300],{},[114,1301,1302],{},"jpeg.mozjpeg: true"," — MozJPEG produces 5-10% smaller JPEGs than the default encoder at the same visual quality. It's slower to encode but since this runs at build time, you don't care.",[194,1305,1306,1311],{},[291,1307,1308],{},[114,1309,1310],{},"avif.effort: 4"," — AVIF effort ranges from 0 (fastest, largest) to 9 (slowest, smallest). Default is 4. If your build times are tolerable, try 6 for an extra 5-8% compression.",[194,1313,1314,1319],{},[291,1315,1316],{},[114,1317,1318],{},"webp.effort: 6"," — Similar tradeoff. Higher effort squeezes more bytes out.",[10,1321,1322,1323,1326],{},"Per-image ",[114,1324,1325],{},"quality"," props still take precedence over global defaults, so you can override for specific images that need higher or lower quality.",[127,1328,434],{"id":1329},"results-3",[10,1331,1332],{},"Across a 40-page site with 120 images:",[35,1334,1335,1350],{},[38,1336,1337],{},[41,1338,1339,1341,1344,1347],{},[44,1340,626],{},[44,1342,1343],{},"Before (avg)",[44,1345,1346],{},"After (avg)",[44,1348,1349],{},"Saved",[51,1351,1352,1368,1383,1397],{},[41,1353,1354,1357,1360,1363],{},[56,1355,1356],{},"JPEG fallbacks",[56,1358,1359],{},"89KB",[56,1361,1362],{},"76KB",[56,1364,1365],{},[291,1366,1367],{},"-15%",[41,1369,1370,1372,1375,1378],{},[56,1371,498],{},[56,1373,1374],{},"64KB",[56,1376,1377],{},"52KB",[56,1379,1380],{},[291,1381,1382],{},"-19%",[41,1384,1385,1387,1390,1393],{},[56,1386,660],{},[56,1388,1389],{},"48KB",[56,1391,1392],{},"39KB",[56,1394,1395],{},[291,1396,1382],{},[41,1398,1399,1404,1409,1414],{},[56,1400,1401],{},[291,1402,1403],{},"Total image weight",[56,1405,1406],{},[291,1407,1408],{},"7.2MB",[56,1410,1411],{},[291,1412,1413],{},"5.9MB",[56,1415,1416],{},[291,1417,1418],{},"-18%",[10,1420,1421],{},"Build time increased from 28s to 34s — a worthwhile trade for permanently smaller images.",[103,1423,1425],{"id":1424},"fix-5-remote-images-from-your-cms-saved-11s-lcp","Fix 5: Remote images from your CMS (saved 1.1s LCP)",[10,1427,1428],{},"If your content comes from a headless CMS — Contentful, Sanity, Strapi, or similar — your hero images are probably remote URLs. Astro won't optimize them unless you explicitly allow the domain.",[127,1430,130],{"id":1431},"the-problem-4",[132,1433,1435],{"className":134,"code":1434,"language":136,"meta":137,"style":137},"---\nimport { Image } from 'astro:assets';\n---\n\n\u003C!-- Remote image — Astro renders this WITHOUT optimization -->\n\u003CImage\n  src=\"https://cdn.contentful.com/spaces/abc123/hero.jpg\"\n  alt=\"Blog hero\"\n  width={1200}\n  height={630}\n  loading=\"eager\"\n/>\n",[114,1436,1437,1441,1445,1449,1453,1458,1462,1467,1472,1477,1482,1486],{"__ignoreMap":137},[141,1438,1439],{"class":143,"line":144},[141,1440,147],{},[141,1442,1443],{"class":143,"line":150},[141,1444,153],{},[141,1446,1447],{"class":143,"line":156},[141,1448,147],{},[141,1450,1451],{"class":143,"line":162},[141,1452,171],{"emptyLinePlaceholder":170},[141,1454,1455],{"class":143,"line":167},[141,1456,1457],{},"\u003C!-- Remote image — Astro renders this WITHOUT optimization -->\n",[141,1459,1460],{"class":143,"line":174},[141,1461,251],{},[141,1463,1464],{"class":143,"line":180},[141,1465,1466],{},"  src=\"https://cdn.contentful.com/spaces/abc123/hero.jpg\"\n",[141,1468,1469],{"class":143,"line":254},[141,1470,1471],{},"  alt=\"Blog hero\"\n",[141,1473,1474],{"class":143,"line":260},[141,1475,1476],{},"  width={1200}\n",[141,1478,1479],{"class":143,"line":266},[141,1480,1481],{},"  height={630}\n",[141,1483,1484],{"class":143,"line":272},[141,1485,269],{},[141,1487,1488],{"class":143,"line":278},[141,1489,281],{},[10,1491,1492,1493,1495,1496,1499,1500,1503,1504,1507,1508,1511],{},"Without the domain in your config, Astro still renders the ",[114,1494,426],{}," tag (preserving ",[114,1497,1498],{},"width","/",[114,1501,1502],{},"height"," for ",[14,1505,1506],{"href":67},"CLS prevention","), but the image ",[291,1509,1510],{},"bypasses Sharp entirely",". No format conversion, no compression, no resizing. You get the raw file from the CMS CDN.",[127,1513,216],{"id":1514},"the-fix-3",[132,1516,1518],{"className":867,"code":1517,"language":869,"meta":137,"style":137},"// astro.config.mjs\nimport { defineConfig } from 'astro/config';\n\nexport default defineConfig({\n  image: {\n    domains: ['cdn.contentful.com', 'images.ctfassets.net'],\n    // Or use patterns for more flexibility\n    remotePatterns: [\n      {\n        protocol: 'https',\n        hostname: '**.sanity.io',\n      },\n    ],\n  },\n});\n",[114,1519,1520,1524,1528,1532,1536,1540,1545,1550,1555,1560,1565,1570,1574,1579,1583],{"__ignoreMap":137},[141,1521,1522],{"class":143,"line":144},[141,1523,876],{},[141,1525,1526],{"class":143,"line":150},[141,1527,881],{},[141,1529,1530],{"class":143,"line":156},[141,1531,171],{"emptyLinePlaceholder":170},[141,1533,1534],{"class":143,"line":162},[141,1535,890],{},[141,1537,1538],{"class":143,"line":167},[141,1539,895],{},[141,1541,1542],{"class":143,"line":174},[141,1543,1544],{},"    domains: ['cdn.contentful.com', 'images.ctfassets.net'],\n",[141,1546,1547],{"class":143,"line":180},[141,1548,1549],{},"    // Or use patterns for more flexibility\n",[141,1551,1552],{"class":143,"line":254},[141,1553,1554],{},"    remotePatterns: [\n",[141,1556,1557],{"class":143,"line":260},[141,1558,1559],{},"      {\n",[141,1561,1562],{"class":143,"line":266},[141,1563,1564],{},"        protocol: 'https',\n",[141,1566,1567],{"class":143,"line":272},[141,1568,1569],{},"        hostname: '**.sanity.io',\n",[141,1571,1572],{"class":143,"line":278},[141,1573,1267],{},[141,1575,1576],{"class":143,"line":387},[141,1577,1578],{},"    ],\n",[141,1580,1581],{"class":143,"line":393},[141,1582,905],{},[141,1584,1585],{"class":143,"line":399},[141,1586,910],{},[10,1588,1589],{},"Once the domain is authorized, Astro processes remote images through Sharp — converting to WebP/AVIF, compressing, and resizing just like local images.",[127,1591,1593],{"id":1592},"for-ssr-sites-caching-matters","For SSR sites: caching matters",[10,1595,1596,1597,1600,1601,1604,1605,121,1608,1611],{},"If you're running Astro in SSR mode (not static), remote images are processed on each request by default. Astro caches processed images in ",[114,1598,1599],{},"./node_modules/.astro/"," and respects the remote server's ",[114,1602,1603],{},"Cache-Control"," headers. Since Astro 5.1, it also uses ",[114,1606,1607],{},"Last-Modified",[114,1609,1610],{},"ETag"," headers to avoid re-downloading unchanged images.",[10,1613,1614],{},"Make sure your CMS CDN sends proper cache headers. Most do by default, but it's worth verifying:",[132,1616,1620],{"className":1617,"code":1618,"language":1619,"meta":137,"style":137},"language-bash shiki shiki-themes github-light github-dark","curl -sI https://cdn.contentful.com/spaces/abc123/hero.jpg | grep -i cache-control\n# Should show something like: cache-control: max-age=31536000\n","bash",[114,1621,1622,1649],{"__ignoreMap":137},[141,1623,1624,1628,1632,1636,1640,1643,1646],{"class":143,"line":144},[141,1625,1627],{"class":1626},"sScJk","curl",[141,1629,1631],{"class":1630},"sj4cs"," -sI",[141,1633,1635],{"class":1634},"sZZnC"," https://cdn.contentful.com/spaces/abc123/hero.jpg",[141,1637,1639],{"class":1638},"szBVR"," |",[141,1641,1642],{"class":1626}," grep",[141,1644,1645],{"class":1630}," -i",[141,1647,1648],{"class":1634}," cache-control\n",[141,1650,1651],{"class":143,"line":150},[141,1652,1654],{"class":1653},"sJ8bj","# Should show something like: cache-control: max-age=31536000\n",[127,1656,434],{"id":1657},"results-4",[35,1659,1660,1674],{},[38,1661,1662],{},[41,1663,1664,1666,1669,1672],{},[44,1665,46],{},[44,1667,1668],{},"Before (unoptimized remote)",[44,1670,1671],{},"After (optimized)",[44,1673,451],{},[51,1675,1676,1690],{},[41,1677,1678,1680,1683,1685],{},[56,1679,87],{},[56,1681,1682],{},"1.4MB (JPEG)",[56,1684,698],{},[56,1686,1687],{},[291,1688,1689],{},"-90%",[41,1691,1692,1694,1697,1700],{},[56,1693,17],{},[56,1695,1696],{},"3.6s",[56,1698,1699],{},"2.5s",[56,1701,1702],{},[291,1703,1704],{},"-1.1s",[103,1706,1708],{"id":1707},"the-full-picture","The full picture",[10,1710,1711],{},"Five fixes, each targeting a different part of the image pipeline:",[35,1713,1714,1727],{},[38,1715,1716],{},[41,1717,1718,1721,1724],{},[44,1719,1720],{},"Fix",[44,1722,1723],{},"Technique",[44,1725,1726],{},"LCP Impact",[51,1728,1729,1745,1759,1775,1788],{},[41,1730,1731,1734,1741],{},[56,1732,1733],{},"1",[56,1735,1736,1738,1739],{},[114,1737,295],{}," + ",[114,1740,303],{},[56,1742,1743],{},[291,1744,467],{},[41,1746,1747,1750,1755],{},[56,1748,1749],{},"2",[56,1751,1752,1754],{},[114,1753,920],{}," with AVIF + WebP",[56,1756,1757],{},[291,1758,716],{},[41,1760,1761,1764,1770],{},[56,1762,1763],{},"3",[56,1765,1766,1767],{},"Responsive images with ",[114,1768,1769],{},"layout",[56,1771,1772],{},[291,1773,1774],{},"-600ms (mobile)",[41,1776,1777,1780,1783],{},[56,1778,1779],{},"4",[56,1781,1782],{},"Astro 6.1 codec-specific Sharp defaults",[56,1784,1785],{},[291,1786,1787],{},"-18% image weight",[41,1789,1790,1793,1796],{},[56,1791,1792],{},"5",[56,1794,1795],{},"Authorize remote CMS domains",[56,1797,1798],{},[291,1799,1704],{},[10,1801,1802],{},"Applied together to our test site:",[35,1804,1805,1817],{},[38,1806,1807],{},[41,1808,1809,1811,1813,1815],{},[44,1810,46],{},[44,1812,445],{},[44,1814,448],{},[44,1816,451],{},[51,1818,1819,1833,1848,1862,1874,1886],{},[41,1820,1821,1823,1825,1828],{},[56,1822,1086],{},[56,1824,60],{},[56,1826,1827],{},"1.4s",[56,1829,1830],{},[291,1831,1832],{},"-67%",[41,1834,1835,1838,1840,1843],{},[56,1836,1837],{},"LCP (desktop)",[56,1839,462],{},[56,1841,1842],{},"0.9s",[56,1844,1845],{},[291,1846,1847],{},"-68%",[41,1849,1850,1852,1854,1857],{},[56,1851,68],{},[56,1853,71],{},[56,1855,1856],{},"0.01",[56,1858,1859],{},[291,1860,1861],{},"-93%",[41,1863,1864,1866,1868,1871],{},[56,1865,79],{},[56,1867,82],{},[56,1869,1870],{},"42ms",[56,1872,1873],{},"No meaningful change",[41,1875,1876,1878,1880,1882],{},[56,1877,1403],{},[56,1879,1408],{},[56,1881,1413],{},[56,1883,1884],{},[291,1885,1418],{},[41,1887,1888,1890,1892,1895],{},[56,1889,95],{},[56,1891,98],{},[56,1893,1894],{},"96",[56,1896,1897],{},[291,1898,1899],{},"+44 points",[10,1901,1902,1903,121,1905,1908,1909,1913],{},"The CLS improvement comes from ",[114,1904,116],{},[114,1906,1907],{},"\u003CPicture />"," automatically inferring dimensions. The INP was already good — that's ",[14,1910,1912],{"href":1911},"/blog/astro-performance-optimization/","Astro's zero-JS advantage",".",[103,1915,1917],{"id":1916},"image-optimization-checklist-for-astro","Image optimization checklist for Astro",[10,1919,1920],{},"Before deploying, verify each of these:",[286,1922,1925,1938,1949,1961,1975,1989,2002,2011],{"className":1923},[1924],"contains-task-list",[194,1926,1929,1933,1934,121,1936],{"className":1927},[1928],"task-list-item",[1930,1931],"input",{"disabled":170,"type":1932},"checkbox"," LCP image uses ",[114,1935,295],{},[114,1937,303],{},[194,1939,1941,1933,1943,1945,1946],{"className":1940},[1928],[1930,1942],{"disabled":170,"type":1932},[114,1944,920],{}," with ",[114,1947,1948],{},"formats={['avif', 'webp']}",[194,1950,1952,1954,1955,1957,1958,1960],{"className":1951},[1928],[1930,1953],{"disabled":170,"type":1932}," All other images use ",[114,1956,116],{}," (not raw ",[114,1959,426],{},")",[194,1962,1964,1966,1967,1970,1971,1974],{"className":1963},[1928],[1930,1965],{"disabled":170,"type":1932}," Images are in ",[114,1968,1969],{},"src/"," not ",[114,1972,1973],{},"public/"," (so Sharp can process them)",[194,1976,1978,1980,1981,1983,1984,1499,1986,1988],{"className":1977},[1928],[1930,1979],{"disabled":170,"type":1932}," Responsive ",[114,1982,1769],{}," or manual ",[114,1985,916],{},[114,1987,796],{}," set for hero images",[194,1990,1992,1994,1995,1998,1999],{"className":1991},[1928],[1930,1993],{"disabled":170,"type":1932}," Remote CMS domains added to ",[114,1996,1997],{},"image.domains"," or ",[114,2000,2001],{},"image.remotePatterns",[194,2003,2005,2007,2008],{"className":2004},[1928],[1930,2006],{"disabled":170,"type":1932}," Astro 6.1+ codec defaults configured in ",[114,2009,2010],{},"astro.config.mjs",[194,2012,2014,2016,2017,2019],{"className":2013},[1928],[1930,2015],{"disabled":170,"type":1932}," No images above the fold using ",[114,2018,120],{}," (the default)",[103,2021,2023],{"id":2022},"frequently-asked-questions","Frequently Asked Questions",[127,2025,2027],{"id":2026},"why-is-my-astro-sites-lcp-slow-when-astro-is-supposed-to-be-fast","Why is my Astro site's LCP slow when Astro is supposed to be fast?",[10,2029,2030,2031,2033,2034,2036,2037,121,2039,2041],{},"Astro ships zero JavaScript by default, but LCP is usually about images, not JavaScript. If your hero image is unoptimized, uses the default ",[114,2032,120],{},", or loads from an unauthorized remote domain, your LCP will suffer regardless of how little JavaScript you ship. Use Astro's ",[114,2035,116],{}," component with ",[114,2038,295],{},[114,2040,303],{}," on your LCP image.",[127,2043,2045],{"id":2044},"should-i-use-the-image-component-or-the-picture-component-in-astro","Should I use the Image component or the Picture component in Astro?",[10,2047,2048,2049,2051,2052,2054,2055,2057,2058,2061],{},"Use ",[114,2050,920],{}," for your LCP element and any image where you want the browser to choose between AVIF and WebP. ",[114,2053,920],{}," generates multiple ",[114,2056,609],{}," elements so the browser picks the smallest format it supports. Use ",[114,2059,2060],{},"\u003CImage>"," for simpler cases where WebP alone is sufficient.",[127,2063,2065],{"id":2064},"what-image-format-is-best-for-astro-webp-or-avif","What image format is best for Astro — WebP or AVIF?",[10,2067,2068,2069,2072,2073,2036,2075,2077],{},"AVIF produces ",[291,2070,2071],{},"20-30% smaller files"," than WebP at comparable quality, but takes longer to encode at build time. Use the ",[114,2074,920],{},[114,2076,1948],{}," to serve AVIF to browsers that support it and WebP as a fallback. Astro 6.1's codec-specific config lets you tune encoding effort globally to balance file size and build speed.",[127,2079,2081],{"id":2080},"how-do-i-optimize-remote-images-from-a-cms-in-astro","How do I optimize remote images from a CMS in Astro?",[10,2083,2084,2085,2087,2088,2090,2091,2093],{},"Add your CMS domain to the ",[114,2086,1997],{}," array or use ",[114,2089,2001],{}," in ",[114,2092,2010],{},". Without this, Astro renders remote images without optimization — they bypass Sharp entirely. This is a common gotcha for headless CMS setups where hero images come from external CDNs.",[127,2095,2097],{"id":2096},"does-astros-image-component-prevent-cls","Does Astro's Image component prevent CLS?",[10,2099,2100,2101,2103,2104,121,2106,2108,2109,2112,2113,121,2115,2117,2118,2120,2121,2124,2125,2128,2129,2132],{},"Yes. Astro's ",[114,2102,116],{}," component automatically infers ",[114,2105,1498],{},[114,2107,1502],{}," from local images, which reserves space in the layout and prevents ",[14,2110,2111],{"href":67},"Cumulative Layout Shift",". For remote images, you must provide ",[114,2114,1498],{},[114,2116,1502],{}," manually. Using the responsive ",[114,2119,1769],{}," prop (",[114,2122,2123],{},"constrained",", ",[114,2126,2127],{},"full-width",", or ",[114,2130,2131],{},"fixed",") also handles sizing automatically.",[103,2134,2136],{"id":2135},"whats-next","What's next",[10,2138,2139,2140,2144,2145,1913],{},"If you've optimized your images and LCP is still slow, the problem might be elsewhere — render-blocking CSS, slow server response, or ",[14,2141,2143],{"href":2142},"/blog/third-party-scripts-core-web-vitals/","third-party scripts"," blocking the main thread. For a broader look at Astro performance beyond images, see our guide on ",[14,2146,2147],{"href":1911},"Astro's zero-JS architecture and islands",[10,2149,2150,2151,2154],{},"Need help identifying exactly what's slowing your Astro site down? Run it through ",[14,2152,2153],{"href":1499},"PageSpeedFix"," for a detailed Core Web Vitals analysis with framework-specific fixes.",[2156,2157,2158],"style",{},"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 pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":137,"searchDepth":150,"depth":150,"links":2160},[2161,2167,2173,2179,2184,2190,2191,2192,2199],{"id":105,"depth":150,"text":106,"children":2162},[2163,2164,2165,2166],{"id":129,"depth":156,"text":130},{"id":215,"depth":156,"text":216},{"id":314,"depth":156,"text":315},{"id":433,"depth":156,"text":434},{"id":489,"depth":150,"text":490,"children":2168},[2169,2170,2171,2172],{"id":502,"depth":156,"text":130},{"id":543,"depth":156,"text":216},{"id":613,"depth":156,"text":614},{"id":672,"depth":156,"text":434},{"id":719,"depth":150,"text":720,"children":2174},[2175,2176,2177,2178],{"id":726,"depth":156,"text":130},{"id":786,"depth":156,"text":787},{"id":986,"depth":156,"text":987},{"id":1049,"depth":156,"text":434},{"id":1099,"depth":150,"text":1100,"children":2180},[2181,2182,2183],{"id":1112,"depth":156,"text":130},{"id":1156,"depth":156,"text":216},{"id":1329,"depth":156,"text":434},{"id":1424,"depth":150,"text":1425,"children":2185},[2186,2187,2188,2189],{"id":1431,"depth":156,"text":130},{"id":1514,"depth":156,"text":216},{"id":1592,"depth":156,"text":1593},{"id":1657,"depth":156,"text":434},{"id":1707,"depth":150,"text":1708},{"id":1916,"depth":150,"text":1917},{"id":2022,"depth":150,"text":2023,"children":2193},[2194,2195,2196,2197,2198],{"id":2026,"depth":156,"text":2027},{"id":2044,"depth":156,"text":2045},{"id":2064,"depth":156,"text":2065},{"id":2080,"depth":156,"text":2081},{"id":2096,"depth":156,"text":2097},{"id":2135,"depth":150,"text":2136},"Your Astro site's LCP is slow because of images. Here's how to fix it — from the lazy loading trap to Astro 6.1's codec-specific Sharp defaults, with measurable before-and-after results.","md",[2203,2205,2207,2209,2211],{"question":2027,"answer":2204},"Astro ships zero JavaScript by default, but LCP is usually about images, not JavaScript. If your hero image is unoptimized, uses the default lazy loading, or loads from an unauthorized remote domain, your LCP will suffer regardless of how little JavaScript you ship. Use Astro's Image component with loading='eager' and fetchpriority='high' on your LCP image.",{"question":2045,"answer":2206},"Use Picture for your LCP element and any image where you want the browser to choose between AVIF and WebP. Picture generates multiple source elements so the browser picks the smallest format it supports. Use Image for simpler cases where WebP alone is sufficient.",{"question":2065,"answer":2208},"AVIF produces 20-30% smaller files than WebP at comparable quality, but takes longer to encode at build time. Use the Picture component with formats=['avif', 'webp'] to serve AVIF to browsers that support it and WebP as a fallback. Astro 6.1's codec-specific config lets you tune encoding effort globally to balance file size and build speed.",{"question":2081,"answer":2210},"Add your CMS domain to the image.domains array or use image.remotePatterns in astro.config.mjs. Without this, Astro renders remote images without optimization — they bypass Sharp entirely. This is a common gotcha for headless CMS setups where hero images come from external CDNs.",{"question":2097,"answer":2212},"Yes. Astro's Image component automatically infers width and height from local images, which reserves space in the layout and prevents Cumulative Layout Shift. For remote images, you must provide width and height manually. Using the responsive layout prop (constrained, full-width, or fixed) also handles sizing automatically.","/og/astro-image-optimization.png","Astro guide: Astro Image Optimization: Fix LCP Without the Guesswork",null,{},"/blog/astro-image-optimization","2026-04-19",[2220,2223,2226,2229,2232],{"title":2221,"url":2222},"Images - Astro Documentation","https://docs.astro.build/en/guides/images/",{"title":2224,"url":2225},"Astro 6.1 Release Notes","https://astro.build/blog/astro-610/",{"title":2227,"url":2228},"Largest Contentful Paint (LCP) - web.dev","https://web.dev/articles/lcp",{"title":2230,"url":2231},"Optimize Largest Contentful Paint - web.dev","https://web.dev/articles/optimize-lcp",{"title":2233,"url":2234},"Sharp Image Processing Library","https://sharp.pixelplumbing.com/",{"title":5,"description":2200},"blog/astro-image-optimization",[136,2238,2239,2240,2241,2242],"image-optimization","lcp","core-web-vitals","performance","sharp","1TN69VSkY5EzgaMImMLlLorDxRXG07BUBG3uaiNK1NY",1776939172537]