[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"sanity-_E0USnaexm6ZeSN8zgjMQXhCInABejTfDSUq_Mbkrds":3,"sanity-9IzYyCgOE_kGWlm4yu-aaQFSwrREJWhL4yvqXUilXs4":1964},{"data":4,"sourceMap":-1},{"latestPodcast":5,"latestReleases":14,"post":39,"recent":1939},[6],{"_id":7,"publishedAt":8,"slug":9,"sponsored":12,"title":13},"4d0175f4-40a8-47eb-9bb3-a453b326aa7d","2026-07-03T07:40:00.000Z",{"_type":10,"current":11},"slug","the-good-the-bad-and-the-ai-apps",null,"The good, the bad, and the AI apps",[15,21,27,33],{"_id":16,"publishedAt":17,"slug":18,"title":20},"eb5b66eb-9410-4329-83bb-22bbff39402a","2026-04-28T13:00:00.000Z",{"_type":10,"current":19},"turn-scattered-knowledge-into-trusted-intelligence","Turning scattered knowledge into trusted intelligence: Stack Internal 2026.3",{"_id":22,"publishedAt":23,"slug":24,"title":26},"369c2401-b62e-4a37-8ff8-bf603023ecad","2026-03-02T15:03:00.988Z",{"_type":10,"current":25},"what-s-new-at-stack-overflow-march-2026","What’s new at Stack Overflow: March 2026",{"_id":28,"publishedAt":29,"slug":30,"title":32},"5e9053a4-07ea-447c-91ea-29e0b6228537","2026-02-02T15:00:00.000Z",{"_type":10,"current":31},"what-s-new-at-stack-overflow-february-2026","What’s new at Stack Overflow: February 2026",{"_id":34,"publishedAt":35,"slug":36,"title":38},"a1b538eb-a8a6-46d0-80a1-ac70ec9bb935","2026-01-05T10:00:00.000-05:00",{"_type":10,"current":37},"what-s-new-at-stack-overflow-january-2026","What’s new at Stack Overflow: January 2026",{"_createdAt":40,"_id":41,"_rev":42,"_system":43,"_type":46,"_updatedAt":47,"author":48,"body":65,"comments":1900,"dateUrl":1901,"excerpt":1902,"image":1903,"legacyBody":1906,"product":12,"publishedAt":1909,"slug":1910,"sponsored":12,"tags":1912,"title":1938,"visible":1900},"2023-05-24T12:51:04Z","wp-post-19849","Bqj3l3jZyXV24sfjnzZkZZ",{"base":44},{"id":41,"rev":45},"0aYkJXBENQTxI4C1z7OwOp","blogPost","2026-05-11T18:32:12Z",[49],{"_createdAt":50,"_id":51,"_rev":52,"_type":53,"_updatedAt":54,"avatar":55,"bio":60,"employee":61,"name":62,"slug":63},"2023-05-23T16:27:18Z","wp-author-cap-19583","dgl3SCUzppW3U2LvCoP6c0","blogAuthor","2023-06-20T15:05:12Z",{"_type":56,"asset":57},"image",{"_ref":58,"_type":59},"image-cbc6b28272d341ec949ceca510bbab0eb21b8cd4-1200x1200-jpg","reference","Addy Osmani is an engineering manager working on Google Chrome. He leads Developer Experience teams focused on making the web fast. His teams work on projects like Lighthouse, PageSpeed Insights, contributions to popular JavaScript frameworks and Content Management Systems. \n","none","Addy Osmani",{"current":64},"addy-osmani",[66,78,107,133,141,162,171,187,195,203,222,230,246,264,272,338,347,366,371,379,441,460,467,485,490,497,506,537,553,576,597,629,632,640,661,669,712,717,724,731,748,805,813,821,825,833,849,853,861,890,893,946,951,981,989,1008,1024,1028,1047,1058,1062,1070,1078,1083,1090,1098,1102,1129,1137,1145,1183,1186,1201,1220,1224,1232,1240,1244,1262,1266,1322,1360,1368,1429,1437,1445,1467,1475,1494,1509,1517,1532,1535,1543,1580,1588,1591,1607,1615,1620,1639,1644,1651,1658,1676,1684,1692,1697,1758,1773,1776,1809,1814,1828,1831,1846,1851,1858,1866,1881],{"_key":67,"_type":68,"children":69,"markDefs":76,"style":77},"f4df1fc91371","block",[70],{"_key":71,"_type":72,"marks":73,"text":75},"f4df1fc913710","span",[74],"em","[Ed. note: While we take some time to rest up over the holidays and prepare for next year, we are re-publishing our top ten posts for the year. Please enjoy our favorite work this year and we’ll see you in 2023.]",[],"normal",{"_key":79,"_type":68,"children":80,"markDefs":103,"style":77},"72f5fc64bc5a",[81,85,90,94,99],{"_key":82,"_type":72,"marks":83,"text":84},"72f5fc64bc5a0",[],"Images are one of the most pervasive parts of the web. This isn’t a huge surprise as we humans are quite visual and the ",{"_key":86,"_type":72,"marks":87,"text":89},"72f5fc64bc5a1",[88],"code","\u003Cimg>",{"_key":91,"_type":72,"marks":92,"text":93},"72f5fc64bc5a2",[]," tag has been around for almost 30 years. Images are so prominent that they are part of the most important content in over ",{"_key":95,"_type":72,"marks":96,"text":98},"72f5fc64bc5a3",[97],"b938c79bbb0f","~70%",{"_key":100,"_type":72,"marks":101,"text":102},"72f5fc64bc5a4",[]," of pages on both mobile and desktop according to the largest contentful paint metric. We like images over on the Stack Overflow blog too.",[104],{"_key":97,"_type":105,"href":106,"reference":12},"link","https:\u002F\u002Falmanac.httparchive.org\u002Fen\u002F2021\u002Fmedia#images",{"_key":108,"_type":68,"children":109,"markDefs":130,"style":77},"76689cec15ef",[110,114,117,121,126],{"_key":111,"_type":72,"marks":112,"text":113},"76689cec15ef0",[],"The humble ",{"_key":115,"_type":72,"marks":116,"text":89},"76689cec15ef1",[88],{"_key":118,"_type":72,"marks":119,"text":120},"76689cec15ef2",[]," element has gained some superpowers since it was created. Given how central it is to image optimization on the web, let’s catch up on what it can do and how it can help improve user-experience and the ",{"_key":122,"_type":72,"marks":123,"text":125},"76689cec15ef3",[124],"6c2d7b83ac93","Core Web Vitals",{"_key":127,"_type":72,"marks":128,"text":129},"76689cec15ef4",[],".",[131],{"_key":124,"_type":105,"href":132,"reference":12},"https:\u002F\u002Fweb.dev\u002Fmeasure\u002F",{"_key":134,"_type":68,"children":135,"markDefs":140,"style":77},"03e0d5710deb",[136],{"_key":137,"_type":72,"marks":138,"text":139},"03e0d5710deb0",[],"First, some tips to get us started optimizing our metrics:",[],{"_key":142,"_type":68,"children":143,"level":157,"listItem":158,"markDefs":159,"style":77},"a7d5b1ef2225",[144,148,153],{"_key":145,"_type":72,"marks":146,"text":147},"a7d5b1ef22250",[],"For a fast ",{"_key":149,"_type":72,"marks":150,"text":152},"a7d5b1ef22251",[151],"798691195362","Largest Contentful Paint",{"_key":154,"_type":72,"marks":155,"text":156},"a7d5b1ef22252",[],": ",1,"bullet",[160],{"_key":151,"_type":105,"href":161,"reference":12},"https:\u002F\u002Fweb.dev\u002Flcp\u002F",{"_key":163,"_type":68,"children":164,"level":169,"listItem":158,"markDefs":170,"style":77},"af79e08b6247",[165],{"_key":166,"_type":72,"marks":167,"text":168},"af79e08b62470",[],"Request your key hero image early",2,[],{"_key":172,"_type":68,"children":173,"level":169,"listItem":158,"markDefs":186,"style":77},"ede015c48efe",[174,178,182],{"_key":175,"_type":72,"marks":176,"text":177},"ede015c48efe0",[],"Use ",{"_key":179,"_type":72,"marks":180,"text":181},"ede015c48efe1",[88],"srcset",{"_key":183,"_type":72,"marks":184,"text":185},"ede015c48efe2",[]," + efficient modern image formats",[],{"_key":188,"_type":68,"children":189,"level":169,"listItem":158,"markDefs":194,"style":77},"9257567ce944",[190],{"_key":191,"_type":72,"marks":192,"text":193},"9257567ce9440",[],"Avoid wasting pixels (compress, don’t serve overly high DPR images)",[],{"_key":196,"_type":68,"children":197,"level":169,"listItem":158,"markDefs":202,"style":77},"174ea149e983",[198],{"_key":199,"_type":72,"marks":200,"text":201},"174ea149e9830",[],"Lazy-load offscreen images (reduce network contention for key resources)",[],{"_key":204,"_type":68,"children":205,"level":157,"listItem":158,"markDefs":219,"style":77},"1ccdc75452e6",[206,210,215],{"_key":207,"_type":72,"marks":208,"text":209},"1ccdc75452e60",[],"For a low ",{"_key":211,"_type":72,"marks":212,"text":214},"1ccdc75452e61",[213],"7a088b0a246d","Cumulative Layout Shift",{"_key":216,"_type":72,"marks":217,"text":218},"1ccdc75452e62",[],":",[220],{"_key":213,"_type":105,"href":221,"reference":12},"https:\u002F\u002Fweb.dev\u002Fcls\u002F",{"_key":223,"_type":68,"children":224,"level":169,"listItem":158,"markDefs":229,"style":77},"4db64d99102e",[225],{"_key":226,"_type":72,"marks":227,"text":228},"4db64d99102e0",[],"Set dimensions (width, height) on your images",[],{"_key":231,"_type":68,"children":232,"level":169,"listItem":158,"markDefs":245,"style":77},"864919a06c57",[233,237,241],{"_key":234,"_type":72,"marks":235,"text":236},"864919a06c570",[],"Use CSS ",{"_key":238,"_type":72,"marks":239,"text":240},"864919a06c571",[88],"aspect-ratio",{"_key":242,"_type":72,"marks":243,"text":244},"864919a06c572",[]," or aspect ratio boxes to reserve space otherwise",[],{"_key":247,"_type":68,"children":248,"level":157,"listItem":158,"markDefs":261,"style":77},"5a812ed252ea",[249,253,258],{"_key":250,"_type":72,"marks":251,"text":252},"5a812ed252ea0",[],"For low impact to ",{"_key":254,"_type":72,"marks":255,"text":257},"5a812ed252ea1",[256],"9f536adab9be","First Input Delay",{"_key":259,"_type":72,"marks":260,"text":218},"5a812ed252ea2",[],[262],{"_key":256,"_type":105,"href":263,"reference":12},"https:\u002F\u002Fweb.dev\u002Ffid\u002F",{"_key":265,"_type":68,"children":266,"level":169,"listItem":158,"markDefs":271,"style":77},"96fcc8b4b102",[267],{"_key":268,"_type":72,"marks":269,"text":270},"96fcc8b4b1020",[],"Avoid images causing network contention with other critical resources like CSS and JS. While not render-blocking, they can indirectly impact render performance.",[],{"_key":273,"_type":68,"children":274,"markDefs":331,"style":77},"c203de6e601b",[275,280,284,287,291,296,300,304,309,312,316,319,323,328],{"_key":276,"_type":72,"marks":277,"text":279},"c203de6e601b0",[278],"strong","Note: ",{"_key":281,"_type":72,"marks":282,"text":283},"c203de6e601b1",[],"Modern image components that build on ",{"_key":285,"_type":72,"marks":286,"text":89},"c203de6e601b2",[88],{"_key":288,"_type":72,"marks":289,"text":290},"c203de6e601b3",[],", like ",{"_key":292,"_type":72,"marks":293,"text":295},"c203de6e601b4",[294],"8601b2e4388d","Next.js ",{"_key":297,"_type":72,"marks":298,"text":299},"c203de6e601b5",[294,88],"\u003CImage>",{"_key":301,"_type":72,"marks":302,"text":303},"c203de6e601b6",[]," (for React) and ",{"_key":305,"_type":72,"marks":306,"text":308},"c203de6e601b7",[307],"f922e60b99f8","Nuxt ",{"_key":310,"_type":72,"marks":311,"text":56},"c203de6e601b8",[307,88],{"_key":313,"_type":72,"marks":314,"text":315},"c203de6e601b9",[]," (for Vue) try to bake in as many of these concepts as possible by default. We’ll cover this later. You can of course also do this manually just using the ",{"_key":317,"_type":72,"marks":318,"text":89},"c203de6e601b10",[88],{"_key":320,"_type":72,"marks":321,"text":322},"c203de6e601b11",[]," element directly. If using 11ty for your static sites, try the ",{"_key":324,"_type":72,"marks":325,"text":327},"c203de6e601b12",[326],"5efb4b550b5d","11ty high-performance blog template",{"_key":329,"_type":72,"marks":330,"text":129},"c203de6e601b13",[],[332,334,336],{"_key":294,"_type":105,"href":333,"reference":12},"https:\u002F\u002Fnextjs.org\u002Fdocs\u002Fapi-reference\u002Fnext\u002Fimage",{"_key":307,"_type":105,"href":335,"reference":12},"https:\u002F\u002Fimage.nuxtjs.org\u002F",{"_key":326,"_type":105,"href":337,"reference":12},"https:\u002F\u002Fgithub.com\u002Fgoogle\u002Feleventy-high-performance-blog",{"_key":339,"_type":68,"children":340,"markDefs":345,"style":346},"9a5bfe397e4a",[341],{"_key":342,"_type":72,"marks":343,"text":344},"9a5bfe397e4a0",[],"Image impact on user-experience and the Core Web Vitals",[],"h2",{"_key":348,"_type":68,"children":349,"markDefs":363,"style":77},"717e36dd5f89",[350,354,359],{"_key":351,"_type":72,"marks":352,"text":353},"717e36dd5f890",[],"You may have heard of Core Web Vitals (CWV). It’s an initiative by Google to share unified guidance for quality signals that can be key to delivering a great user-experience on the web. CWV is part of a set of ",{"_key":355,"_type":72,"marks":356,"text":358},"717e36dd5f891",[357],"97ec3e97e263","page experience signals",{"_key":360,"_type":72,"marks":361,"text":362},"717e36dd5f892",[]," Google Search will be evaluating for ranking. Images can impact the CWV in a number of ways.",[364],{"_key":357,"_type":105,"href":365,"reference":12},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fblog\u002F2020\u002F11\u002Ftiming-for-page-experience",{"_key":367,"_type":56,"alt":12,"asset":368,"caption":370,"markDefs":12},"695044a14a12",{"_ref":369,"_type":59},"image-747711bd8a1cb0426a52cc6f7e0440bb9d6d637b-1600x897-png","Above, the Stack Overflow “The Key” hero image was the Largest Contentful Paint element",{"_key":372,"_type":68,"children":373,"markDefs":378,"style":77},"2b76b0f022f1",[374],{"_key":375,"_type":72,"marks":376,"text":377},"2b76b0f022f10",[],"",[],{"_key":380,"_type":68,"children":381,"markDefs":430,"style":77},"80aab1d781ed",[382,386,391,395,400,404,409,413,418,422,427],{"_key":383,"_type":72,"marks":384,"text":385},"80aab1d781ed0",[],"In this guide, we will be using Lighthouse to identify opportunities to improve the Core Web Vitals, walking through optimizations for each metric. ",{"_key":387,"_type":72,"marks":388,"text":390},"80aab1d781ed1",[389],"a0eaace35636","Lighthouse",{"_key":392,"_type":72,"marks":393,"text":394},"80aab1d781ed2",[]," is an open-source, automated tool for improving the quality of web pages. You can find it in the ",{"_key":396,"_type":72,"marks":397,"text":399},"80aab1d781ed3",[398],"072b101f97ed","Chrome DevTools",{"_key":401,"_type":72,"marks":402,"text":403},"80aab1d781ed4",[]," suite of debugging tools and run it against any web page, whether public or requiring authentication. You can also find Lighthouse in ",{"_key":405,"_type":72,"marks":406,"text":408},"80aab1d781ed5",[407],"a2bbdfc27135","PageSpeed Insights",{"_key":410,"_type":72,"marks":411,"text":412},"80aab1d781ed6",[],", ",{"_key":414,"_type":72,"marks":415,"text":417},"80aab1d781ed7",[416],"e6719946bb08","CI",{"_key":419,"_type":72,"marks":420,"text":421},"80aab1d781ed8",[],", and ",{"_key":423,"_type":72,"marks":424,"text":426},"80aab1d781ed9",[425],"f94bcdcefd6a","WebPageTest",{"_key":428,"_type":72,"marks":429,"text":129},"80aab1d781ed10",[],[431,433,435,437,439],{"_key":389,"_type":105,"href":432,"reference":12},"https:\u002F\u002Fgithub.com\u002FGoogleChrome\u002Flighthouse",{"_key":398,"_type":105,"href":434,"reference":12},"https:\u002F\u002Fdevelopers.google.com\u002Fweb\u002Ftools\u002Fchrome-devtools",{"_key":407,"_type":105,"href":436,"reference":12},"https:\u002F\u002Fdevelopers.google.com\u002Fspeed\u002Fpagespeed\u002Finsights\u002F?url=https%3A%2F%2Fstore.google.com",{"_key":416,"_type":105,"href":438,"reference":12},"https:\u002F\u002Fgithub.com\u002FGoogleChrome\u002Flighthouse-ci",{"_key":425,"_type":105,"href":440,"reference":12},"https:\u002F\u002Fwww.webpagetest.org\u002Feasy",{"_key":442,"_type":68,"children":443,"markDefs":457,"style":77},"e0333752eae5",[444,448,453],{"_key":445,"_type":72,"marks":446,"text":447},"e0333752eae50",[],"Keep in mind that Lighthouse is a lab tool. While great for looking at opportunities to improve your user-experience, always try to consult ",{"_key":449,"_type":72,"marks":450,"text":452},"e0333752eae51",[451],"58e7c9904fd5","real-world data",{"_key":454,"_type":72,"marks":455,"text":456},"e0333752eae52",[]," for a complete picture of what actual users are seeing.",[458],{"_key":451,"_type":105,"href":459,"reference":12},"https:\u002F\u002Fweb.dev\u002Fvitals-field-measurement-best-practices\u002F",{"_key":461,"_type":68,"children":462,"markDefs":466,"style":346},"8cfdc8b76ff4",[463],{"_key":464,"_type":72,"marks":465,"text":214},"8cfdc8b76ff40",[],[],{"_key":468,"_type":68,"children":469,"markDefs":482,"style":77},"d112e95d8c50",[470,474,478],{"_key":471,"_type":72,"marks":472,"text":473},"d112e95d8c500",[],"Layout shifts can be distracting to users. Imagine you've started reading an article when all of a sudden elements shift around the page, throwing you off and requiring you to find your place again. ",{"_key":475,"_type":72,"marks":476,"text":214},"d112e95d8c501",[477],"d5a7f0a79a3f",{"_key":479,"_type":72,"marks":480,"text":481},"d112e95d8c502",[]," (CLS) measures the instability of content. The most common causes of CLS include images without dimensions (see below), which can push down content when they load and snap into place. Ignoring them means the browser may not be able to reserve sufficient space in advance of them loading.",[483],{"_key":477,"_type":105,"href":484,"reference":12},"http:\u002F\u002Fweb.dev\u002Fcls",{"_key":486,"_type":56,"alt":12,"asset":487,"caption":489,"markDefs":12},"65bc426facc6",{"_ref":488,"_type":59},"image-662782b66680f29cbd45400df436ead87873de7e-1280x720-gif","Generated using Layout Shift GIF Generator. You may also be interested in the CLS Debugger.",{"_key":491,"_type":68,"children":492,"markDefs":496,"style":77},"055443c4be04",[493],{"_key":494,"_type":72,"marks":495,"text":377},"055443c4be040",[],[],{"_key":498,"_type":68,"children":499,"markDefs":504,"style":505},"9c543ce6b8b5",[500],{"_key":501,"_type":72,"marks":502,"text":503},"9c543ce6b8b50",[],"The basics",[],"h3",{"_key":507,"_type":68,"children":508,"markDefs":536,"style":77},"fce94b8a7ac7",[509,513,516,520,524,528,532],{"_key":510,"_type":72,"marks":511,"text":512},"fce94b8a7ac70",[],"To place an image on a web page, we use the ",{"_key":514,"_type":72,"marks":515,"text":89},"fce94b8a7ac71",[88],{"_key":517,"_type":72,"marks":518,"text":519},"fce94b8a7ac72",[]," element. This is an empty element—it has no closing tag—that requires a minimum of one attribute to be helpful: ",{"_key":521,"_type":72,"marks":522,"text":523},"fce94b8a7ac73",[88],"src",{"_key":525,"_type":72,"marks":526,"text":527},"fce94b8a7ac74",[],", the source file for the image. If an image is called “",{"_key":529,"_type":72,"marks":530,"text":531},"fce94b8a7ac75",[74],"keyboard.jpg”",{"_key":533,"_type":72,"marks":534,"text":535},"fce94b8a7ac76",[]," and it exists in the same path as your HTML document, it can be embedded as follows:",[],{"_key":538,"_type":68,"children":539,"markDefs":552,"style":77},"f458a408fdf1",[540,544,548],{"_key":541,"_type":72,"marks":542,"text":543},"f458a408fdf10",[88,278],"\u003Cimg",{"_key":545,"_type":72,"marks":546,"text":547},"f458a408fdf11",[88]," src=\"keyboard.jpg\"",{"_key":549,"_type":72,"marks":550,"text":551},"f458a408fdf12",[88,278],">",[],{"_key":554,"_type":68,"children":555,"markDefs":575,"style":77},"cade6ad177ac",[556,560,564,568,571],{"_key":557,"_type":72,"marks":558,"text":559},"cade6ad177ac0",[],"To ensure our image is accessible, we add the ",{"_key":561,"_type":72,"marks":562,"text":563},"cade6ad177ac1",[88],"alt",{"_key":565,"_type":72,"marks":566,"text":567},"cade6ad177ac2",[]," attribute. The value of this attribute should be a textual description of the image, and is used as an alternative to the image when it can’t be displayed or seen; for example, a user accessing your page via a screen reader. The above code with an ",{"_key":569,"_type":72,"marks":570,"text":563},"cade6ad177ac3",[88],{"_key":572,"_type":72,"marks":573,"text":574},"cade6ad177ac4",[]," specified looks as follows:",[],{"_key":577,"_type":68,"children":578,"markDefs":596,"style":77},"06cd8c4da537",[579,582,585,589,593],{"_key":580,"_type":72,"marks":581,"text":543},"06cd8c4da5370",[88,278],{"_key":583,"_type":72,"marks":584,"text":547},"06cd8c4da5371",[88],{"_key":586,"_type":72,"marks":587,"text":588},"06cd8c4da5372",[],"\n",{"_key":590,"_type":72,"marks":591,"text":592},"06cd8c4da5373",[88],"alt=\"A beautiful pink keyboard.\"",{"_key":594,"_type":72,"marks":595,"text":551},"06cd8c4da5374",[88,278],[],{"_key":598,"_type":68,"children":599,"markDefs":628,"style":77},"bf4a735f17ce",[600,604,608,612,616,620,624],{"_key":601,"_type":72,"marks":602,"text":603},"bf4a735f17ce0",[],"Next, we add ",{"_key":605,"_type":72,"marks":606,"text":607},"bf4a735f17ce1",[88],"width",{"_key":609,"_type":72,"marks":610,"text":611},"bf4a735f17ce2",[]," and ",{"_key":613,"_type":72,"marks":614,"text":615},"bf4a735f17ce3",[88],"height",{"_key":617,"_type":72,"marks":618,"text":619},"bf4a735f17ce4",[]," attributes to specify the width and height of the image, otherwise known as the image’s dimensions. The dimensions of an image can usually be found by looking at this information via your operating system’s file explorer (",{"_key":621,"_type":72,"marks":622,"text":623},"bf4a735f17ce5",[278],"Cmd + I",{"_key":625,"_type":72,"marks":626,"text":627},"bf4a735f17ce6",[]," on macOS).",[],{"_key":630,"_type":88,"code":631,"markDefs":12},"cbede6a409cb","\u003Cimg src=\"keyboard.jpg\"\n    alt=\"A beautiful pink keyboard.\"\n    width=\"400\"\n    height=\"400\">",{"_key":633,"_type":68,"children":634,"markDefs":639,"style":77},"e9ef8fb0d619",[635],{"_key":636,"_type":72,"marks":637,"text":638},"e9ef8fb0d6190",[],"When width and height are specified on an image, the browser knows how much space to reserve for the image until it is downloaded. Forgetting to include the image’s dimensions can cause layout shifts, as the browser is unsure how much space the image will need.",[],{"_key":641,"_type":68,"children":642,"markDefs":660,"style":77},"adb06cc34d93",[643,647,650,653,656],{"_key":644,"_type":72,"marks":645,"text":646},"adb06cc34d930",[],"Modern browsers now set the default aspect ratio of images based on an image’s ",{"_key":648,"_type":72,"marks":649,"text":607},"adb06cc34d931",[88],{"_key":651,"_type":72,"marks":652,"text":611},"adb06cc34d932",[],{"_key":654,"_type":72,"marks":655,"text":615},"adb06cc34d933",[88],{"_key":657,"_type":72,"marks":658,"text":659},"adb06cc34d934",[]," attributes, so it’s valuable to set these to prevent such layout shifts.",[],{"_key":662,"_type":68,"children":663,"markDefs":668,"style":505},"18c4a8791921",[664],{"_key":665,"_type":72,"marks":666,"text":667},"18c4a87919210",[],"Identify layout shifts from images without dimensions",[],{"_key":670,"_type":68,"children":671,"markDefs":707,"style":77},"ff3d31225347",[672,676,681,685,690,693,696,699,703],{"_key":673,"_type":72,"marks":674,"text":675},"ff3d312253470",[],"To ",{"_key":677,"_type":72,"marks":678,"text":680},"ff3d312253471",[679],"d51aec71262c","limit",{"_key":682,"_type":72,"marks":683,"text":684},"ff3d312253472",[]," Cumulative Layout Shifts from images without dimensions, ",{"_key":686,"_type":72,"marks":687,"text":689},"ff3d312253473",[688],"d802f4296dac","include ",{"_key":691,"_type":72,"marks":692,"text":607},"ff3d312253474",[688,88],{"_key":694,"_type":72,"marks":695,"text":611},"ff3d312253475",[688],{"_key":697,"_type":72,"marks":698,"text":615},"ff3d312253476",[688,88],{"_key":700,"_type":72,"marks":701,"text":702},"ff3d312253477",[688]," attributes",{"_key":704,"_type":72,"marks":705,"text":706},"ff3d312253478",[]," on your images and video elements. This approach ensures that the browser can allocate the correct amount of space in the document while the image is loading. Lighthouse will highlight images without a width and height:",[708,710],{"_key":679,"_type":105,"href":709,"reference":12},"https:\u002F\u002Fweb.dev\u002Foptimize-cls\u002F#images-without-dimensions",{"_key":688,"_type":105,"href":711,"reference":12},"https:\u002F\u002Fwww.smashingmagazine.com\u002F2020\u002F03\u002Fsetting-height-width-images-important-again\u002F",{"_key":713,"_type":56,"alt":12,"asset":714,"caption":716,"markDefs":12},"abbf4dd51658",{"_ref":715,"_type":59},"image-0b0c85017c708df1782bcf84f2387c6c266e094a-1600x1027-png","Most images on the blog do set a width and height. Lighthouse was only able to find one small example and CLS on the pages tested were generally pretty good!",{"_key":718,"_type":68,"children":719,"markDefs":723,"style":77},"da0c1b1c0fbb",[720],{"_key":721,"_type":72,"marks":722,"text":377},"da0c1b1c0fbb0",[],[],{"_key":725,"_type":68,"children":726,"markDefs":730,"style":346},"b0556f17b833",[727],{"_key":728,"_type":72,"marks":729,"text":152},"b0556f17b8330",[],[],{"_key":732,"_type":68,"children":733,"markDefs":746,"style":77},"8a407ad28a8c",[734,738,742],{"_key":735,"_type":72,"marks":736,"text":737},"8a407ad28a8c0",[],"In many modern web experiences, images tend to be the largest visible element when a page completes loading. These include hero images and images from carousels, stories, and banners. ",{"_key":739,"_type":72,"marks":740,"text":152},"8a407ad28a8c1",[741],"72490afc5e46",{"_key":743,"_type":72,"marks":744,"text":745},"8a407ad28a8c2",[]," (LCP) is a Core Web Vitals metric which measures when the largest contentful element (images, text) in a user’s viewport, becomes visible. This allows a browser to determine when the main content of the page has finished rendering.",[747],{"_key":741,"_type":105,"href":161,"reference":12},{"_key":749,"_type":68,"children":750,"markDefs":796,"style":77},"a1c43a94a47d",[751,755,760,763,768,771,776,780,785,789,792],{"_key":752,"_type":72,"marks":753,"text":754},"a1c43a94a47d0",[],"When an image is the largest contentful element, how slowly the image loads can impact LCP. In addition to applying image compression (e.g. using ",{"_key":756,"_type":72,"marks":757,"text":759},"a1c43a94a47d1",[758],"b75d580622da","Squoosh",{"_key":761,"_type":72,"marks":762,"text":412},"a1c43a94a47d2",[],{"_key":764,"_type":72,"marks":765,"text":767},"a1c43a94a47d3",[766],"6a81c50658b5","Sharp",{"_key":769,"_type":72,"marks":770,"text":412},"a1c43a94a47d4",[],{"_key":772,"_type":72,"marks":773,"text":775},"a1c43a94a47d5",[774],"739091d49560","ImageOptim",{"_key":777,"_type":72,"marks":778,"text":779},"a1c43a94a47d6",[]," or an ",{"_key":781,"_type":72,"marks":782,"text":784},"a1c43a94a47d7",[783],"c379a527c272","image CDN",{"_key":786,"_type":72,"marks":787,"text":788},"a1c43a94a47d8",[],") and using a modern image format, you can tweak the ",{"_key":790,"_type":72,"marks":791,"text":89},"a1c43a94a47d9",[88],{"_key":793,"_type":72,"marks":794,"text":795},"a1c43a94a47d10",[]," element to serve the most appropriate responsive version of an image or lazy-load it.",[797,799,801,803],{"_key":758,"_type":105,"href":798,"reference":12},"https:\u002F\u002Fsquoosh.app",{"_key":766,"_type":105,"href":800,"reference":12},"https:\u002F\u002Fsharp.pixelplumbing.com\u002F",{"_key":774,"_type":105,"href":802,"reference":12},"https:\u002F\u002Fimageoptim.com\u002Fmac",{"_key":783,"_type":105,"href":804,"reference":12},"https:\u002F\u002Fweb.dev\u002Fimage-cdns\u002F",{"_key":806,"_type":68,"children":807,"markDefs":812,"style":505},"34435cb2f7ea",[808],{"_key":809,"_type":72,"marks":810,"text":811},"34435cb2f7ea0",[],"Identify the Largest Contentful Paint element",[],{"_key":814,"_type":68,"children":815,"markDefs":820,"style":77},"e3a8bddc59c1",[816],{"_key":817,"_type":72,"marks":818,"text":819},"e3a8bddc59c10",[],"Lighthouse has a “Largest Contentful Paint element” audit that identifies what element was the largest contentful paint. Hovering over the element will highlight it in the main browser window.",[],{"_key":822,"_type":56,"alt":12,"asset":823,"caption":377,"markDefs":12},"81b4a318e50b",{"_ref":824,"_type":59},"image-627de61f95f81e529a554e3530a5326a2f2d7140-1600x1027-png",{"_key":826,"_type":68,"children":827,"markDefs":832,"style":77},"cc7ef255cf64",[828],{"_key":829,"_type":72,"marks":830,"text":831},"cc7ef255cf640",[],"If this element is an image, this information is a useful hint you may want to optimize the loading of this image.",[],{"_key":834,"_type":68,"children":835,"markDefs":848,"style":77},"c80b67aa395d",[836,840,844],{"_key":837,"_type":72,"marks":838,"text":839},"c80b67aa395d0",[],"Hovering over an image in the Chrome DevTools ",{"_key":841,"_type":72,"marks":842,"text":843},"c80b67aa395d1",[278],"Elements",{"_key":845,"_type":72,"marks":846,"text":847},"c80b67aa395d2",[]," panel will display the dimensions of the image as well as the image’s intrinsic size.",[],{"_key":850,"_type":56,"alt":12,"asset":851,"caption":377,"markDefs":12},"7248bb963902",{"_ref":852,"_type":59},"image-94a932c66fe3691bc6eead91eac97e98001c2846-1600x1027-png",{"_key":854,"_type":68,"children":855,"markDefs":860,"style":505},"b349a11244e3",[856],{"_key":857,"_type":72,"marks":858,"text":859},"b349a11244e30",[],"Responsive images",[],{"_key":862,"_type":68,"children":863,"markDefs":889,"style":77},"1fad6bb6763a",[864,868,871,875,878,881,885],{"_key":865,"_type":72,"marks":866,"text":867},"1fad6bb6763a0",[],"What about switching image resolution? A standard ",{"_key":869,"_type":72,"marks":870,"text":89},"1fad6bb6763a1",[88],{"_key":872,"_type":72,"marks":873,"text":874},"1fad6bb6763a2",[]," only allows us to supply a single source file to the browser. But with the ",{"_key":876,"_type":72,"marks":877,"text":181},"1fad6bb6763a3",[88],{"_key":879,"_type":72,"marks":880,"text":611},"1fad6bb6763a4",[],{"_key":882,"_type":72,"marks":883,"text":884},"1fad6bb6763a5",[88],"sizes",{"_key":886,"_type":72,"marks":887,"text":888},"1fad6bb6763a6",[]," attributes we can provide many additional source images (and hints) so the browser can pick the most appropriate one. This allows us to supply images that are smaller or larger.",[],{"_key":891,"_type":88,"code":892,"markDefs":12},"85ab5541f617","\u003Cimg src=\"keyboard-800w.jpg\"\n    alt=\"A beautiful pink keyboard.\"\n    width=\"400\"\n    height=\"400\"\n    srcset=\"keyboard-400w.jpg 400w,\n            keyboard-800w.jpg 800w\"\n    sizes=\"(max-width: 640px) 400px,\n            800px\">",{"_key":894,"_type":68,"children":895,"markDefs":945,"style":77},"564edb04deb3",[896,900,903,907,911,915,919,923,927,930,934,937,941],{"_key":897,"_type":72,"marks":898,"text":899},"564edb04deb30",[],"The ",{"_key":901,"_type":72,"marks":902,"text":181},"564edb04deb31",[88],{"_key":904,"_type":72,"marks":905,"text":906},"564edb04deb32",[]," attribute defines the set of images the browser can select from, as well as the size of each image. Each image string is separated by a comma and includes: a source filename (",{"_key":908,"_type":72,"marks":909,"text":910},"564edb04deb33",[88],"keyboard-400w.jpg",{"_key":912,"_type":72,"marks":913,"text":914},"564edb04deb34",[],"); a space; and the image’s intrinsic width specified in pixels (",{"_key":916,"_type":72,"marks":917,"text":918},"564edb04deb35",[88],"400w",{"_key":920,"_type":72,"marks":921,"text":922},"564edb04deb36",[],"), or a pixel density descriptor (",{"_key":924,"_type":72,"marks":925,"text":926},"564edb04deb37",[88],"1x",{"_key":928,"_type":72,"marks":929,"text":412},"564edb04deb38",[],{"_key":931,"_type":72,"marks":932,"text":933},"564edb04deb39",[88],"1.5x",{"_key":935,"_type":72,"marks":936,"text":412},"564edb04deb310",[],{"_key":938,"_type":72,"marks":939,"text":940},"564edb04deb311",[88],"2x",{"_key":942,"_type":72,"marks":943,"text":944},"564edb04deb312",[],", etc.).",[],{"_key":947,"_type":56,"alt":12,"asset":948,"caption":950,"markDefs":12},"236a4cf382b4",{"_ref":949,"_type":59},"image-7cef0543ca6fdd40ec396a043ad369f8b053d775-1600x659-png","From Speed at Scale with Katie Hempenius and I at Google I\u002FO",{"_key":952,"_type":68,"children":953,"markDefs":980,"style":77},"b8851edb749d",[954,957,960,964,968,972,976],{"_key":955,"_type":72,"marks":956,"text":899},"b8851edb749d0",[],{"_key":958,"_type":72,"marks":959,"text":884},"b8851edb749d1",[88],{"_key":961,"_type":72,"marks":962,"text":963},"b8851edb749d2",[]," attribute specifies a set of conditions, such as screen widths, and what image size is best to select when those conditions are met. Above, (",{"_key":965,"_type":72,"marks":966,"text":967},"b8851edb749d3",[88],"max-width:640px",{"_key":969,"_type":72,"marks":970,"text":971},"b8851edb749d4",[],") is a media condition asking “if the viewport width is 640 pixels or less,” and ",{"_key":973,"_type":72,"marks":974,"text":975},"b8851edb749d5",[88],"400px",{"_key":977,"_type":72,"marks":978,"text":979},"b8851edb749d6",[]," is the width the slot the image is going to fill when the media condition is true. This typically corresponds to the page’s responsive breakpoints.",[],{"_key":982,"_type":68,"children":983,"markDefs":988,"style":505},"7f5bfcb8aa9a",[984],{"_key":985,"_type":72,"marks":986,"text":987},"7f5bfcb8aa9a0",[],"Device Pixel Ratio (DPR) \u002F Pixel density capping",[],{"_key":990,"_type":68,"children":991,"markDefs":1005,"style":77},"4a9669bc40fc",[992,996,1001],{"_key":993,"_type":72,"marks":994,"text":995},"4a9669bc40fc0",[],"Device Pixel Ratio (DPR) represents how a CSS pixel is translated to physical pixels on a hardware screen. ",{"_key":997,"_type":72,"marks":998,"text":1000},"4a9669bc40fc1",[999],"5d1d67a4fe24","High resolution",{"_key":1002,"_type":72,"marks":1003,"text":1004},"4a9669bc40fc2",[]," and retina screens use more physical pixels to represent CSS pixels for imagery that is sharper and has more detailed visuals.",[1006],{"_key":999,"_type":105,"href":1007,"reference":12},"https:\u002F\u002Fweb.dev\u002Fchoose-the-right-image-format\u002F#implications-of-high-resolution-screens",{"_key":1009,"_type":68,"children":1010,"markDefs":1023,"style":77},"63229175203b",[1011,1015,1019],{"_key":1012,"_type":72,"marks":1013,"text":1014},"63229175203b0",[],"The human eye may not be capable of distinguishing the difference between images that are a 2x-3x DPR vs. an even higher-resolution. Serving overly high DPR images is a common problem for sites leveraging ",{"_key":1016,"_type":72,"marks":1017,"text":1018},"63229175203b1",[88],"\u003Cimg srcset>",{"_key":1020,"_type":72,"marks":1021,"text":1022},"63229175203b2",[]," and a suite of image sizes.",[],{"_key":1025,"_type":56,"alt":12,"asset":1026,"caption":377,"markDefs":12},"c2d362cfddb1",{"_ref":1027,"_type":59},"image-a5fa4997b8b284427503b370b082b72d16d68f30-1600x887-png",{"_key":1029,"_type":68,"children":1030,"markDefs":1044,"style":77},"cbe43f08d59e",[1031,1035,1040],{"_key":1032,"_type":72,"marks":1033,"text":1034},"cbe43f08d59e0",[],"It may be possible to use DPR-capping to serve your users an image at a 2x or 3x fidelity to prevent large image payloads. Twitter ",{"_key":1036,"_type":72,"marks":1037,"text":1039},"cbe43f08d59e1",[1038],"87ea6db3cc56","capped",{"_key":1041,"_type":72,"marks":1042,"text":1043},"cbe43f08d59e2",[]," their image fidelity at 2x, resulting in 33% faster timeline image loading times. They found that 2x was a sweet spot of both good performance wins with no degradation in quality metrics.",[1045],{"_key":1038,"_type":105,"href":1046,"reference":12},"https:\u002F\u002Fblog.twitter.com\u002Fengineering\u002Fen_us\u002Ftopics\u002Finfrastructure\u002F2019\u002Fcapping-image-fidelity-on-ultra-high-resolution-devices.html",{"_key":1048,"_type":68,"children":1049,"markDefs":1057,"style":77},"ed05d2400bb6",[1050,1053],{"_key":1051,"_type":72,"marks":1052,"text":279},"ed05d2400bb60",[278],{"_key":1054,"_type":72,"marks":1055,"text":1056},"ed05d2400bb61",[],"This approach to DPR-capping is currently not possible if using “w” descriptors.",[],{"_key":1059,"_type":56,"alt":12,"asset":1060,"caption":377,"markDefs":12},"d594c51deb00",{"_ref":1061,"_type":59},"image-96b82b705a9b5d1957e1184f07ecb163f38061c7-1600x553-png",{"_key":1063,"_type":68,"children":1064,"markDefs":1069,"style":505},"24703d820a77",[1065],{"_key":1066,"_type":72,"marks":1067,"text":1068},"24703d820a770",[],"Identify images that can be better sized",[],{"_key":1071,"_type":68,"children":1072,"markDefs":1077,"style":77},"62b285941645",[1073],{"_key":1074,"_type":72,"marks":1075,"text":1076},"62b2859416450",[],"Lighthouse includes a number of image optimization audits for helping you understand if your images could be better compressed, delivered in a more optimal modern image format or resized.",[],{"_key":1079,"_type":56,"alt":12,"asset":1080,"caption":1082,"markDefs":12},"da8c698fac47",{"_ref":1081,"_type":59},"image-b641fb26672d8bf2d34e706d5f8ee6887ddd7e54-1600x1027-png","Lighthouse detected that the Stack Overflow blog is using WordPress and was able to suggest some WP-specific guidance on how to size a small number of images that could have been smaller.",{"_key":1084,"_type":68,"children":1085,"markDefs":1089,"style":77},"b1f76d94303d",[1086],{"_key":1087,"_type":72,"marks":1088,"text":377},"b1f76d94303d0",[],[],{"_key":1091,"_type":68,"children":1092,"markDefs":1097,"style":77},"5fae41e11061",[1093],{"_key":1094,"_type":72,"marks":1095,"text":1096},"5fae41e110610",[],"Even those images that are responsive (that is, sized relative to the viewport) should have width and height set. In modern browsers, these attributes establish an aspect ratio that helps prevent layout shifts, even if the absolute sizes are overridden by CSS.",[],{"_key":1099,"_type":56,"alt":12,"asset":1100,"caption":377,"markDefs":12},"6b073b78fb21",{"_ref":1101,"_type":59},"image-70daa2969ad4b20ca25a78613bc7ca6e12bd6464-1600x1027-png",{"_key":1103,"_type":68,"children":1104,"markDefs":1126,"style":77},"1201aa74a1b5",[1105,1109,1114,1118,1122],{"_key":1106,"_type":72,"marks":1107,"text":1108},"1201aa74a1b50",[],"When not using an image CDN or framework, I like to use ",{"_key":1110,"_type":72,"marks":1111,"text":1113},"1201aa74a1b51",[1112],"521d23f06827","responsivebreakpoints.com",{"_key":1115,"_type":72,"marks":1116,"text":1117},"1201aa74a1b52",[]," to determine the optimal image breakpoints and generate ",{"_key":1119,"_type":72,"marks":1120,"text":1121},"1201aa74a1b53",[88],"\u003Cimg> srcset",{"_key":1123,"_type":72,"marks":1124,"text":1125},"1201aa74a1b54",[]," code for my responsive images.",[1127],{"_key":1112,"_type":105,"href":1128,"reference":12},"https:\u002F\u002Fresponsivebreakpoints.com\u002F",{"_key":1130,"_type":68,"children":1131,"markDefs":1136,"style":505},"c61182eed4a1",[1132],{"_key":1133,"_type":72,"marks":1134,"text":1135},"c61182eed4a10",[],"Serving modern image formats",[],{"_key":1138,"_type":68,"children":1139,"markDefs":1144,"style":77},"87db7ff65403",[1140],{"_key":1141,"_type":72,"marks":1142,"text":1143},"87db7ff654030",[],"Art direction allows us to serve different images depending on a user’s display. While responsive images load different sizes of the same image, art direction can load very different images based on the display.",[],{"_key":1146,"_type":68,"children":1147,"markDefs":1182,"style":77},"9b8b075d7999",[1148,1152,1156,1160,1163,1167,1171,1175,1178],{"_key":1149,"_type":72,"marks":1150,"text":1151},"9b8b075d79990",[],"The browser can choose which image format to display using the ",{"_key":1153,"_type":72,"marks":1154,"text":1155},"9b8b075d79991",[88],"\u003Cpicture>",{"_key":1157,"_type":72,"marks":1158,"text":1159},"9b8b075d79992",[]," element. The ",{"_key":1161,"_type":72,"marks":1162,"text":1155},"9b8b075d79993",[88],{"_key":1164,"_type":72,"marks":1165,"text":1166},"9b8b075d79994",[]," element supports multiple ",{"_key":1168,"_type":72,"marks":1169,"text":1170},"9b8b075d79995",[88],"\u003Csource>",{"_key":1172,"_type":72,"marks":1173,"text":1174},"9b8b075d79996",[]," elements and a single ",{"_key":1176,"_type":72,"marks":1177,"text":89},"9b8b075d79997",[88],{"_key":1179,"_type":72,"marks":1180,"text":1181},"9b8b075d79998",[]," element, which can reference sources for different formats including AVIF and WebP.",[],{"_key":1184,"_type":88,"code":1185,"markDefs":12},"f1e986b06b96","\u003Cpicture>\n    \u003Csource srcset=\"keyboard.avif\" type=\"image\u002Favif\">\n    \u003Csource srcset=\"keyboard.webp\" type=\"image\u002Fwebp\">\n    \u003Csource srcset=\"keyboard.jpg\" type=\"image\u002Fjpeg\">\n    \u003Cimg src=\"keyboard.jpg\" alt=\"Omg a keyboard\">\n\u003C\u002Fpicture>\n",{"_key":1187,"_type":68,"children":1188,"markDefs":1200,"style":77},"02a4d3a620b5",[1189,1193,1196],{"_key":1190,"_type":72,"marks":1191,"text":1192},"02a4d3a620b50",[],"In this example, the browser will begin to parse the sources and will stop when it has found the first supported match. If no match is found, the browser loads the source specified in ",{"_key":1194,"_type":72,"marks":1195,"text":89},"02a4d3a620b51",[88],{"_key":1197,"_type":72,"marks":1198,"text":1199},"02a4d3a620b52",[]," as the fallback.",[],{"_key":1202,"_type":68,"children":1203,"markDefs":1217,"style":77},"e258a0701acd",[1204,1208,1213],{"_key":1205,"_type":72,"marks":1206,"text":1207},"e258a0701acd0",[],"Understanding the myriad of image format options out there today can be a confusing process, but you may find Cloudinary’s ",{"_key":1209,"_type":72,"marks":1210,"text":1212},"e258a0701acd1",[1211],"5ba6aa2cf745","comparison of modern image formats",{"_key":1214,"_type":72,"marks":1215,"text":1216},"e258a0701acd2",[]," helpful:",[1218],{"_key":1211,"_type":105,"href":1219,"reference":12},"https:\u002F\u002Fcloudinary.com\u002Fblog\u002Ftime_for_next_gen_codecs_to_dethrone_jpeg",{"_key":1221,"_type":56,"alt":12,"asset":1222,"caption":377,"markDefs":12},"c7b728990598",{"_ref":1223,"_type":59},"image-b8706b15b710433a519d9d6f88b659600cc2dfd0-1600x509-png",{"_key":1225,"_type":68,"children":1226,"markDefs":1231,"style":505},"9225e119200f",[1227],{"_key":1228,"_type":72,"marks":1229,"text":1230},"9225e119200f0",[],"Identify images that could be served in a more modern format",[],{"_key":1233,"_type":68,"children":1234,"markDefs":1239,"style":77},"01c9ed30a792",[1235],{"_key":1236,"_type":72,"marks":1237,"text":1238},"01c9ed30a7920",[],"Lighthouse highlights potential savings from serving images in a next-generation format.",[],{"_key":1241,"_type":56,"alt":12,"asset":1242,"caption":377,"markDefs":12},"a90833534b8f",{"_ref":1243,"_type":59},"image-6aadbe8b6caaa93aba70693a15f6f63a93c67fd1-1600x1027-png",{"_key":1245,"_type":68,"children":1246,"markDefs":1259,"style":77},"b3293ac3963e",[1247,1251,1255],{"_key":1248,"_type":72,"marks":1249,"text":1250},"b3293ac3963e0",[],"I also enjoy using ",{"_key":1252,"_type":72,"marks":1253,"text":759},"b3293ac3963e1",[1254],"b05dbfd44828",{"_key":1256,"_type":72,"marks":1257,"text":1258},"b3293ac3963e2",[]," for its support of bleeding-edge formats, such as JPEG XL, as it offers a low-friction way to experiment with modern formats outside of a CLI or CDN.",[1260],{"_key":1254,"_type":105,"href":1261,"reference":12},"https:\u002F\u002Fsquoosh.app\u002F",{"_key":1263,"_type":56,"alt":12,"asset":1264,"caption":377,"markDefs":12},"31b0997b8079",{"_ref":1265,"_type":59},"image-0f924d063489a37efbeb19ab4061b87fb9c0e675-1600x1027-png",{"_key":1267,"_type":68,"children":1268,"markDefs":1321,"style":77},"d94a9fa69072",[1269,1273,1276,1280,1283,1286,1289,1293,1296,1300,1303,1307,1310,1314,1317],{"_key":1270,"_type":72,"marks":1271,"text":1272},"d94a9fa690720",[],"There are multiple ways to approach sizing issues as both ",{"_key":1274,"_type":72,"marks":1275,"text":181},"d94a9fa690721",[88],{"_key":1277,"_type":72,"marks":1278,"text":1279},"d94a9fa690722",[]," and sizes are both usable on ",{"_key":1281,"_type":72,"marks":1282,"text":1155},"d94a9fa690723",[88],{"_key":1284,"_type":72,"marks":1285,"text":611},"d94a9fa690724",[],{"_key":1287,"_type":72,"marks":1288,"text":89},"d94a9fa690725",[88],{"_key":1290,"_type":72,"marks":1291,"text":1292},"d94a9fa690726",[],". When in doubt, use ",{"_key":1294,"_type":72,"marks":1295,"text":89},"d94a9fa690727",[88],{"_key":1297,"_type":72,"marks":1298,"text":1299},"d94a9fa690728",[]," with ",{"_key":1301,"_type":72,"marks":1302,"text":181},"d94a9fa690729",[88],{"_key":1304,"_type":72,"marks":1305,"text":1306},"d94a9fa6907210",[],"\u002F",{"_key":1308,"_type":72,"marks":1309,"text":884},"d94a9fa6907211",[88],{"_key":1311,"_type":72,"marks":1312,"text":1313},"d94a9fa6907212",[]," for single images that have a simple layout. Use ",{"_key":1315,"_type":72,"marks":1316,"text":1155},"d94a9fa6907213",[88],{"_key":1318,"_type":72,"marks":1319,"text":1320},"d94a9fa6907214",[]," for serving multiple formats, complex layout, and art direction.",[],{"_key":1323,"_type":68,"children":1324,"markDefs":1353,"style":77},"182f34cee873",[1325,1329,1334,1337,1342,1345,1350],{"_key":1326,"_type":72,"marks":1327,"text":1328},"182f34cee8730",[],"caniuse has the latest browser support details for ",{"_key":1330,"_type":72,"marks":1331,"text":1333},"182f34cee8731",[1332],"d408db8bbc13","WebP",{"_key":1335,"_type":72,"marks":1336,"text":412},"182f34cee8732",[],{"_key":1338,"_type":72,"marks":1339,"text":1341},"182f34cee8733",[1340],"8767ce72978b","AVIF",{"_key":1343,"_type":72,"marks":1344,"text":611},"182f34cee8734",[],{"_key":1346,"_type":72,"marks":1347,"text":1349},"182f34cee8735",[1348],"bf9f257f973f","JPEG XL",{"_key":1351,"_type":72,"marks":1352,"text":129},"182f34cee8736",[],[1354,1356,1358],{"_key":1332,"_type":105,"href":1355,"reference":12},"https:\u002F\u002Fcaniuse.com\u002Fwebp",{"_key":1340,"_type":105,"href":1357,"reference":12},"https:\u002F\u002Fcaniuse.com\u002Favif",{"_key":1348,"_type":105,"href":1359,"reference":12},"https:\u002F\u002Fcaniuse.com\u002Fjpegxl",{"_key":1361,"_type":68,"children":1362,"markDefs":1367,"style":505},"11706b919b4b",[1363],{"_key":1364,"_type":72,"marks":1365,"text":1366},"11706b919b4b0",[],"Content negotiation",[],{"_key":1369,"_type":68,"children":1370,"markDefs":1420,"style":77},"a70983e10568",[1371,1375,1378,1382,1387,1391,1395,1400,1403,1408,1411,1416],{"_key":1372,"_type":72,"marks":1373,"text":1374},"a70983e105680",[],"An alternative to manually handling image format selection using ",{"_key":1376,"_type":72,"marks":1377,"text":1155},"a70983e105681",[88],{"_key":1379,"_type":72,"marks":1380,"text":1381},"a70983e105682",[]," is to rely on the ",{"_key":1383,"_type":72,"marks":1384,"text":1386},"a70983e105683",[1385,88],"d8d642b76359","Accept",{"_key":1388,"_type":72,"marks":1389,"text":1390},"a70983e105684",[1385]," header",{"_key":1392,"_type":72,"marks":1393,"text":1394},"a70983e105685",[],". This is sent by the client, allowing the server to deliver an image format that is a best-fit for the user. CDNs such as ",{"_key":1396,"_type":72,"marks":1397,"text":1399},"a70983e105686",[1398],"830800c8299d","Akamai",{"_key":1401,"_type":72,"marks":1402,"text":412},"a70983e105687",[],{"_key":1404,"_type":72,"marks":1405,"text":1407},"a70983e105688",[1406],"9a54de3358d6","Cloudinary",{"_key":1409,"_type":72,"marks":1410,"text":421},"a70983e105689",[],{"_key":1412,"_type":72,"marks":1413,"text":1415},"a70983e1056810",[1414],"c6984a644837","Cloudflare",{"_key":1417,"_type":72,"marks":1418,"text":1419},"a70983e1056811",[]," support it.",[1421,1423,1425,1427],{"_key":1385,"_type":105,"href":1422,"reference":12},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FHTTP\u002FHeaders\u002FAccept",{"_key":1398,"_type":105,"href":1424,"reference":12},"https:\u002F\u002Fwww.akamai.com\u002Fde\u002Fde\u002Fproducts\u002Fperformance\u002Fimage-and-video-manager.jsp",{"_key":1406,"_type":105,"href":1426,"reference":12},"https:\u002F\u002Fcloudinary.com\u002F",{"_key":1414,"_type":105,"href":1428,"reference":12},"https:\u002F\u002Fsupport.cloudflare.com\u002Fhc\u002Fen-us\u002Farticles\u002F360000607372-Using-Cloudflare-Polish-to-compress-images",{"_key":1430,"_type":68,"children":1431,"markDefs":1436,"style":505},"8515b6ee93a3",[1432],{"_key":1433,"_type":72,"marks":1434,"text":1435},"8515b6ee93a30",[],"Request your image early",[],{"_key":1438,"_type":68,"children":1439,"markDefs":1444,"style":77},"9dd3498d2a14",[1440],{"_key":1441,"_type":72,"marks":1442,"text":1443},"9dd3498d2a140",[],"If you are optimizing LCP, preload can help boost how soon late-discovered hero images (e.g such as those loaded by JavaScript or background hero images in CSS) are fetched. Where possible, attempt to solve this by better minimizing the request chains to your LCP image so that the browser doesn’t need to first fetch, parse, and execute JavaScript or wait for a component to render\u002Fhydrate to discover the image.",[],{"_key":1446,"_type":68,"children":1447,"markDefs":1466,"style":77},"554d0f74af40",[1448,1452,1456,1459,1462],{"_key":1449,"_type":72,"marks":1450,"text":1451},"554d0f74af400",[],"You can use ",{"_key":1453,"_type":72,"marks":1454,"text":1455},"554d0f74af401",[88],"\u003Clink rel=preload>",{"_key":1457,"_type":72,"marks":1458,"text":1299},"554d0f74af402",[],{"_key":1460,"_type":72,"marks":1461,"text":89},"554d0f74af403",[88],{"_key":1463,"_type":72,"marks":1464,"text":1465},"554d0f74af404",[]," to allow browsers to discover critical resources you want to load as soon as possible, prior to them being found in HTML.",[],{"_key":1468,"_type":68,"children":1469,"markDefs":1474,"style":77},"9ae9f47eb242",[1470],{"_key":1471,"_type":72,"marks":1472,"text":1473},"9ae9f47eb2420",[88],"\u003Clink rel=\"preload\" as=\"image\" href=\"keyboard.jpg\">",[],{"_key":1476,"_type":68,"children":1477,"markDefs":1493,"style":77},"83f5a073ba9c",[1478,1481,1485,1489],{"_key":1479,"_type":72,"marks":1480,"text":279},"83f5a073ba9c0",[278],{"_key":1482,"_type":72,"marks":1483,"text":1484},"83f5a073ba9c1",[],"Use preload sparingly and ",{"_key":1486,"_type":72,"marks":1487,"text":1488},"83f5a073ba9c2",[74],"always",{"_key":1490,"_type":72,"marks":1491,"text":1492},"83f5a073ba9c3",[]," measure its impact in production. If the preload for your image is earlier in the document than it is, this can help browsers discover it (and order relative to other resources).",[],{"_key":1495,"_type":68,"children":1496,"markDefs":1508,"style":77},"fb8f5f49c4b0",[1497,1501,1504],{"_key":1498,"_type":72,"marks":1499,"text":1500},"fb8f5f49c4b00",[],"Preload can be used to fetch sources for an ",{"_key":1502,"_type":72,"marks":1503,"text":89},"fb8f5f49c4b01",[88],{"_key":1505,"_type":72,"marks":1506,"text":1507},"fb8f5f49c4b02",[]," of a particular format:",[],{"_key":1510,"_type":68,"children":1511,"markDefs":1516,"style":77},"c715018b1adc",[1512],{"_key":1513,"_type":72,"marks":1514,"text":1515},"c715018b1adc0",[88],"\u003Clink rel=\"preload\" as=\"image\" href=\"keyboard.webp\" type=\"image\u002Fwebp\">",[],{"_key":1518,"_type":68,"children":1519,"markDefs":1529,"style":77},"2756696e7028",[1520,1525],{"_key":1521,"_type":72,"marks":1522,"text":1524},"2756696e70280",[1523],"cdfd03ea7246","Preload can also be used to fetch responsive images",{"_key":1526,"_type":72,"marks":1527,"text":1528},"2756696e70281",[]," so the correct source is discovered sooner:",[1530],{"_key":1523,"_type":105,"href":1531,"reference":12},"https:\u002F\u002Fweb.dev\u002Fpreload-responsive-images\u002F",{"_key":1533,"_type":88,"code":1534,"markDefs":12},"d2f43683051c","\u003Clink rel=\"preload\" as=\"image\" \n     href=\"keyboard.jpg\" \n     imagesrcset=\"\n        poster_400px.jpg 400w, \n        poster_800px.jpg 800w, \n        poster_1600px.jpg 1600w\" \n    imagesizes=\"50vw\">\n",{"_key":1536,"_type":68,"children":1537,"markDefs":1542,"style":505},"29a0d0e2f4e1",[1538],{"_key":1539,"_type":72,"marks":1540,"text":1541},"29a0d0e2f4e10",[],"Placeholders",[],{"_key":1544,"_type":68,"children":1545,"markDefs":1579,"style":77},"c36d77c8f6cf",[1546,1550,1554,1558,1561,1565,1568,1571,1575],{"_key":1547,"_type":72,"marks":1548,"text":1549},"c36d77c8f6cf0",[],"What if you would like to show the user a placeholder while the image loads? The ",{"_key":1551,"_type":72,"marks":1552,"text":1553},"c36d77c8f6cf1",[88],"background-image",{"_key":1555,"_type":72,"marks":1556,"text":1557},"c36d77c8f6cf2",[]," CSS property allows us to set background images on an element, including the ",{"_key":1559,"_type":72,"marks":1560,"text":89},"c36d77c8f6cf3",[88],{"_key":1562,"_type":72,"marks":1563,"text":1564},"c36d77c8f6cf4",[]," tag or any parent container elements. We can combine ",{"_key":1566,"_type":72,"marks":1567,"text":1553},"c36d77c8f6cf5",[88],{"_key":1569,"_type":72,"marks":1570,"text":1299},"c36d77c8f6cf6",[],{"_key":1572,"_type":72,"marks":1573,"text":1574},"c36d77c8f6cf7",[88],"background-size: cover",{"_key":1576,"_type":72,"marks":1577,"text":1578},"c36d77c8f6cf8",[]," to set the size of an element’s background image and scale the image as large as possible without stretching the image.",[],{"_key":1581,"_type":68,"children":1582,"markDefs":1587,"style":77},"b0be0868d87a",[1583],{"_key":1584,"_type":72,"marks":1585,"text":1586},"b0be0868d87a0",[],"Placeholders are often inline, Base64-encoded data URLs which are low-quality image placeholders (LQIP) or SVG image placeholders (SQIP). This allows users to get a very quick preview of the image, even on slow network connections, before the sharper final image loads in to replace it.",[],{"_key":1589,"_type":88,"code":1590,"markDefs":12},"6f7ea89363a4","\u003Cimg src=\"donut-800w.jpg\"\n    alt=\"A delicious donut\"\n    width=\"400\"\n    height=\"400\"\n    srcset=\"donut-400w.jpg 400w,\n            donut-800w.jpg 800w\"\n    sizes=\"(max-width: 640px) 400px,\n            800px\"\n    loading=\"lazy\"\n    decoding=\"async\"\n    style=\"background-size: cover;\n            background-image:\n              url(data:image\u002Fsvg+xml;base64,[svg text]);\">",{"_key":1592,"_type":68,"children":1593,"markDefs":1606,"style":77},"ef8d3b1825ef",[1594,1598,1602],{"_key":1595,"_type":72,"marks":1596,"text":1597},"ef8d3b1825ef0",[],"Note: Given that Base64 data URLs can be quite long, [",{"_key":1599,"_type":72,"marks":1600,"text":1601},"ef8d3b1825ef1",[88],"svg text",{"_key":1603,"_type":72,"marks":1604,"text":1605},"ef8d3b1825ef2",[],"] is denoted in the example above to improve readability. The decoding attribute above is also used to signal a preference between synchronous and asynchronous image decoding.",[],{"_key":1608,"_type":68,"children":1609,"markDefs":1614,"style":77},"f049259d5ff5",[1610],{"_key":1611,"_type":72,"marks":1612,"text":1613},"f049259d5ff50",[],"With an inline SVG placeholder, here is how the example from earlier now looks when loaded on a very slow connection. Notice how users are shown a preview right away prior to any full-size images being downloaded:",[],{"_key":1616,"_type":56,"alt":12,"asset":1617,"caption":1619,"markDefs":12},"5c4cc1dea5a7",{"_ref":1618,"_type":59},"image-05ec3e21b4052fcdf21219de5bc283bb89e0dc51-1600x981-png","Images loaded on a simulated slow connection, displaying a placeholder approximating the final image as it loads in. This can improve perceived performance in certain cases.",{"_key":1621,"_type":68,"children":1622,"markDefs":1636,"style":77},"6ead8ed13de5",[1623,1627,1632],{"_key":1624,"_type":72,"marks":1625,"text":1626},"6ead8ed13de50",[],"There are a variety of modern solutions for image placeholders (e.g CSS background-color, LQIP, SQIP, ",{"_key":1628,"_type":72,"marks":1629,"text":1631},"6ead8ed13de51",[1630],"fd52f8fb3161","Blur Hash",{"_key":1633,"_type":72,"marks":1634,"text":1635},"6ead8ed13de52",[],", Potrace).",[1637],{"_key":1630,"_type":105,"href":1638,"reference":12},"https:\u002F\u002Fblurha.sh\u002F",{"_key":1640,"_type":56,"alt":12,"asset":1641,"caption":1643,"markDefs":12},"8f05924e5000",{"_ref":1642,"_type":59},"image-ab20dd88d88aca6fb431433a834f568615b8f6a1-512x442-png","Perceptual image loading methods from Gunther Brunner of CyberAgent",{"_key":1645,"_type":68,"children":1646,"markDefs":1650,"style":77},"06251023fab3",[1647],{"_key":1648,"_type":72,"marks":1649,"text":377},"06251023fab30",[],[],{"_key":1652,"_type":68,"children":1653,"markDefs":1657,"style":346},"b4e7a9e84744",[1654],{"_key":1655,"_type":72,"marks":1656,"text":257},"b4e7a9e847440",[],[],{"_key":1659,"_type":68,"children":1660,"markDefs":1673,"style":77},"ec3947e944c6",[1661,1665,1669],{"_key":1662,"_type":72,"marks":1663,"text":1664},"ec3947e944c60",[],"It’s possible for images to block a user’s bandwidth and CPU on page load. They can get in the way of how critical resources are loaded, in particular on slow connections and lower-end mobile devices leading to bandwidth saturation. ",{"_key":1666,"_type":72,"marks":1667,"text":257},"ec3947e944c61",[1668],"cf43d08c8ad8",{"_key":1670,"_type":72,"marks":1671,"text":1672},"ec3947e944c62",[]," (FID) is a Core Web Vitals metric that captures a user's first impression of a site's interactivity and responsiveness. By reducing main-thread CPU usage, FID can also be reduced.",[1674],{"_key":1668,"_type":105,"href":1675,"reference":12},"http:\u002F\u002Fweb.dev\u002Ffid",{"_key":1677,"_type":68,"children":1678,"markDefs":1683,"style":505},"15910f8909a9",[1679],{"_key":1680,"_type":72,"marks":1681,"text":1682},"15910f8909a90",[],"Image lazy loading",[],{"_key":1685,"_type":68,"children":1686,"markDefs":1691,"style":77},"b8dfe3021159",[1687],{"_key":1688,"_type":72,"marks":1689,"text":1690},"b8dfe30211590",[],"What about offscreen images that are not visible until a user scrolls down the page? There may not be value in eagerly loading lots of images a user may never see, especially if it slows loading more critical content they see earlier on in the page. In the example below, all the images on the page are “eagerly loaded” (the default in browsers today), causing the user to download 1.1 MB of images. This can cause users’ data plans to take a hit in addition to affecting performance.",[],{"_key":1693,"_type":56,"alt":12,"asset":1694,"caption":1696,"markDefs":12},"d92206b7d98f",{"_ref":1695,"_type":59},"image-828cba5fce1f2f3fa2582331a8b7d95e48e8d750-1600x981-png","An image gallery eagerly loading all the images it needs up front, as shown in the Chrome DevTools Network panel. 1.1 MB of images have been downloaded, despite only a small number being visible when the user first lands on the page.",{"_key":1698,"_type":68,"children":1699,"markDefs":1755,"style":77},"f7c9131cb950",[1700,1704,1709,1713,1717,1720,1724,1728,1732,1736,1740,1744,1748,1751],{"_key":1701,"_type":72,"marks":1702,"text":1703},"f7c9131cb9500",[],"Using the ",{"_key":1705,"_type":72,"marks":1706,"text":1708},"f7c9131cb9501",[1707,88],"b3f657af53b9","loading",{"_key":1710,"_type":72,"marks":1711,"text":1712},"f7c9131cb9502",[1707]," attribute",{"_key":1714,"_type":72,"marks":1715,"text":1716},"f7c9131cb9503",[]," on ",{"_key":1718,"_type":72,"marks":1719,"text":89},"f7c9131cb9504",[88],{"_key":1721,"_type":72,"marks":1722,"text":1723},"f7c9131cb9505",[],", we can control the behavior of image loading. ",{"_key":1725,"_type":72,"marks":1726,"text":1727},"f7c9131cb9506",[88],"loading=\"lazy\"",{"_key":1729,"_type":72,"marks":1730,"text":1731},"f7c9131cb9507",[]," lazy-loads images, deferring their loading until they reach a calculated distance from the viewport. Setting ",{"_key":1733,"_type":72,"marks":1734,"text":1735},"f7c9131cb9508",[88],"loading=\"eager\"",{"_key":1737,"_type":72,"marks":1738,"text":1739},"f7c9131cb9509",[]," loads images right away, regardless of their visibility in the viewport. The default is ",{"_key":1741,"_type":72,"marks":1742,"text":1743},"f7c9131cb95010",[88],"eager",{"_key":1745,"_type":72,"marks":1746,"text":1747},"f7c9131cb95011",[],", so it doesn’t need to be explicitly added (that is, just use ",{"_key":1749,"_type":72,"marks":1750,"text":89},"f7c9131cb95012",[88],{"_key":1752,"_type":72,"marks":1753,"text":1754},"f7c9131cb95013",[]," for eager loading).",[1756],{"_key":1707,"_type":105,"href":1757,"reference":12},"https:\u002F\u002Fweb.dev\u002Fnative-lazy-loading\u002F",{"_key":1759,"_type":68,"children":1760,"markDefs":1772,"style":77},"afeccba6f4b6",[1761,1765,1768],{"_key":1762,"_type":72,"marks":1763,"text":1764},"afeccba6f4b60",[],"Below is an example of lazy-loading an ",{"_key":1766,"_type":72,"marks":1767,"text":89},"afeccba6f4b61",[88],{"_key":1769,"_type":72,"marks":1770,"text":1771},"afeccba6f4b62",[]," with a single source:",[],{"_key":1774,"_type":88,"code":1775,"markDefs":12},"2b2cb9a1f39f","\u003Cimg src=\"donut.jpg\"\n    alt=\"A delicious pink donut.\"\n    loading=\"lazy\"\n    width=\"400\"\n    height=\"400\">",{"_key":1777,"_type":68,"children":1778,"markDefs":1806,"style":77},"21a972a3ba26",[1779,1783,1786,1790,1793,1797,1802],{"_key":1780,"_type":72,"marks":1781,"text":1782},"21a972a3ba260",[],"With native ",{"_key":1784,"_type":72,"marks":1785,"text":89},"21a972a3ba261",[88],{"_key":1787,"_type":72,"marks":1788,"text":1789},"21a972a3ba262",[]," lazy-loading, the earlier example now downloads only about 90 KB of images! Just adding ",{"_key":1791,"_type":72,"marks":1792,"text":1727},"21a972a3ba263",[88],{"_key":1794,"_type":72,"marks":1795,"text":1796},"21a972a3ba264",[]," to our offscreen images has a huge impact. You ideally want to lazy-load all images present ",{"_key":1798,"_type":72,"marks":1799,"text":1801},"21a972a3ba265",[1800],"37355b3e467f","outside of the initial viewport",{"_key":1803,"_type":72,"marks":1804,"text":1805},"21a972a3ba266",[]," and avoid it for everything within the initial viewport.",[1807],{"_key":1800,"_type":105,"href":1808,"reference":12},"https:\u002F\u002Fweb.dev\u002Fbrowser-level-image-lazy-loading\u002F#avoid-lazy-loading-images-that-are-in-the-first-visible-viewport",{"_key":1810,"_type":56,"alt":12,"asset":1811,"caption":1813,"markDefs":12},"767f6ea46979",{"_ref":1812,"_type":59},"image-7b58ebacb5c6395437f8139ccdedf53d86004585-1600x981-png","An image gallery using native image lazy-loading on images outside of the viewport. As seen in the Chrome DevTools Network panel, the page now only downloads the bare minimum of images users need up front. The rest of the images are loaded in as users scroll down the page.",{"_key":1815,"_type":68,"children":1816,"markDefs":1827,"style":77},"ed1b1da00330",[1817,1821,1824],{"_key":1818,"_type":72,"marks":1819,"text":1820},"ed1b1da003300",[],"Lazy loading also works with images that include ",{"_key":1822,"_type":72,"marks":1823,"text":181},"ed1b1da003301",[88],{"_key":1825,"_type":72,"marks":1826,"text":218},"ed1b1da003302",[],[],{"_key":1829,"_type":88,"code":1830,"markDefs":12},"461c85a4fee7","\u003Cimg src=\"donut-800w.jpg\"\n    alt=\"A delicious pink donut\"\n    width=\"400\"\n    height=\"400\"\n    srcset=\"donut-400w.jpg 400w,\n            donut-800w.jpg 800w\"\n    sizes=\"(max-width: 640px) 400px,\n            800px\"\n    loading=\"lazy\">",{"_key":1832,"_type":68,"children":1833,"markDefs":1845,"style":77},"d6104e906d27",[1834,1837,1841],{"_key":1835,"_type":72,"marks":1836,"text":899},"d6104e906d270",[],{"_key":1838,"_type":72,"marks":1839,"text":1840},"d6104e906d271",[278],"Opportunities ",{"_key":1842,"_type":72,"marks":1843,"text":1844},"d6104e906d272",[],"section of Lighthouse lists any offscreen or hidden images on a page that can be lazy-loaded as well as the potential savings from doing so.",[],{"_key":1847,"_type":56,"alt":12,"asset":1848,"caption":1850,"markDefs":12},"2842ebbed895",{"_ref":1849,"_type":59},"image-a7a8cfea177fb078b64a4c0161261f1d7b435693-1600x833-png","See caniuse.com for latest browser support for native image lazy-loading.",{"_key":1852,"_type":68,"children":1853,"markDefs":1857,"style":77},"0a24ad3d6d90",[1854],{"_key":1855,"_type":72,"marks":1856,"text":377},"0a24ad3d6d900",[],[],{"_key":1859,"_type":68,"children":1860,"markDefs":1865,"style":346},"379c86dee97c",[1861],{"_key":1862,"_type":72,"marks":1863,"text":1864},"379c86dee97c0",[],"Conclusions",[],{"_key":1867,"_type":68,"children":1868,"markDefs":1880,"style":77},"3acfad7430c4",[1869,1873,1876],{"_key":1870,"_type":72,"marks":1871,"text":1872},"3acfad7430c40",[],"Images are key to delivering a great experience on the web. Hopefully you’ve learned something useful about how far the ",{"_key":1874,"_type":72,"marks":1875,"text":89},"3acfad7430c41",[88],{"_key":1877,"_type":72,"marks":1878,"text":1879},"3acfad7430c42",[]," element has evolved. When in doubt, test it out and see what tools like Lighthouse suggest might be opportunities to deliver an even more amazing image loading experience than you are today.",[],{"_key":1882,"_type":68,"children":1883,"markDefs":1897,"style":77},"66f4e62c5376",[1884,1888,1893],{"_key":1885,"_type":72,"marks":1886,"text":1887},"66f4e62c53760",[],"If you’re interested in learning more, I recently published a new book called ",{"_key":1889,"_type":72,"marks":1890,"text":1892},"66f4e62c53761",[1891],"61fcd482df22","Image Optimization",{"_key":1894,"_type":72,"marks":1895,"text":1896},"66f4e62c53762",[]," that covers advanced image optimization techniques that can help make your images on the web shine.",[1898],{"_key":1891,"_type":105,"href":1899,"reference":12},"http:\u002F\u002Fbit.ly\u002Fsmashing-images",true,"2022\u002F12\u002F27","You may not think about images as part of your web dev work, but they can affect your web app's performance more than any other part of your code. ",{"_type":56,"asset":1904},{"_ref":1905,"_type":59},"image-657012422149f5176ac4701b38b218782c358c3d-2400x1260-jpg",{"code":1907,"language":1908},"\u003C!-- wp:paragraph -->\n\u003Cp>\u003Cem>[Ed. note: While we take some time to rest up over the holidays and prepare for next year, we are re-publishing our top ten posts for the year. Please enjoy our favorite work this year and we’ll see you in 2023.]\u003C\u002Fem>\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Images are one of the most pervasive parts of the web. This isn’t a huge surprise as we humans are quite visual and the \u003Ccode>&lt;img&gt;\u003C\u002Fcode> tag has been around for almost 30 years. Images are so prominent that they are part of the most important content in over \u003Ca href=\"https:\u002F\u002Falmanac.httparchive.org\u002Fen\u002F2021\u002Fmedia#images\">~70%\u003C\u002Fa> of pages on both mobile and desktop according to the largest contentful paint metric. We like images over on the Stack Overflow blog too.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>The humble \u003Ccode>&lt;img&gt;\u003C\u002Fcode> element has gained some superpowers since it was created. Given how central it is to image optimization on the web, let’s catch up on what it can do and how it can help improve user-experience and the \u003Ca href=\"https:\u002F\u002Fweb.dev\u002Fmeasure\u002F\">Core Web Vitals\u003C\u002Fa>.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>First, some tips to get us started optimizing our metrics:\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:list -->\n\u003Cul>\u003C!-- wp:list-item -->\n\u003Cli>For a fast \u003Ca href=\"https:\u002F\u002Fweb.dev\u002Flcp\u002F\">Largest Contentful Paint\u003C\u002Fa>:\u003C!-- wp:list -->\n\u003Cul>\u003C!-- wp:list-item -->\n\u003Cli>Request your key hero image early\u003C\u002Fli>\n\u003C!-- \u002Fwp:list-item -->\n\n\u003C!-- wp:list-item -->\n\u003Cli>Use \u003Ccode>srcset\u003C\u002Fcode> + efficient modern image formats\u003C\u002Fli>\n\u003C!-- \u002Fwp:list-item -->\n\n\u003C!-- wp:list-item -->\n\u003Cli>Avoid wasting pixels (compress, don’t serve overly high DPR images)\u003C\u002Fli>\n\u003C!-- \u002Fwp:list-item -->\n\n\u003C!-- wp:list-item -->\n\u003Cli>Lazy-load offscreen images (reduce network contention for key resources)\u003C\u002Fli>\n\u003C!-- \u002Fwp:list-item -->\u003C\u002Ful>\n\u003C!-- \u002Fwp:list -->\u003C\u002Fli>\n\u003C!-- \u002Fwp:list-item -->\n\n\u003C!-- wp:list-item -->\n\u003Cli>For a low \u003Ca href=\"https:\u002F\u002Fweb.dev\u002Fcls\u002F\">Cumulative Layout Shift\u003C\u002Fa>:\u003C!-- wp:list -->\n\u003Cul>\u003C!-- wp:list-item -->\n\u003Cli>Set dimensions (width, height) on your images&nbsp;\u003C\u002Fli>\n\u003C!-- \u002Fwp:list-item -->\n\n\u003C!-- wp:list-item -->\n\u003Cli>Use CSS \u003Ccode>aspect-ratio\u003C\u002Fcode> or aspect ratio boxes to reserve space otherwise\u003C\u002Fli>\n\u003C!-- \u002Fwp:list-item -->\u003C\u002Ful>\n\u003C!-- \u002Fwp:list -->\u003C\u002Fli>\n\u003C!-- \u002Fwp:list-item -->\n\n\u003C!-- wp:list-item -->\n\u003Cli>For low impact to \u003Ca href=\"https:\u002F\u002Fweb.dev\u002Ffid\u002F\">First Input Delay\u003C\u002Fa>:\u003C!-- wp:list -->\n\u003Cul>\u003C!-- wp:list-item -->\n\u003Cli>Avoid images causing network contention with other critical resources like CSS and JS. While not render-blocking, they can indirectly impact render performance.\u003C\u002Fli>\n\u003C!-- \u002Fwp:list-item -->\u003C\u002Ful>\n\u003C!-- \u002Fwp:list -->\u003C\u002Fli>\n\u003C!-- \u002Fwp:list-item -->\u003C\u002Ful>\n\u003C!-- \u002Fwp:list -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Cstrong>Note: \u003C\u002Fstrong>Modern image components that build on \u003Ccode>&lt;img&gt;\u003C\u002Fcode>, like \u003Ca href=\"https:\u002F\u002Fnextjs.org\u002Fdocs\u002Fapi-reference\u002Fnext\u002Fimage\">Next.js \u003Ccode>&lt;Image&gt;\u003C\u002Fcode>\u003C\u002Fa> (for React) and \u003Ca href=\"https:\u002F\u002Fimage.nuxtjs.org\u002F\">Nuxt \u003Ccode>image\u003C\u002Fcode>\u003C\u002Fa> (for Vue) try to bake in as many of these concepts as possible by default. We’ll cover this later. You can of course also do this manually just using the \u003Ccode>&lt;img&gt;\u003C\u002Fcode> element directly. If using 11ty for your static sites, try the \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fgoogle\u002Feleventy-high-performance-blog\">11ty high-performance blog template\u003C\u002Fa>.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading -->\n\u003Ch2 id=\"h-image-impact-on-user-experience-and-the-core-web-vitals\">Image impact on user-experience and the Core Web Vitals\u003C\u002Fh2>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>You may have heard of Core Web Vitals (CWV). It’s an initiative by Google to share unified guidance for quality signals that can be key to delivering a great user-experience on the web. CWV is part of a set of \u003Ca href=\"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fblog\u002F2020\u002F11\u002Ftiming-for-page-experience\">page experience signals\u003C\u002Fa> Google Search will be evaluating for ranking. Images can impact the CWV in a number of ways.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:image -->\n\u003Cfigure class=\"wp-block-image\">\u003Cimg src=\"https:\u002F\u002Flh5.googleusercontent.com\u002FdbAew3uUiJWjXJG4Ny60Hh_SPsSBFdPRtf6q0TuwGjtjouXfjvBUHQ8xDpWPtUiY2j1YZXgsXTeIHBQZ05Z8kPJgikYa2t_hCyssiWih7sJsmGSE9QLsbWsWT4CPzzHe7Qx3Rkvl\" alt=\"\"\u002F>\u003Cfigcaption class=\"wp-element-caption\">\u003Cem>Above, the Stack Overflow “The Key” hero image was the Largest Contentful Paint element\u003C\u002Fem>\u003C\u002Ffigcaption>\u003C\u002Ffigure>\n\u003C!-- \u002Fwp:image -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>In this guide, we will be using Lighthouse to identify opportunities to improve the Core Web Vitals, walking through optimizations for each metric. \u003Ca href=\"https:\u002F\u002Fgithub.com\u002FGoogleChrome\u002Flighthouse\">Lighthouse\u003C\u002Fa> is an open-source, automated tool for improving the quality of web pages. You can find it in the \u003Ca href=\"https:\u002F\u002Fdevelopers.google.com\u002Fweb\u002Ftools\u002Fchrome-devtools\">Chrome DevTools\u003C\u002Fa> suite of debugging tools and run it against any web page, whether public or requiring authentication. You can also find Lighthouse in \u003Ca href=\"https:\u002F\u002Fdevelopers.google.com\u002Fspeed\u002Fpagespeed\u002Finsights\u002F?url=https%3A%2F%2Fstore.google.com\">PageSpeed Insights\u003C\u002Fa>, \u003Ca href=\"https:\u002F\u002Fgithub.com\u002FGoogleChrome\u002Flighthouse-ci\">CI\u003C\u002Fa>, and \u003Ca href=\"https:\u002F\u002Fwww.webpagetest.org\u002Feasy\">WebPageTest\u003C\u002Fa>.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Keep in mind that Lighthouse is a lab tool. While great for looking at opportunities to improve your user-experience, always try to consult \u003Ca href=\"https:\u002F\u002Fweb.dev\u002Fvitals-field-measurement-best-practices\u002F\">real-world data\u003C\u002Fa> for a complete picture of what actual users are seeing.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading -->\n\u003Ch2 id=\"h-cumulative-layout-shift\">Cumulative Layout Shift\u003C\u002Fh2>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Layout shifts can be distracting to users. Imagine you've started reading an article when all of a sudden elements shift around the page, throwing you off and requiring you to find your place again. \u003Ca href=\"http:\u002F\u002Fweb.dev\u002Fcls\">Cumulative Layout Shift\u003C\u002Fa> (CLS) measures the instability of content. The most common causes of CLS include images without dimensions (see below), which can push down content when they load and snap into place. Ignoring them means the browser may not be able to reserve sufficient space in advance of them loading.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:image -->\n\u003Cfigure class=\"wp-block-image\">\u003Cimg src=\"https:\u002F\u002Flh6.googleusercontent.com\u002F3w3PSGt9ZiRrXtukFkEXdS6qEA5nwZuId2YzevYn0yICXUU7kiqbM_HErPXxWXyLH03OB75Xzc_aLrfKoZiI9L1q2bJMTGoEl_-QdVFvkbxC9n4r9Cm_tHwuJFEOFiXinkf7a_xL\" alt=\"\"\u002F>\u003Cfigcaption class=\"wp-element-caption\">\u003Cem>Generated using \u003C\u002Fem>\u003Ca href=\"https:\u002F\u002Fdefaced.dev\u002Ftools\u002Flayout-shift-gif-generator\u002F\">\u003Cem>Layout Shift GIF Generator\u003C\u002Fem>\u003C\u002Fa>\u003Cem>. You may also be interested in the \u003C\u002Fem>\u003Ca href=\"https:\u002F\u002Fwebvitals.dev\u002Fcls\u002FG1hinueOMKWaKLJFJcQW\">\u003Cem>CLS Debugger\u003C\u002Fem>\u003C\u002Fa>\u003Cem>.\u003C\u002Fem>\u003C\u002Ffigcaption>\u003C\u002Ffigure>\n\u003C!-- \u002Fwp:image -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3 id=\"h-the-basics\">The basics\u003C\u002Fh3>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>To place an image on a web page, we use the \u003Ccode>&lt;img&gt;\u003C\u002Fcode> element. This is an empty element—it has no closing tag—that requires a minimum of one attribute to be helpful: \u003Ccode>src\u003C\u002Fcode>, the source file for the image. If an image is called “\u003Cem>keyboard.jpg”\u003C\u002Fem> and it exists in the same path as your HTML document, it can be embedded as follows:\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ccode>\u003Cstrong>&lt;img\u003C\u002Fstrong> src=\"keyboard.jpg\"\u003Cstrong>&gt;\u003C\u002Fstrong>\u003C\u002Fcode>\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>To ensure our image is accessible, we add the \u003Ccode>alt\u003C\u002Fcode> attribute. The value of this attribute should be a textual description of the image, and is used as an alternative to the image when&nbsp; it can’t be displayed or seen; for example, a user accessing your page via a screen reader. The above code with an \u003Ccode>alt\u003C\u002Fcode> specified looks as follows:\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ccode>\u003Cstrong>&lt;img\u003C\u002Fstrong> src=\"keyboard.jpg\"\u003Cbr>&nbsp; &nbsp; alt=\"A beautiful pink keyboard.\"\u003Cstrong>&gt;\u003C\u002Fstrong>\u003C\u002Fcode>\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Next, we add \u003Ccode>width\u003C\u002Fcode> and \u003Ccode>height\u003C\u002Fcode> attributes to specify the width and height of the image, otherwise known as the image’s dimensions. The dimensions of an image can usually be found by looking at this information via your operating system’s file explorer (\u003Cstrong>Cmd + I\u003C\u002Fstrong> on macOS).\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:code -->\n\u003Cpre class=\"wp-block-code\">\u003Ccode>\u003Cstrong>&lt;img\u003C\u002Fstrong> src=\"keyboard.jpg\"\u003Cbr>&nbsp; &nbsp; alt=\"A beautiful pink keyboard.\"\u003Cbr>&nbsp; &nbsp; width=\"400\"\u003Cbr>&nbsp; &nbsp; height=\"400\"\u003Cstrong>&gt;\u003C\u002Fstrong>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C!-- \u002Fwp:code -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>When width and height are specified on an image, the browser knows how much space to reserve for the image until it is downloaded. Forgetting to include the image’s dimensions can cause layout shifts, as the browser is unsure how much space the image will need.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Modern browsers now set the default aspect ratio of images based on an image’s \u003Ccode>width\u003C\u002Fcode> and \u003Ccode>height\u003C\u002Fcode> attributes, so it’s valuable to set these to prevent such layout shifts.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3 id=\"h-identify-layout-shifts-from-images-without-dimensions\">Identify layout shifts from images without dimensions\u003C\u002Fh3>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>To \u003Ca href=\"https:\u002F\u002Fweb.dev\u002Foptimize-cls\u002F#images-without-dimensions\">limit\u003C\u002Fa> Cumulative Layout Shifts from images without dimensions, \u003Ca href=\"https:\u002F\u002Fwww.smashingmagazine.com\u002F2020\u002F03\u002Fsetting-height-width-images-important-again\u002F\">include \u003Ccode>width\u003C\u002Fcode> and \u003Ccode>height\u003C\u002Fcode> attributes\u003C\u002Fa> on your images and video elements. This approach ensures that the browser can allocate the correct amount of space in the document while the image is loading. Lighthouse will highlight images without a width and height:\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:image -->\n\u003Cfigure class=\"wp-block-image\">\u003Cimg src=\"https:\u002F\u002Flh3.googleusercontent.com\u002F2x0Y3yxxKu6cdyLbkDnk4NzjfV1kSrsyEXokGlcbgE1Bijc0qMjZfdz7n9fttc5qfKFB0LgAddmZ12aqqYhwBIsOZkgqjVE7XDyqFrp4QyLCZU9WJbhKh6W41LgKgbWnZ0M71lUX\" alt=\"\"\u002F>\u003Cfigcaption class=\"wp-element-caption\">\u003Cem>Most images on the blog do set a width and height. Lighthouse was only able to find one small example and CLS on the pages tested were generally pretty good!\u003C\u002Fem>\u003C\u002Ffigcaption>\u003C\u002Ffigure>\n\u003C!-- \u002Fwp:image -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading -->\n\u003Ch2 id=\"h-largest-contentful-paint\">Largest Contentful Paint\u003C\u002Fh2>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>In many modern web experiences, images tend to be the largest visible element when a page completes loading. These include hero images and images from carousels, stories, and banners. \u003Ca href=\"https:\u002F\u002Fweb.dev\u002Flcp\u002F\">Largest Contentful Paint\u003C\u002Fa> (LCP) is a Core Web Vitals metric which measures when the largest contentful element (images, text) in a user’s viewport, becomes visible. This allows a browser to determine when the main content of the page has finished rendering.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>When an image is the largest contentful element, how slowly the image loads can impact LCP. In addition to applying image compression (e.g. using \u003Ca href=\"https:\u002F\u002Fsquoosh.app\">Squoosh\u003C\u002Fa>, \u003Ca href=\"https:\u002F\u002Fsharp.pixelplumbing.com\u002F\">Sharp\u003C\u002Fa>, \u003Ca href=\"https:\u002F\u002Fimageoptim.com\u002Fmac\">ImageOptim\u003C\u002Fa> or an \u003Ca href=\"https:\u002F\u002Fweb.dev\u002Fimage-cdns\u002F\">image CDN\u003C\u002Fa>) and using a modern image format, you can tweak the \u003Ccode>&lt;img&gt;\u003C\u002Fcode> element to serve the most appropriate responsive version of an image or lazy-load it.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3 id=\"h-identify-the-largest-contentful-paint-element\">Identify the Largest Contentful Paint element\u003C\u002Fh3>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Lighthouse has a “Largest Contentful Paint element” audit that identifies what element was the largest contentful paint. Hovering over the element will highlight it in the main browser window.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:image -->\n\u003Cfigure class=\"wp-block-image\">\u003Cimg src=\"https:\u002F\u002Flh5.googleusercontent.com\u002FDV-vPQx8xDQSUAkKnxRMIefkqsy_kqlV6it1psxftOMd73BY_qxU5nLw4SLTPnN88hBtQGzg2YKqeoJ10urzXD9BkpwTsWMHe69pqN_MnHByUS-_-Igthpqwv1RtNXgwoEcmCMPl\" alt=\"\"\u002F>\u003C\u002Ffigure>\n\u003C!-- \u002Fwp:image -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>If this element is an image, this information is a useful hint you may want to optimize the loading of this image.&nbsp;&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Hovering over an image in the Chrome DevTools \u003Cstrong>Elements\u003C\u002Fstrong> panel will display the dimensions of the image as well as the image’s intrinsic size.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:image -->\n\u003Cfigure class=\"wp-block-image\">\u003Cimg src=\"https:\u002F\u002Flh4.googleusercontent.com\u002FBeM9SCXzJAyIkTjFmYLax8WmoxrUppxumLig4MZoeqD_bTpC5cqubC99x-awCqXbtlH6zFmzoQhqO5Z7q3Oj4herg33a1uXDJtVad-P5GQtIwb5h6wYT8DS69l-jCC-fL8eB0OlW\" alt=\"\"\u002F>\u003C\u002Ffigure>\n\u003C!-- \u002Fwp:image -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3 id=\"h-responsive-images\">Responsive images\u003C\u002Fh3>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>What about switching image resolution? A standard \u003Ccode>&lt;img&gt;\u003C\u002Fcode> only allows us to supply a single source file to the browser. But with the \u003Ccode>srcset\u003C\u002Fcode> and \u003Ccode>sizes\u003C\u002Fcode> attributes we can provide many additional source images (and hints) so the browser can pick the most appropriate one. This allows us to supply images that are smaller or larger.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:code -->\n\u003Cpre class=\"wp-block-code\">\u003Ccode>\u003Cstrong>&lt;img\u003C\u002Fstrong> src=\"keyboard-800w.jpg\"\u003Cbr>&nbsp; &nbsp; alt=\"A beautiful pink keyboard.\"\u003Cbr>&nbsp; &nbsp; width=\"400\"\u003Cbr>&nbsp; &nbsp; height=\"400\"\u003Cbr>&nbsp; &nbsp; srcset=\"keyboard-400w.jpg 400w,\u003Cbr>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keyboard-800w.jpg 800w\"\u003Cbr>&nbsp; &nbsp; sizes=\"(max-width: 640px) 400px,\u003Cbr>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 800px\"\u003Cstrong>&gt;\u003C\u002Fstrong>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C!-- \u002Fwp:code -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>The \u003Ccode>srcset\u003C\u002Fcode> attribute defines the set of images the browser can select from, as well as the size of each image. Each image string is separated by a comma and includes: a source filename (\u003Ccode>keyboard-400w.jpg\u003C\u002Fcode>); a space; and the image’s intrinsic width specified in pixels (\u003Ccode>400w\u003C\u002Fcode>), or a pixel density descriptor (\u003Ccode>1x\u003C\u002Fcode>, \u003Ccode>1.5x\u003C\u002Fcode>, \u003Ccode>2x\u003C\u002Fcode>, etc.).\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:image -->\n\u003Cfigure class=\"wp-block-image\">\u003Cimg src=\"https:\u002F\u002Flh3.googleusercontent.com\u002FkHEmMSpUUOdIIfRNEcBijHg2zmB2FEBtOrZM5oUTjvT5q17gWPqyR_14IGKQR3nghrx6cOE6mhOQh8TOCHrIYrhG-1CyXbDHpv5gqiEauUrqu8arAhwgeVGtXC9uKtNywVG2djiH\" alt=\"\"\u002F>\u003Cfigcaption class=\"wp-element-caption\">From \u003Ca href=\"https:\u002F\u002Fyoutu.be\u002FYJGCZCaIZkQ?t=839\">Speed at Scale\u003C\u002Fa> with Katie Hempenius and I at Google I\u002FO\u003C\u002Ffigcaption>\u003C\u002Ffigure>\n\u003C!-- \u002Fwp:image -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>The \u003Ccode>sizes\u003C\u002Fcode> attribute specifies a set of conditions, such as screen widths, and what image size is best to select when those conditions are met. Above, (\u003Ccode>max-width:640px\u003C\u002Fcode>) is a media condition asking “if the viewport width is 640 pixels or less,” and \u003Ccode>400px\u003C\u002Fcode> is the width the slot the image is going to fill when the media condition is true. This typically corresponds to the page’s responsive breakpoints.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3 id=\"h-device-pixel-ratio-dpr-pixel-density-capping\">Device Pixel Ratio (DPR) \u002F Pixel density capping\u003C\u002Fh3>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Device Pixel Ratio (DPR) represents how a CSS pixel is translated to physical pixels on a hardware screen. \u003Ca href=\"https:\u002F\u002Fweb.dev\u002Fchoose-the-right-image-format\u002F#implications-of-high-resolution-screens\">High resolution\u003C\u002Fa> and retina screens use more physical pixels to represent CSS pixels for imagery that is sharper and has more detailed visuals.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>The human eye may not be capable of distinguishing the difference between images that are a 2x-3x DPR vs. an even higher-resolution. Serving overly high DPR images is a common problem for sites leveraging \u003Ccode>&lt;img srcset&gt;\u003C\u002Fcode> and a suite of image sizes.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:image -->\n\u003Cfigure class=\"wp-block-image\">\u003Cimg src=\"https:\u002F\u002Flh5.googleusercontent.com\u002FnmuecJ6F0E0aWXqizV1mHpOvtMHFotybD0kpqoPRw-mDJ0RHWVzr1y9AzQFuvSj64Q_ZGSWT2pRs_Yk-viaCwDuphRM-KIYom1orMjGsFKmq1qHN6Ts5VpQ6DDVcA59KolacysUS\" alt=\"\"\u002F>\u003C\u002Ffigure>\n\u003C!-- \u002Fwp:image -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>It may be possible to use DPR-capping to serve your users an image at a 2x or 3x fidelity to prevent large image payloads. Twitter \u003Ca href=\"https:\u002F\u002Fblog.twitter.com\u002Fengineering\u002Fen_us\u002Ftopics\u002Finfrastructure\u002F2019\u002Fcapping-image-fidelity-on-ultra-high-resolution-devices.html\">capped\u003C\u002Fa> their image fidelity at 2x, resulting in 33% faster timeline image loading times. They found that 2x was a sweet spot of both good performance wins with no degradation in quality metrics.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Cstrong>Note: \u003C\u002Fstrong>This approach to DPR-capping is currently not possible if using “w” descriptors.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:image -->\n\u003Cfigure class=\"wp-block-image\">\u003Cimg src=\"https:\u002F\u002Flh6.googleusercontent.com\u002F3-PmE9TVa_K8LQqlIytAAQRV4UvEVFkHBKOyBCcCOPsVwN2efN_wdN50XJ2PXO2TJYJUCphwXpPdXak5RcpjeNDpFxKJ1su2qZt_j55Xu3A5Say_6q6SqH20RTd07fgAZ5J3mf9i\" alt=\"\"\u002F>\u003C\u002Ffigure>\n\u003C!-- \u002Fwp:image -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3 id=\"h-identify-images-that-can-be-better-sized\">Identify images that can be better sized\u003C\u002Fh3>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Lighthouse includes a number of image optimization audits for helping you understand if your images could be better compressed, delivered in a more optimal modern image format or resized.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:image -->\n\u003Cfigure class=\"wp-block-image\">\u003Cimg src=\"https:\u002F\u002Flh6.googleusercontent.com\u002FzZVIxbEPPJpv0ZkDgdyVV27RrIDNwPuT5FVc95W6DljE8BTAwvD8rQmt6JtvoEf7vq9g8mPoxSIU6doA2FhOE0VLfZVNZnuZoIDtj2hk_jsTfV5lAG3d9QuH3JKOmbnHgZ5Isc5p\" alt=\"\"\u002F>\u003Cfigcaption class=\"wp-element-caption\">\u003Cem>Lighthouse detected that the Stack Overflow blog is using WordPress and was able to suggest some WP-specific guidance on how to size a small number of images that could have been smaller.\u003C\u002Fem>\u003C\u002Ffigcaption>\u003C\u002Ffigure>\n\u003C!-- \u002Fwp:image -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Even those images that are responsive (that is, sized relative to the viewport) should have width and height set. In modern browsers, these attributes establish an aspect ratio that helps prevent layout shifts, even if the absolute sizes are overridden by CSS.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:image -->\n\u003Cfigure class=\"wp-block-image\">\u003Cimg src=\"https:\u002F\u002Flh6.googleusercontent.com\u002FG0MUOMZJs8b6Bc1PU-WUKh9Nlp3upEA5z-ZENsSIeml0PGgT5bgyeZVGkDw06M5vAxGfUT0PiqSE178Ygh-vXAYsTbRgzVaM9njS_C-LUddXkyWXfVaEr_rOV1FYEd84qNVSeQdx\" alt=\"\"\u002F>\u003C\u002Ffigure>\n\u003C!-- \u002Fwp:image -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>When not using an image CDN or framework, I like to use \u003Ca href=\"https:\u002F\u002Fresponsivebreakpoints.com\u002F\">responsivebreakpoints.com\u003C\u002Fa> to determine the optimal image breakpoints and generate \u003Ccode>&lt;img&gt; srcset\u003C\u002Fcode> code for my responsive images.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3 id=\"h-serving-modern-image-formats\">Serving modern image formats\u003C\u002Fh3>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Art direction allows us to serve different images depending on a user’s display. While responsive images load different sizes of the same image, art direction can load very different images based on the display.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>The browser can choose which image format to display using the \u003Ccode>&lt;picture&gt;\u003C\u002Fcode> element. The \u003Ccode>&lt;picture&gt;\u003C\u002Fcode> element supports multiple \u003Ccode>&lt;source&gt;\u003C\u002Fcode> elements and a single \u003Ccode>&lt;img&gt;\u003C\u002Fcode> element, which can reference sources for different formats including AVIF and WebP.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:code -->\n\u003Cpre class=\"wp-block-code\">\u003Ccode>&lt;picture&gt;\n    &lt;source srcset=\"keyboard.avif\" type=\"image\u002Favif\"&gt;\n    &lt;source srcset=\"keyboard.webp\" type=\"image\u002Fwebp\"&gt;\n    &lt;source srcset=\"keyboard.jpg\" type=\"image\u002Fjpeg\"&gt;\n    &lt;img src=\"keyboard.jpg\" alt=\"Omg a keyboard\"&gt;\n&lt;\u002Fpicture&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C!-- \u002Fwp:code -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>In this example, the browser will begin to parse the sources and will stop when it has found the first supported match. If no match is found, the browser loads the source specified in \u003Ccode>&lt;img&gt;\u003C\u002Fcode> as the fallback.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Understanding the myriad of image format options out there today can be a confusing process, but you may find Cloudinary’s \u003Ca href=\"https:\u002F\u002Fcloudinary.com\u002Fblog\u002Ftime_for_next_gen_codecs_to_dethrone_jpeg\">comparison of modern image formats\u003C\u002Fa> helpful:\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:image -->\n\u003Cfigure class=\"wp-block-image\">\u003Cimg src=\"https:\u002F\u002Flh6.googleusercontent.com\u002F9HZQk-BaR_xtX3WH6iUMQlPrGqU-sU-8IwmoV1JztlxTbHUPNOzRcBprcIHk4-Be4aWwNcx2J7NnesQxM7vBLmWK5_tMo8cZho0pA4kvIO95nkviNZuAUl6midKT23qbsIYJtzag\" alt=\"\"\u002F>\u003C\u002Ffigure>\n\u003C!-- \u002Fwp:image -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3 id=\"h-identify-images-that-could-be-served-in-a-more-modern-format\">Identify images that could be served in a more modern format\u003C\u002Fh3>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Lighthouse highlights potential savings from serving images in a next-generation format.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:image -->\n\u003Cfigure class=\"wp-block-image\">\u003Cimg src=\"https:\u002F\u002Flh6.googleusercontent.com\u002F5OCgIs3A-5D-o6nXAt_aTTPPsLfzW7rpSf8Zr7OtxmjbiZVjgny55Wtxd5MWrN6VK1JJ-zzhfWCSwKka26Dyl5qtO1iIOGWQnoi43jcXu-uKq_VWQ_fiywM-tKF0Lc9bMUGNzSEJ\" alt=\"\"\u002F>\u003C\u002Ffigure>\n\u003C!-- \u002Fwp:image -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>I also enjoy using \u003Ca href=\"https:\u002F\u002Fsquoosh.app\u002F\">Squoosh\u003C\u002Fa> for its support of bleeding-edge formats, such as JPEG XL, as it offers a low-friction way to experiment with modern formats outside of a CLI or CDN.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:image -->\n\u003Cfigure class=\"wp-block-image\">\u003Cimg src=\"https:\u002F\u002Flh4.googleusercontent.com\u002FkwWAnN2xtb9A6HBuNXv-mRgcsDNTapEPs2zVRyEBidjvlU5GuVHYCP74YajCfERljFZWud9ippP769v5ihx_YaxT9FKPF3oHD3o0Et2LTmNAWtDNI5H7c47OX-_KoWvUKULlWXWP\" alt=\"\"\u002F>\u003C\u002Ffigure>\n\u003C!-- \u002Fwp:image -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>There are multiple ways to approach sizing issues as both \u003Ccode>srcset\u003C\u002Fcode> and sizes are both usable on \u003Ccode>&lt;picture&gt;\u003C\u002Fcode> and \u003Ccode>&lt;img&gt;\u003C\u002Fcode>. When in doubt, use \u003Ccode>&lt;img&gt;\u003C\u002Fcode> with \u003Ccode>srcset\u003C\u002Fcode>\u002F\u003Ccode>sizes\u003C\u002Fcode> for single images that have a simple layout. Use \u003Ccode>&lt;picture&gt;\u003C\u002Fcode> for serving multiple formats, complex layout, and art direction.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>caniuse has the latest browser support details for \u003Ca href=\"https:\u002F\u002Fcaniuse.com\u002Fwebp\">WebP\u003C\u002Fa>, \u003Ca href=\"https:\u002F\u002Fcaniuse.com\u002Favif\">AVIF\u003C\u002Fa> and \u003Ca href=\"https:\u002F\u002Fcaniuse.com\u002Fjpegxl\">JPEG XL\u003C\u002Fa>.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3 id=\"h-content-negotiation\">Content negotiation\u003C\u002Fh3>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>An alternative to manually handling image format selection using \u003Ccode>&lt;picture&gt;\u003C\u002Fcode> is to rely on the \u003Ca href=\"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FHTTP\u002FHeaders\u002FAccept\">\u003Ccode>Accept\u003C\u002Fcode> header\u003C\u002Fa>. This is sent by the client, allowing the server to deliver an image format that is a best-fit for the user. CDNs such as \u003Ca href=\"https:\u002F\u002Fwww.akamai.com\u002Fde\u002Fde\u002Fproducts\u002Fperformance\u002Fimage-and-video-manager.jsp\">Akamai\u003C\u002Fa>, \u003Ca href=\"https:\u002F\u002Fcloudinary.com\u002F\">Cloudinary\u003C\u002Fa>, and \u003Ca href=\"https:\u002F\u002Fsupport.cloudflare.com\u002Fhc\u002Fen-us\u002Farticles\u002F360000607372-Using-Cloudflare-Polish-to-compress-images\">Cloudflare\u003C\u002Fa> support it.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3 id=\"h-request-your-image-early\">Request your image early\u003C\u002Fh3>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>If you are optimizing LCP, preload can help boost how soon late-discovered hero images (e.g such as those loaded by JavaScript or background hero images in CSS) are fetched.&nbsp; Where possible, attempt to solve this by better minimizing the request chains to your LCP image so that the browser doesn’t need to first fetch, parse, and execute JavaScript or wait for a component to render\u002Fhydrate to discover the image.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>You can use \u003Ccode>&lt;link rel=preload&gt;\u003C\u002Fcode> with \u003Ccode>&lt;img&gt;\u003C\u002Fcode> to allow browsers to discover critical resources you want to load as soon as possible, prior to them being found in HTML.&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ccode>&lt;link rel=\"preload\" as=\"image\" href=\"keyboard.jpg\"&gt;\u003C\u002Fcode>\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Cstrong>Note: \u003C\u002Fstrong>Use preload sparingly and \u003Cem>always\u003C\u002Fem> measure its impact in production. If the preload for your image is earlier in the document than it is, this can help browsers discover it (and order relative to other resources).&nbsp;\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Preload can be used to fetch sources for an \u003Ccode>&lt;img&gt;\u003C\u002Fcode> of a particular format:\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ccode>&lt;link rel=\"preload\" as=\"image\" href=\"keyboard.webp\" type=\"image\u002Fwebp\"&gt;\u003C\u002Fcode>\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003Ca href=\"https:\u002F\u002Fweb.dev\u002Fpreload-responsive-images\u002F\">Preload can also be used to fetch responsive images\u003C\u002Fa> so the correct source is discovered sooner:\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:code -->\n\u003Cpre class=\"wp-block-code\">\u003Ccode>&lt;link rel=\"preload\" as=\"image\" \n     href=\"keyboard.jpg\" \n     imagesrcset=\"\n        poster_400px.jpg 400w, \n        poster_800px.jpg 800w, \n        poster_1600px.jpg 1600w\" \n    imagesizes=\"50vw\"&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C!-- \u002Fwp:code -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3 id=\"h-placeholders\">Placeholders\u003C\u002Fh3>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>What if you would like to show the user a placeholder while the image loads? The \u003Ccode>background-image\u003C\u002Fcode> CSS property allows us to set background images on an element, including the \u003Ccode>&lt;img&gt;\u003C\u002Fcode> tag or any parent container elements. We can combine \u003Ccode>background-image\u003C\u002Fcode> with \u003Ccode>background-size: cover\u003C\u002Fcode> to set the size of an element’s background image and scale the image as large as possible without stretching the image.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Placeholders are often inline, Base64-encoded data URLs which are low-quality image placeholders (LQIP) or SVG image placeholders (SQIP). This allows users to get a very quick preview of the image, even on slow network connections, before the sharper final image loads in to replace it.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:code -->\n\u003Cpre class=\"wp-block-code\">\u003Ccode>\u003Cstrong>&lt;img\u003C\u002Fstrong> src=\"donut-800w.jpg\"\u003Cbr>&nbsp; &nbsp; alt=\"A delicious donut\"\u003Cbr>&nbsp; &nbsp; width=\"400\"\u003Cbr>&nbsp; &nbsp; height=\"400\"\u003Cbr>&nbsp; &nbsp; srcset=\"donut-400w.jpg 400w,\u003Cbr>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; donut-800w.jpg 800w\"\u003Cbr>&nbsp; &nbsp; sizes=\"(max-width: 640px) 400px,\u003Cbr>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 800px\"\u003Cbr>&nbsp; &nbsp; loading=\"lazy\"\u003Cbr>&nbsp; &nbsp; decoding=\"async\"\u003Cbr>&nbsp; &nbsp; style=\"background-size: cover;\u003Cbr>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; background-image:\u003Cbr>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; url(data:image\u002Fsvg+xml;base64,\u003Cstrong>&#91;\u003C\u002Fstrong>svg text]);\"\u003Cstrong>&gt;\u003C\u002Fstrong>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C!-- \u002Fwp:code -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Note: Given that Base64 data URLs can be quite long, [\u003Ccode>svg text\u003C\u002Fcode>] is denoted in the example above to improve readability. The decoding attribute above is also used to signal a preference between synchronous and asynchronous image decoding.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>With an inline SVG placeholder, here is how the example from earlier now looks when loaded on a very slow connection. Notice how users are shown a preview right away prior to any full-size images being downloaded:\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:image -->\n\u003Cfigure class=\"wp-block-image\">\u003Cimg src=\"https:\u002F\u002Flh3.googleusercontent.com\u002F9ql0f9Yt5iCESzgu3dwWqhoJ9ugBFy9tE4JvvU6VtchdEf8hici-aqXzE9fKTXCokrpeR8wdju9XVyR7FgtVhAHENnRvIjM0Z7jdJ-LUnUI7KKHICPnP6xgViUNb44SLbwaVr3V7\" alt=\"\"\u002F>\u003Cfigcaption class=\"wp-element-caption\">\u003Cem>Images loaded on a simulated slow connection, displaying a placeholder approximating the final image as it loads in. This can improve perceived performance in certain cases.\u003C\u002Fem>\u003C\u002Ffigcaption>\u003C\u002Ffigure>\n\u003C!-- \u002Fwp:image -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>There are a variety of modern solutions for image placeholders (e.g CSS background-color, LQIP, SQIP, \u003Ca href=\"https:\u002F\u002Fblurha.sh\u002F\">Blur Hash\u003C\u002Fa>, Potrace). \u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:image {\"id\":19850,\"sizeSlug\":\"full\",\"linkDestination\":\"none\"} -->\n\u003Cfigure class=\"wp-block-image size-full\">\u003Cimg src=\"https:\u002F\u002Fstackoverflow.blog\u002Fwp-content\u002Fuploads\u002F2022\u002F03\u002Funnamed-5.png\" alt=\"\" class=\"wp-image-19850\"\u002F>\u003Cfigcaption class=\"wp-element-caption\">\u003Ca href=\"https:\u002F\u002Fgithub.com\u002FWICG\u002Flargest-contentful-paint\u002Fissues\u002F68#issuecomment-742141525\">Perceptual image loading methods\u003C\u002Fa> from Gunther Brunner of CyberAgent\u003C\u002Ffigcaption>\u003C\u002Ffigure>\n\u003C!-- \u002Fwp:image -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading -->\n\u003Ch2 id=\"h-first-input-delay\">First Input Delay\u003C\u002Fh2>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>It’s possible for images to block a user’s bandwidth and CPU on page load. They can get in the way of how critical resources are loaded, in particular on slow connections and lower-end mobile devices leading to bandwidth saturation. \u003Ca href=\"http:\u002F\u002Fweb.dev\u002Ffid\">First Input Delay\u003C\u002Fa> (FID) is a Core Web Vitals metric that captures a user's first impression of a site's interactivity and responsiveness. By reducing main-thread CPU usage, FID can also be reduced.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading {\"level\":3} -->\n\u003Ch3 id=\"h-image-lazy-loading\">Image lazy loading\u003C\u002Fh3>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>What about offscreen images that are not visible until a user scrolls down the page? There may not be value in eagerly loading lots of images a user may never see, especially if it slows loading more critical content they see earlier on in the page. In the example below, all the images on the page are “eagerly loaded” (the default in browsers today), causing the user to download 1.1 MB of images. This can cause users’ data plans to take a hit in addition to affecting performance.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:image -->\n\u003Cfigure class=\"wp-block-image\">\u003Cimg src=\"https:\u002F\u002Flh4.googleusercontent.com\u002FyPb6VVYiWtXTxmqxbla5qytPg8VkJiXPIXdGeaDXBG3dDrDo6cpiZNAfmDRlKyRKL_LbxZ-JLCexfjI7ZfDJKEzB9q8K8LfAKgBtbDoFPl1jNO1bUS7tB3bYw0vB2YIYyFFP3EX1\" alt=\"\"\u002F>\u003Cfigcaption class=\"wp-element-caption\">\u003Cem>An image gallery eagerly loading all the images it needs up front, as shown in the Chrome DevTools \u003C\u002Fem>\u003Cstrong>\u003Cem>Network\u003C\u002Fem>\u003C\u002Fstrong>\u003Cem> panel. 1.1 MB of images have been downloaded, despite only a small number being visible when the user first lands on the page.\u003C\u002Fem>\u003C\u002Ffigcaption>\u003C\u002Ffigure>\n\u003C!-- \u002Fwp:image -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Using the \u003Ca href=\"https:\u002F\u002Fweb.dev\u002Fnative-lazy-loading\u002F\">\u003Ccode>loading\u003C\u002Fcode> attribute\u003C\u002Fa> on \u003Ccode>&lt;img&gt;\u003C\u002Fcode>, we can control the behavior of image loading. \u003Ccode>loading=\"lazy\"\u003C\u002Fcode> lazy-loads images, deferring their loading until they reach a calculated distance from the viewport. Setting \u003Ccode>loading=\"eager\"\u003C\u002Fcode> loads images right away, regardless of their visibility in the viewport. The default is \u003Ccode>eager\u003C\u002Fcode>, so it doesn’t need to be explicitly added (that is, just use \u003Ccode>&lt;img&gt;\u003C\u002Fcode> for eager loading).\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Below is an example of lazy-loading an \u003Ccode>&lt;img&gt;\u003C\u002Fcode> with a single source:\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:code -->\n\u003Cpre class=\"wp-block-code\">\u003Ccode>\u003Cstrong>&lt;img\u003C\u002Fstrong> src=\"donut.jpg\"\u003Cbr>&nbsp; &nbsp; alt=\"A delicious pink donut.\"\u003Cbr>&nbsp; &nbsp; loading=\"lazy\"\u003Cbr>&nbsp; &nbsp; width=\"400\"\u003Cbr>&nbsp; &nbsp; height=\"400\"\u003Cstrong>&gt;\u003C\u002Fstrong>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C!-- \u002Fwp:code -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>With native \u003Ccode>&lt;img&gt;\u003C\u002Fcode> lazy-loading, the earlier example now downloads only about 90 KB of images! Just adding \u003Ccode>loading=\"lazy\"\u003C\u002Fcode> to our offscreen images has a huge impact. You ideally want to lazy-load all images present \u003Ca href=\"https:\u002F\u002Fweb.dev\u002Fbrowser-level-image-lazy-loading\u002F#avoid-lazy-loading-images-that-are-in-the-first-visible-viewport\">outside of the initial viewport\u003C\u002Fa> and avoid it for everything within the initial viewport.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:image -->\n\u003Cfigure class=\"wp-block-image\">\u003Cimg src=\"https:\u002F\u002Flh5.googleusercontent.com\u002FH1GzudpIZ1_WZLZNZDGfKNfCzttPsWyspXQXSSn9mVULK7xF6l_X81vMOtUIxe7ZG2UtYrE3rvo3HH_gIqr2o2ypim0JhvSa3TzcYszIVFZJ5hrrfYm_fwPf4cnKUaWmB5inVhpd\" alt=\"\"\u002F>\u003Cfigcaption class=\"wp-element-caption\">\u003Cem>An image gallery using native image lazy-loading on images outside of the viewport. As seen in the Chrome DevTools \u003C\u002Fem>\u003Cstrong>\u003Cem>Network\u003C\u002Fem>\u003C\u002Fstrong>\u003Cem> panel, the page now only downloads the bare minimum of images users need up front. The rest of the images are loaded in as users scroll down the page.\u003C\u002Fem>\u003C\u002Ffigcaption>\u003C\u002Ffigure>\n\u003C!-- \u002Fwp:image -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Lazy loading also works with images that include \u003Ccode>srcset\u003C\u002Fcode>:\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:code -->\n\u003Cpre class=\"wp-block-code\">\u003Ccode>\u003Cstrong>&lt;img\u003C\u002Fstrong> src=\"donut-800w.jpg\"\u003Cbr>&nbsp; &nbsp; alt=\"A delicious pink donut\"\u003Cbr>&nbsp; &nbsp; width=\"400\"\u003Cbr>&nbsp; &nbsp; height=\"400\"\u003Cbr>&nbsp; &nbsp; srcset=\"donut-400w.jpg 400w,\u003Cbr>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; donut-800w.jpg 800w\"\u003Cbr>&nbsp; &nbsp; sizes=\"(max-width: 640px) 400px,\u003Cbr>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 800px\"\u003Cbr>&nbsp; &nbsp; loading=\"lazy\"\u003Cstrong>&gt;\u003C\u002Fstrong>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C!-- \u002Fwp:code -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>The \u003Cstrong>Opportunities \u003C\u002Fstrong>section of Lighthouse lists any offscreen or hidden images on a page that can be lazy-loaded as well as the potential savings from doing so.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:image -->\n\u003Cfigure class=\"wp-block-image\">\u003Cimg src=\"https:\u002F\u002Flh3.googleusercontent.com\u002FeY7ZVEC9CBIVq_QMnTZTDIhbwmV8bwHT1jkVmrhSbqgWCq95SaEwmr5rUP6JIruL53OytOppg98oZB6xixS-TXYIuVWcXIYrBIZTCg43kU94PxoOvw595d3IuDGKv65iQXWcaGnz\" alt=\"\"\u002F>\u003Cfigcaption class=\"wp-element-caption\">See \u003Ca href=\"https:\u002F\u002Fcaniuse.com\u002Floading-lazy-attr\">caniuse.com\u003C\u002Fa> for latest browser support for native image lazy-loading.\u003C\u002Ffigcaption>\u003C\u002Ffigure>\n\u003C!-- \u002Fwp:image -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:heading -->\n\u003Ch2 id=\"h-conclusions\">Conclusions\u003C\u002Fh2>\n\u003C!-- \u002Fwp:heading -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>Images are key to delivering a great experience on the web. Hopefully you’ve learned something useful about how far the \u003Ccode>&lt;img&gt;\u003C\u002Fcode> element has evolved. When in doubt, test it out and see what tools like Lighthouse suggest might be opportunities to deliver an even more amazing image loading experience than you are today.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->\n\n\u003C!-- wp:paragraph -->\n\u003Cp>If you’re interested in learning more, I recently published a new book called \u003Ca href=\"http:\u002F\u002Fbit.ly\u002Fsmashing-images\">Image Optimization\u003C\u002Fa> that covers advanced image optimization techniques that can help make your images on the web shine.\u003C\u002Fp>\n\u003C!-- \u002Fwp:paragraph -->","html","2022-12-27T14:00:00.000Z",{"current":1911},"picture-perfect-images-with-the-modern-element",[1913,1921,1925,1929,1933],{"_createdAt":1914,"_id":1915,"_rev":1916,"_type":1917,"_updatedAt":1914,"slug":1918,"title":1920},"2023-05-23T16:43:21Z","wp-tagcat-code-for-a-living","9HpbCsT2tq0xwozQfkc4ih","blogTag",{"current":1919},"code-for-a-living","Code for a Living",{"_createdAt":1914,"_id":1922,"_rev":1916,"_type":1917,"_updatedAt":1914,"slug":1923,"title":1924},"wp-tagcat-images",{"current":1924},"images",{"_createdAt":1914,"_id":1926,"_rev":1916,"_type":1917,"_updatedAt":1914,"slug":1927,"title":1928},"wp-tagcat-optimization",{"current":1928},"optimization",{"_createdAt":1914,"_id":1930,"_rev":1916,"_type":1917,"_updatedAt":1914,"slug":1931,"title":1932},"wp-tagcat-performance",{"current":1932},"performance",{"_createdAt":1914,"_id":1934,"_rev":1916,"_type":1917,"_updatedAt":1914,"slug":1935,"title":1937},"wp-tagcat-web-development",{"current":1936},"web-development","web development","Picture perfect images with the modern \u003Cimg> element",[1940,1946,1952,1958],{"_id":1941,"publishedAt":1942,"slug":1943,"sponsored":12,"title":1945},"28e560af-f0aa-4d46-bd90-f435ad604aa7","2026-06-26T14:00:27.102Z",{"_type":10,"current":1944},"paging-charity-how-can-engineering-leaders-avoid-becoming-bond-villains","Paging Charity! How can engineering leaders avoid becoming Bond villains?",{"_id":1947,"publishedAt":1948,"slug":1949,"sponsored":12,"title":1951},"4b22c2a3-3779-4966-93eb-5230391dbdce","2026-06-23T14:08:58.595Z",{"_type":10,"current":1950},"your-ai-shipped-a-backend-that-boots-that-is-the-whole-problem","Your AI shipped a backend that boots. That is the whole problem.",{"_id":1953,"publishedAt":1954,"slug":1955,"sponsored":12,"title":1957},"5cf362e1-fe7b-45af-b69c-914731c6a052","2026-06-23T14:00:00.000Z",{"_type":10,"current":1956},"the-2026-developer-survey-is-now-open-for-human-developers-only","The 2026 Developer Survey is now open (for human developers only)!",{"_id":1959,"publishedAt":1960,"slug":1961,"sponsored":12,"title":1963},"30b995f7-7cb9-4dd8-bf71-d0685940a32b","2026-06-19T14:00:00.000Z",{"_type":10,"current":1962},"dispatches-from-o-reilly-from-capabilities-to-responsibilities","Dispatches from O'Reilly: From capabilities to responsibilities",{"data":1965,"sourceMap":-1},{"count":1966,"lastTimestamp":1967},6,"2023-05-25T09:48:04Z"]