[{"data":1,"prerenderedAt":1176},["ShallowReactive",2],{"content:\u002Fimage-media-optimization\u002Fimage-decoding-and-placeholders\u002Flqip-vs-blurhash-placeholders":3,"surroundings:\u002Fimage-media-optimization\u002Fimage-decoding-and-placeholders\u002Flqip-vs-blurhash-placeholders":1168},{"id":4,"title":5,"body":6,"description":1147,"extension":1148,"meta":1149,"navigation":1161,"path":1162,"seo":1163,"stem":1166,"__hash__":1167},"content\u002Fimage-media-optimization\u002Fimage-decoding-and-placeholders\u002Flqip-vs-blurhash-placeholders\u002Findex.md","LQIP vs BlurHash Placeholders",{"type":7,"value":8,"toc":1130},"minimark",[9,14,29,49,216,221,254,258,264,270,280,286,361,365,370,482,599,603,609,706,710,713,781,785,788,926,930,933,937,948,952,958,962,991,995,1001,1007,1013,1019,1023,1035,1044,1053,1062,1079,1088,1092,1115,1120,1123,1126],[10,11,13],"h1",{"id":12},"lqip-vs-blurhash-placeholders-choosing-an-image-placeholder","LQIP vs BlurHash Placeholders: Choosing an Image Placeholder",[15,16,17,18,23,24,28],"p",{},"This comparison sits within ",[19,20,22],"a",{"href":21},"\u002Fimage-media-optimization\u002Fimage-decoding-and-placeholders\u002F","Image Decoding & Placeholders",", part of ",[19,25,27],{"href":26},"\u002Fimage-media-optimization\u002F","Image & Media Optimization",". Placeholders fill the space an image will occupy while it loads. Their job is perceptual — make the page look composed rather than full of holes — and structural — reserve space so nothing shifts when the image arrives. They do not make the real image load faster, and badly chosen placeholders can make pages slower.",[15,30,31,32,36,37,40,41,44,45,48],{},"There are four common techniques. A ",[33,34,35],"strong",{},"dominant colour"," is a single background colour extracted from the image. ",[33,38,39],{},"LQIP"," (low-quality image placeholder) is a tiny version of the image — often 20–40 pixels wide — inlined as a data URI and blurred with CSS. ",[33,42,43],{},"BlurHash"," encodes a blurred representation into a 20–30 character string, decoded to pixels by JavaScript. ",[33,46,47],{},"ThumbHash"," is a newer variant with better colour and alpha fidelity in a similar size. Each trades bytes, JavaScript and fidelity differently.",[15,50,51],{},[52,53,59,60,59,67,59,71,59,74,59,83,59,89,59,95,59,102,59,106,59,111,59,114,59,118,59,121,59,125,59,129,59,133,59,137,59,141,59,143,59,145,59,150,59,153,59,156,59,160,59,162,59,165,59,167,59,169,59,171,59,174,59,177,59,180,59,182,59,185,59,187,59,190,59,192,59,195,59,198,59,201,59,203,59,206,59,208,59,211,59,213,59],"svg",{"viewBox":54,"width":55,"role":56,"ariaLabel":57,"style":58},"0 0 760 228","100%","img","Comparison of dominant colour, LQIP, BlurHash and ThumbHash by bytes in HTML, JavaScript needed, fidelity and LCP risk.","height:auto;max-width:760px;display:block;margin:1.75rem auto;font-family:inherit;color:var(--fp-svg-ink)"," ",[61,62],"rect",{"className":63,"x":65,"y":65,"width":55,"height":55,"fill":66},[64],"svg-canvas","0","#ffffff",[68,69,70],"title",{},"Placeholder techniques compared",[72,73,57],"desc",{},[61,75],{"x":76,"y":76,"width":77,"height":78,"rx":79,"fill":80,"stroke":81,"style":82},"1","758","226","10","none","currentColor","stroke-opacity:0.18",[84,85,70],"text",{"x":86,"y":87,"fill":81,"style":88},"28.0","34.0","font-size:16px;font-weight:700",[61,90],{"x":86,"y":91,"width":92,"height":93,"rx":65,"fill":81,"stroke":81,"style":94},"56.0","114.7","30.0","fill-opacity:0.06;stroke-opacity:0.4",[84,96,101],{"x":97,"y":98,"fill":81,"style":99,"textAnchor":100},"38.0","75.5","font-size:12.5px;font-weight:700","start","Technique",[61,103],{"x":104,"y":91,"width":105,"height":93,"rx":65,"fill":81,"stroke":81,"style":94},"142.7","196.4",[84,107,110],{"x":108,"y":98,"fill":81,"style":99,"textAnchor":109},"240.9","middle","Bytes per image",[61,112],{"x":113,"y":91,"width":105,"height":93,"rx":65,"fill":81,"stroke":81,"style":94},"339.1",[84,115,117],{"x":116,"y":98,"fill":81,"style":99,"textAnchor":109},"437.3","JS needed",[61,119],{"x":120,"y":91,"width":105,"height":93,"rx":65,"fill":81,"stroke":81,"style":94},"535.6",[84,122,124],{"x":123,"y":98,"fill":81,"style":99,"textAnchor":109},"633.8","Fidelity",[61,126],{"x":86,"y":127,"width":92,"height":93,"rx":65,"fill":80,"stroke":81,"style":128},"86.0","stroke-opacity:0.35",[84,130,132],{"x":97,"y":131,"fill":81,"style":99,"textAnchor":100},"105.5","Dominant colour",[61,134],{"x":104,"y":127,"width":105,"height":93,"rx":65,"fill":135,"stroke":135,"style":136},"#0466c8","fill-opacity:0.14;stroke-opacity:0.9",[84,138,140],{"x":108,"y":131,"fill":81,"style":139,"textAnchor":109},"font-size:12px","~10 bytes CSS",[61,142],{"x":113,"y":127,"width":105,"height":93,"rx":65,"fill":135,"stroke":135,"style":136},[84,144,80],{"x":116,"y":131,"fill":81,"style":139,"textAnchor":109},[61,146],{"x":120,"y":127,"width":105,"height":93,"rx":65,"fill":147,"stroke":148,"style":149},"#ffc300","#b8860b","fill-opacity:0.24;stroke-opacity:0.9",[84,151,152],{"x":123,"y":131,"fill":81,"style":139,"textAnchor":109},"flat colour",[61,154],{"x":86,"y":155,"width":92,"height":93,"rx":65,"fill":80,"stroke":81,"style":128},"116.0",[84,157,159],{"x":97,"y":158,"fill":81,"style":99,"textAnchor":100},"135.5","LQIP (data URI)",[61,161],{"x":104,"y":155,"width":105,"height":93,"rx":65,"fill":81,"stroke":81,"style":94},[84,163,164],{"x":108,"y":158,"fill":81,"style":139,"textAnchor":109},"300-1500 bytes",[61,166],{"x":113,"y":155,"width":105,"height":93,"rx":65,"fill":135,"stroke":135,"style":136},[84,168,80],{"x":116,"y":158,"fill":81,"style":139,"textAnchor":109},[61,170],{"x":120,"y":155,"width":105,"height":93,"rx":65,"fill":135,"stroke":135,"style":136},[84,172,173],{"x":123,"y":158,"fill":81,"style":139,"textAnchor":109},"composition visible",[61,175],{"x":86,"y":176,"width":92,"height":93,"rx":65,"fill":80,"stroke":81,"style":128},"146.0",[84,178,43],{"x":97,"y":179,"fill":81,"style":99,"textAnchor":100},"165.5",[61,181],{"x":104,"y":176,"width":105,"height":93,"rx":65,"fill":135,"stroke":135,"style":136},[84,183,184],{"x":108,"y":179,"fill":81,"style":139,"textAnchor":109},"~30 chars",[61,186],{"x":113,"y":176,"width":105,"height":93,"rx":65,"fill":147,"stroke":148,"style":149},[84,188,189],{"x":116,"y":179,"fill":81,"style":139,"textAnchor":109},"decoder + canvas",[61,191],{"x":120,"y":176,"width":105,"height":93,"rx":65,"fill":81,"stroke":81,"style":94},[84,193,194],{"x":123,"y":179,"fill":81,"style":139,"textAnchor":109},"soft blur",[61,196],{"x":86,"y":197,"width":92,"height":93,"rx":65,"fill":80,"stroke":81,"style":128},"176.0",[84,199,47],{"x":97,"y":200,"fill":81,"style":99,"textAnchor":100},"195.5",[61,202],{"x":104,"y":197,"width":105,"height":93,"rx":65,"fill":135,"stroke":135,"style":136},[84,204,205],{"x":108,"y":200,"fill":81,"style":139,"textAnchor":109},"~30 bytes",[61,207],{"x":113,"y":197,"width":105,"height":93,"rx":65,"fill":147,"stroke":148,"style":149},[84,209,210],{"x":116,"y":200,"fill":81,"style":139,"textAnchor":109},"decoder",[61,212],{"x":120,"y":197,"width":105,"height":93,"rx":65,"fill":135,"stroke":135,"style":136},[84,214,215],{"x":123,"y":200,"fill":81,"style":139,"textAnchor":109},"better colour\u002Falpha",[217,218,220],"h2",{"id":219},"rapid-diagnosis","Rapid Diagnosis",[222,223,224,236,242,248],"ul",{},[225,226,227,230,231,235],"li",{},[33,228,229],{},"Measure placeholder bytes in HTML."," Search the HTML for ",[232,233,234],"code",{},"data:image","; sum sizes. Hundreds of LQIPs can add tens of kilobytes.",[225,237,238,241],{},[33,239,240],{},"Check placeholder JavaScript."," BlurHash\u002FThumbHash decoders and the canvas work to render them run on the main thread; check whether they run at startup.",[225,243,244,247],{},[33,245,246],{},"Check LCP attribution."," If LCP fires early on a blurry preview and then again on the real image, the placeholder is acting as an LCP candidate.",[225,249,250,253],{},[33,251,252],{},"Check CLS."," Placeholders without the image's aspect ratio shift when replaced.",[217,255,257],{"id":256},"root-cause-analysis","Root Cause Analysis",[15,259,260,263],{},[33,261,262],{},"1. LQIP inflating HTML."," Inlining a data URI for every grid image makes the HTML — which carries the LCP text and critical CSS — larger and slower.",[15,265,266,269],{},[33,267,268],{},"2. Runtime decoders at startup."," Decoding dozens of BlurHashes to canvas during load adds main-thread work right when INP and TBT matter.",[15,271,272,275,276,279],{},[33,273,274],{},"3. Placeholders as LCP candidates."," A visible ",[232,277,278],{},"\u003Cimg>"," LQIP large enough to be the biggest element is recorded as an LCP candidate; LCP looks fast in the lab, but when the real image replaces it, a later LCP entry wins.",[15,281,282,285],{},[33,283,284],{},"4. Unsized placeholders."," Placeholder and image with different boxes produce layout shift.",[15,287,288],{},[52,289,59,292,59,295,59,298,59,300,59,303,59,305,59,312,59,319,59,324,59,328,59,333,59,337,59,341,59,345,59,349,59,353,59,357,59],{"viewBox":290,"width":55,"role":56,"ariaLabel":291,"style":58},"0 0 760 194","Bar chart of HTML bytes and startup main-thread time added by four placeholder techniques on a forty-card listing page.",[61,293],{"className":294,"x":65,"y":65,"width":55,"height":55,"fill":66},[64],[68,296,297],{},"Placeholder cost on a 40-card listing page",[72,299,291],{},[61,301],{"x":76,"y":76,"width":77,"height":302,"rx":79,"fill":80,"stroke":81,"style":82},"192",[84,304,297],{"x":86,"y":87,"fill":81,"style":88},[84,306,311],{"x":307,"y":308,"fill":81,"style":309,"textAnchor":310},"226.6","70.0","font-size:13px","end","Dominant colour (KB HTML)",[61,313],{"x":314,"y":91,"width":315,"height":316,"rx":317,"fill":135,"stroke":135,"style":318},"238.6","2.0","19","3","fill-opacity:0.55;stroke-opacity:0.9",[84,320,323],{"x":321,"y":308,"fill":81,"style":322},"246.6","font-size:12px;font-weight:600","0.4",[84,325,327],{"x":307,"y":326,"fill":81,"style":309,"textAnchor":310},"101.0","LQIP all cards (KB HTML)",[61,329],{"x":314,"y":330,"width":331,"height":316,"rx":317,"fill":147,"stroke":148,"style":332},"87.0","192.0","fill-opacity:0.7;stroke-opacity:0.9",[84,334,336],{"x":335,"y":326,"fill":81,"style":322},"436.6","38",[84,338,340],{"x":307,"y":339,"fill":81,"style":309,"textAnchor":310},"132.0","BlurHash strings (KB HTML)",[61,342],{"x":314,"y":343,"width":344,"height":316,"rx":317,"fill":135,"stroke":135,"style":318},"118.0","6.1",[84,346,348],{"x":347,"y":339,"fill":81,"style":322},"250.7","1.2",[84,350,352],{"x":307,"y":351,"fill":81,"style":309,"textAnchor":310},"163.0","BlurHash decode (ms main thread)",[61,354],{"x":314,"y":355,"width":356,"height":316,"rx":317,"fill":147,"stroke":148,"style":332},"149.0","429.4",[84,358,360],{"x":359,"y":351,"fill":81,"style":322},"674.0","85",[217,362,364],{"id":363},"step-by-step-implementing-placeholders-well","Step-by-Step: Implementing Placeholders Well",[366,367,369],"h3",{"id":368},"_1-default-to-aspect-ratio-plus-dominant-colour","1. Default to aspect ratio plus dominant colour",[371,372,377],"pre",{"className":373,"code":374,"language":375,"meta":376,"style":376},"language-html shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","\u003Cdiv class=\"card-media\" style=\"--ph:#c9b8a4\">\n  \u003Cimg src=\"\u002Fimg\u002Fp42-400.avif\" width=\"400\" height=\"300\" loading=\"lazy\" decoding=\"async\" alt=\"Leather boot\">\n\u003C\u002Fdiv>\n","html","",[232,378,379,414,472],{"__ignoreMap":376},[380,381,384,388,392,396,399,403,406,408,411],"span",{"class":382,"line":383},"line",1,[380,385,387],{"class":386},"saISM","\u003C",[380,389,391],{"class":390},"sZBmE","div",[380,393,395],{"class":394},"sPXB4"," class",[380,397,398],{"class":386},"=",[380,400,402],{"class":401},"sZ8jY","\"card-media\"",[380,404,405],{"class":394}," style",[380,407,398],{"class":386},[380,409,410],{"class":401},"\"--ph:#c9b8a4\"",[380,412,413],{"class":386},">\n",[380,415,417,420,422,425,427,430,433,435,438,441,443,446,449,451,454,457,459,462,465,467,470],{"class":382,"line":416},2,[380,418,419],{"class":386},"  \u003C",[380,421,56],{"class":390},[380,423,424],{"class":394}," src",[380,426,398],{"class":386},[380,428,429],{"class":401},"\"\u002Fimg\u002Fp42-400.avif\"",[380,431,432],{"class":394}," width",[380,434,398],{"class":386},[380,436,437],{"class":401},"\"400\"",[380,439,440],{"class":394}," height",[380,442,398],{"class":386},[380,444,445],{"class":401},"\"300\"",[380,447,448],{"class":394}," loading",[380,450,398],{"class":386},[380,452,453],{"class":401},"\"lazy\"",[380,455,456],{"class":394}," decoding",[380,458,398],{"class":386},[380,460,461],{"class":401},"\"async\"",[380,463,464],{"class":394}," alt",[380,466,398],{"class":386},[380,468,469],{"class":401},"\"Leather boot\"",[380,471,413],{"class":386},[380,473,475,478,480],{"class":382,"line":474},3,[380,476,477],{"class":386},"\u003C\u002F",[380,479,391],{"class":390},[380,481,413],{"class":386},[371,483,487],{"className":484,"code":485,"language":486,"meta":376,"style":376},"language-css shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast",".card-media { aspect-ratio: 4 \u002F 3; background: var(--ph); }\n.card-media img { width: 100%; height: 100%; object-fit: cover; display: block; }\n\u002F* trade-off: a flat colour conveys tone but not composition; it is the right\n   default for grids where many images load quickly. *\u002F\n","css",[232,488,489,532,587,593],{"__ignoreMap":376},[380,490,491,494,497,500,503,506,509,511,514,517,519,522,525,529],{"class":382,"line":383},[380,492,493],{"class":394},".card-media",[380,495,496],{"class":386}," { ",[380,498,499],{"class":394},"aspect-ratio",[380,501,502],{"class":386},": ",[380,504,505],{"class":394},"4",[380,507,508],{"class":386}," \u002F ",[380,510,317],{"class":394},[380,512,513],{"class":386},"; ",[380,515,516],{"class":394},"background",[380,518,502],{"class":386},[380,520,521],{"class":394},"var",[380,523,524],{"class":386},"(",[380,526,528],{"class":527},"sQw3B","--ph",[380,530,531],{"class":386},"); }\n",[380,533,534,536,539,541,544,546,549,553,555,558,560,562,564,566,569,571,574,576,579,581,584],{"class":382,"line":416},[380,535,493],{"class":394},[380,537,538],{"class":390}," img",[380,540,496],{"class":386},[380,542,543],{"class":394},"width",[380,545,502],{"class":386},[380,547,548],{"class":394},"100",[380,550,552],{"class":551},"sPARh","%",[380,554,513],{"class":386},[380,556,557],{"class":394},"height",[380,559,502],{"class":386},[380,561,548],{"class":394},[380,563,552],{"class":551},[380,565,513],{"class":386},[380,567,568],{"class":394},"object-fit",[380,570,502],{"class":386},[380,572,573],{"class":394},"cover",[380,575,513],{"class":386},[380,577,578],{"class":394},"display",[380,580,502],{"class":386},[380,582,583],{"class":394},"block",[380,585,586],{"class":386},"; }\n",[380,588,589],{"class":382,"line":474},[380,590,592],{"class":591},"sjfSM","\u002F* trade-off: a flat colour conveys tone but not composition; it is the right\n",[380,594,596],{"class":382,"line":595},4,[380,597,598],{"class":591},"   default for grids where many images load quickly. *\u002F\n",[366,600,602],{"id":601},"_2-use-lqip-selectively-as-a-css-background","2. Use LQIP selectively, as a CSS background",[15,604,605,606,608],{},"For a handful of large images (the hero, a feature image), a tiny blurred preview improves perceived quality. Put it on the container as a background so it cannot be an ",[232,607,278],{}," LCP candidate.",[371,610,612],{"className":484,"code":611,"language":486,"meta":376,"style":376},".hero-media { aspect-ratio: 16 \u002F 9; background: center \u002F cover no-repeat url(\"data:image\u002Fwebp;base64,UklGRj4AAABXRUJQVlA4…\"); }\n.hero-media img { opacity: 1; transition: opacity 200ms; }\n\u002F* trade-off: CSS background-image placeholders can themselves be LCP candidates\n   if large and visible; a blurred low-content background is usually smaller in\n   effective area or replaced quickly, but check LCP attribution after adding it. *\u002F\n",[232,613,614,659,690,695,700],{"__ignoreMap":376},[380,615,616,619,621,623,625,628,630,633,635,637,639,642,644,646,649,652,654,657],{"class":382,"line":383},[380,617,618],{"class":394},".hero-media",[380,620,496],{"class":386},[380,622,499],{"class":394},[380,624,502],{"class":386},[380,626,627],{"class":394},"16",[380,629,508],{"class":386},[380,631,632],{"class":394},"9",[380,634,513],{"class":386},[380,636,516],{"class":394},[380,638,502],{"class":386},[380,640,641],{"class":394},"center",[380,643,508],{"class":386},[380,645,573],{"class":394},[380,647,648],{"class":394}," no-repeat",[380,650,651],{"class":394}," url",[380,653,524],{"class":386},[380,655,656],{"class":401},"\"data:image\u002Fwebp;base64,UklGRj4AAABXRUJQVlA4…\"",[380,658,531],{"class":386},[380,660,661,663,665,667,670,672,674,676,679,682,685,688],{"class":382,"line":416},[380,662,618],{"class":394},[380,664,538],{"class":390},[380,666,496],{"class":386},[380,668,669],{"class":394},"opacity",[380,671,502],{"class":386},[380,673,76],{"class":394},[380,675,513],{"class":386},[380,677,678],{"class":394},"transition",[380,680,681],{"class":386},": opacity ",[380,683,684],{"class":394},"200",[380,686,687],{"class":551},"ms",[380,689,586],{"class":386},[380,691,692],{"class":382,"line":474},[380,693,694],{"class":591},"\u002F* trade-off: CSS background-image placeholders can themselves be LCP candidates\n",[380,696,697],{"class":382,"line":595},[380,698,699],{"class":591},"   if large and visible; a blurred low-content background is usually smaller in\n",[380,701,703],{"class":382,"line":702},5,[380,704,705],{"class":591},"   effective area or replaced quickly, but check LCP attribution after adding it. *\u002F\n",[366,707,709],{"id":708},"_3-decode-blurhashthumbhash-at-build-time-not-runtime","3. Decode BlurHash\u002FThumbHash at build time, not runtime",[15,711,712],{},"If your data source provides BlurHash strings, decode them to a tiny image or a few gradient stops on the server or at build time, and ship CSS — not a decoder.",[371,714,718],{"className":715,"code":716,"language":717,"meta":376,"style":376},"language-javascript shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","\u002F\u002F build step: turn a ThumbHash into a data URL once.\nimport { thumbHashToDataURL } from 'thumbhash';\nconst placeholder = thumbHashToDataURL(Buffer.from(product.thumbhash, 'base64'));\n\u002F\u002F trade-off: the data URL is larger than the hash string (a few hundred bytes),\n\u002F\u002F but it needs no client JavaScript and renders on first paint.\n","javascript",[232,719,720,725,742,771,776],{"__ignoreMap":376},[380,721,722],{"class":382,"line":383},[380,723,724],{"class":591},"\u002F\u002F build step: turn a ThumbHash into a data URL once.\n",[380,726,727,730,733,736,739],{"class":382,"line":416},[380,728,729],{"class":551},"import",[380,731,732],{"class":386}," { thumbHashToDataURL } ",[380,734,735],{"class":551},"from",[380,737,738],{"class":401}," 'thumbhash'",[380,740,741],{"class":386},";\n",[380,743,744,747,750,753,757,760,762,765,768],{"class":382,"line":474},[380,745,746],{"class":551},"const",[380,748,749],{"class":394}," placeholder",[380,751,752],{"class":551}," =",[380,754,756],{"class":755},"smZ65"," thumbHashToDataURL",[380,758,759],{"class":386},"(Buffer.",[380,761,735],{"class":755},[380,763,764],{"class":386},"(product.thumbhash, ",[380,766,767],{"class":401},"'base64'",[380,769,770],{"class":386},"));\n",[380,772,773],{"class":382,"line":595},[380,774,775],{"class":591},"\u002F\u002F trade-off: the data URL is larger than the hash string (a few hundred bytes),\n",[380,777,778],{"class":382,"line":702},[380,779,780],{"class":591},"\u002F\u002F but it needs no client JavaScript and renders on first paint.\n",[366,782,784],{"id":783},"_4-fade-in-the-real-image-without-layout-change","4. Fade in the real image without layout change",[15,786,787],{},"Swap or fade the real image over the placeholder within the same box; never change dimensions.",[15,789,790],{},[52,791,59,794,59,797,59,800,59,802,59,818,59,821,59,823,59,828,59,834,59,837,59,842,59,850,59,856,59,860,59,866,59,870,59,873,59,877,59,879,59,883,59,886,59,888,59,892,59,895,59,898,59,902,59,904,59,907,59,910,59,913,59,917,59,920,59,923,59],{"viewBox":792,"width":55,"role":56,"ariaLabel":793,"style":58},"0 0 760 342","Decision sequence for choosing an image placeholder technique.",[61,795],{"className":796,"x":65,"y":65,"width":55,"height":55,"fill":66},[64],[68,798,799],{},"Which placeholder for this image?",[72,801,793],{},[803,804,805],"defs",{},[806,807,813],"marker",{"id":808,"viewBox":809,"refX":632,"refY":810,"markerWidth":811,"markerHeight":811,"orient":812},"fae21fee50","0 0 10 10","5","7","auto-start-reverse",[814,815],"path",{"d":816,"fill":81,"style":817},"M0 0 L10 5 L0 10 z","fill-opacity:0.7",[61,819],{"x":76,"y":76,"width":77,"height":820,"rx":79,"fill":80,"stroke":81,"style":82},"340",[84,822,799],{"x":86,"y":87,"fill":81,"style":88},[61,824],{"x":86,"y":91,"width":825,"height":826,"rx":827,"fill":81,"stroke":81,"style":94},"320.0","35.0","6",[84,829,833],{"x":830,"y":831,"fill":81,"style":832,"textAnchor":109},"188.0","78.0","font-size:13px;font-weight:700","One of many images in a grid or feed?",[61,835],{"x":836,"y":91,"width":825,"height":826,"rx":827,"fill":135,"stroke":135,"style":136},"412.0",[84,838,841],{"x":839,"y":831,"fill":81,"style":840,"textAnchor":109},"572.0","font-size:12.5px","Aspect ratio + dominant colour",[382,843],{"x1":844,"y1":845,"x2":846,"y2":845,"stroke":81,"strokeWidth":847,"style":848,"markerEnd":849},"348.0","73.5","410.0","1.5","stroke-opacity:0.6","url(#fae21fee50)",[84,851,855],{"x":852,"y":853,"fill":135,"style":854,"textAnchor":109},"380.0","66.5","font-size:11.5px;font-weight:700","yes",[382,857],{"x1":830,"y1":858,"x2":830,"y2":859,"stroke":81,"strokeWidth":847,"style":848,"markerEnd":849},"91.0","125.0",[84,861,865],{"x":862,"y":863,"fill":864,"style":854},"196.0","113.0","#51617a","no",[61,867],{"x":86,"y":868,"width":825,"height":869,"rx":827,"fill":81,"stroke":81,"style":94},"127.0","52.0",[84,871,872],{"x":830,"y":355,"fill":81,"style":832,"textAnchor":109},"Large hero or feature image where composition",[84,874,876],{"x":830,"y":875,"fill":81,"style":832,"textAnchor":109},"166.0","matters?",[61,878],{"x":836,"y":868,"width":825,"height":869,"rx":827,"fill":135,"stroke":135,"style":136},[84,880,882],{"x":839,"y":881,"fill":81,"style":840,"textAnchor":109},"157.5","LQIP as a CSS background",[382,884],{"x1":844,"y1":885,"x2":846,"y2":885,"stroke":81,"strokeWidth":847,"style":848,"markerEnd":849},"153.0",[84,887,855],{"x":852,"y":176,"fill":135,"style":854,"textAnchor":109},[382,889],{"x1":830,"y1":890,"x2":830,"y2":891,"stroke":81,"strokeWidth":847,"style":848,"markerEnd":849},"179.0","213.0",[84,893,865],{"x":862,"y":894,"fill":864,"style":854},"201.0",[61,896],{"x":86,"y":897,"width":825,"height":826,"rx":827,"fill":81,"stroke":81,"style":94},"215.0",[84,899,901],{"x":830,"y":900,"fill":81,"style":832,"textAnchor":109},"237.0","Data already includes BlurHash\u002FThumbHash?",[61,903],{"x":836,"y":897,"width":825,"height":826,"rx":827,"fill":135,"stroke":135,"style":136},[84,905,906],{"x":839,"y":900,"fill":81,"style":840,"textAnchor":109},"Decode at build time to CSS or tiny image",[382,908],{"x1":844,"y1":909,"x2":846,"y2":909,"stroke":81,"strokeWidth":847,"style":848,"markerEnd":849},"232.5",[84,911,855],{"x":852,"y":912,"fill":135,"style":854,"textAnchor":109},"225.5",[382,914],{"x1":830,"y1":915,"x2":830,"y2":916,"stroke":81,"strokeWidth":847,"style":848,"markerEnd":849},"250.0","284.0",[84,918,865],{"x":862,"y":919,"fill":864,"style":854},"272.0",[61,921],{"x":86,"y":922,"width":825,"height":87,"rx":827,"fill":147,"stroke":148,"style":149},"286.0",[84,924,841],{"x":830,"y":925,"fill":81,"style":840,"textAnchor":109},"307.5",[217,927,929],{"id":928},"verification","Verification",[15,931,932],{},"Check HTML size before and after, the absence of placeholder decoders in startup traces, LCP attribution (the final LCP should be the real image, not a preview), and CLS (zero shift on image arrival, verified with Layout Shift Regions).",[217,934,936],{"id":935},"worked-example-a-real-estate-listings-page","Worked Example: A Real Estate Listings Page",[15,938,939,940,943,944,947],{},"A listings page rendered 60 cards with BlurHash placeholders decoded in the browser by a 7KB library onto 60 small canvases at startup. Startup scripting included 110ms of decoding on mid-tier phones, and some cards shifted when photos loaded because canvases had a fixed height while photos varied. The team replaced runtime decoding with build-time dominant colours, kept a single LQIP for the featured listing, and gave every card ",[232,941,942],{},"aspect-ratio: 3 \u002F 2"," with ",[232,945,946],{},"object-fit: cover",". TBT fell by 120ms, CLS on the page dropped from 0.07 to 0.01, and users perceived the page as equally polished in a quick internal survey.",[217,949,951],{"id":950},"placeholders-and-the-lcp-metric","Placeholders and the LCP Metric",[15,953,954,955,957],{},"Placeholders interact with LCP in ways worth testing. An LQIP rendered as an ",[232,956,278],{}," — or even as a large visible background — can be recorded as an LCP candidate when it paints. If the real image then paints in the same box, it produces a new LCP entry at its later time, and the final LCP is the real image, so the placeholder does not \"fake\" the metric. But if the user interacts before the real image paints, LCP stops at the placeholder, recording a misleadingly early value. For stable, honest measurement, keep placeholders as low-detail backgrounds on the container and make sure the real image is optimised as the true LCP element.",[217,959,961],{"id":960},"common-mistakes","Common Mistakes",[222,963,964,970,976,985],{},[225,965,966,969],{},[33,967,968],{},"LQIP on every image."," Inflates HTML for minimal perceived benefit in dense grids.",[225,971,972,975],{},[33,973,974],{},"Runtime decoders at load."," Main-thread cost when it matters most.",[225,977,978,984],{},[33,979,980,981,983],{},"Placeholders as ",[232,982,278],{}," LCP candidates."," Confuses LCP measurement.",[225,986,987,990],{},[33,988,989],{},"Mismatched aspect ratios."," Layout shift when the real image arrives.",[217,992,994],{"id":993},"edge-cases","Edge Cases",[15,996,997,1000],{},[33,998,999],{},"Transparent images."," Dominant-colour placeholders look wrong for logos and cut-outs on transparent backgrounds; use no placeholder or ThumbHash (which encodes alpha).",[15,1002,1003,1006],{},[33,1004,1005],{},"Dark mode."," Light-toned placeholders flash on dark themes; derive placeholders from the image itself, not a fixed grey.",[15,1008,1009,1012],{},[33,1010,1011],{},"Image CDNs."," Some CDNs generate dominant colours and tiny previews via URL parameters, removing build steps.",[15,1014,1015,1018],{},[33,1016,1017],{},"Low-bandwidth users."," Placeholders are seen longer on slow networks; that is where LQIP's composition preview adds the most value.",[217,1020,1022],{"id":1021},"faq","FAQ",[1024,1025,1028,1032],"details",{"className":1026},[1027],"faq-item",[1029,1030,1031],"summary",{},"Do placeholders improve Core Web Vitals?",[15,1033,1034],{},"They improve CLS when they reserve space correctly. They do not improve LCP for the real image. Their main benefit is perceived performance.",[1024,1036,1038,1041],{"className":1037},[1027],[1029,1039,1040],{},"Is BlurHash worth it over LQIP?",[15,1042,1043],{},"BlurHash strings are tiny in data payloads, which matters for APIs and mobile apps. For web pages, decoding them in the browser costs JavaScript; build-time conversion gives you the visual without the runtime cost.",[1024,1045,1047,1050],{"className":1046},[1027],[1029,1048,1049],{},"How small should an LQIP be?",[15,1051,1052],{},"Around 16–40 pixels wide, heavily compressed (WebP or AVIF), typically 200–800 bytes, displayed blurred. Larger previews add bytes without much perceptual gain.",[1024,1054,1056,1059],{"className":1055},[1027],[1029,1057,1058],{},"Should placeholders fade out?",[15,1060,1061],{},"A short opacity transition of the real image over the placeholder looks smooth and costs little (opacity is composited). Avoid animating size or blur radius, which repaint.",[1024,1063,1065,1068],{"className":1064},[1027],[1029,1066,1067],{},"Do frameworks provide placeholders?",[15,1069,1070,1071,1074,1075,1078],{},"Yes — Next.js ",[232,1072,1073],{},"placeholder=\"blur\"",", Nuxt Image ",[232,1076,1077],{},"placeholder",", Astro and Gatsby image plugins. Check whether they inline data URIs per image and whether that HTML cost is acceptable for your page.",[1024,1080,1082,1085],{"className":1081},[1027],[1029,1083,1084],{},"What about skeleton shimmers for images?",[15,1086,1087],{},"An animated shimmer is a placeholder too. Animate it with transforms, stop it under reduced motion, and keep it in a sized container; for images, a static dominant colour is often better.",[217,1089,1091],{"id":1090},"related","Related",[222,1093,1094,1101,1108],{},[225,1095,1096,1100],{},[19,1097,1099],{"href":1098},"\u002Fcore-web-vitals-measurement\u002Freducing-cumulative-layout-shift-cls\u002Ffixing-cls-from-skeleton-screens-that-resize\u002F","Fixing CLS from skeleton screens that resize"," — sizing placeholders correctly.",[225,1102,1103,1107],{},[19,1104,1106],{"href":1105},"\u002Fimage-media-optimization\u002Fimage-decoding-and-placeholders\u002Fusing-decoding-async-and-the-decode-api\u002F","Using decoding=async and the decode() API"," — how the real image replaces the placeholder.",[225,1109,1110,1114],{},[19,1111,1113],{"href":1112},"\u002Fimage-media-optimization\u002Fresponsive-images-with-srcset-and-sizes\u002Fresponsive-images-with-nuxt-image-and-astro\u002F","Responsive images with Nuxt Image and Astro"," — framework placeholder options.",[1116,1117,1119],"script",{"type":1118},"application\u002Fld+json","\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"HowTo\",\n  \"name\": \"LQIP vs BlurHash Placeholders: Choosing an Image Placeholder\",\n  \"description\": \"How the main image placeholder techniques compare on cost and benefit, and how to implement them without hurting LCP or adding layout shift.\",\n  \"step\": [\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 1,\n      \"name\": \"Default to aspect ratio plus dominant colour\",\n      \"text\": \"Default to aspect ratio plus dominant colour\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 2,\n      \"name\": \"Use LQIP selectively, as a CSS background\",\n      \"text\": \"For a handful of large images (the hero, a feature image), a tiny blurred preview improves perceived quality.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 3,\n      \"name\": \"Decode BlurHash\u002FThumbHash at build time, not runtime\",\n      \"text\": \"If your data source provides BlurHash strings, decode them to a tiny image or a few gradient stops on the server or at build time, and ship CSS — not a decoder.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 4,\n      \"name\": \"Fade in the real image without layout change\",\n      \"text\": \"Swap or fade the real image over the placeholder within the same box; never change dimensions.\"\n    }\n  ]\n}\n",[1116,1121,1122],{"type":1118},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"TechArticle\",\n  \"headline\": \"LQIP vs BlurHash Placeholders: Choosing an Image Placeholder\",\n  \"description\": \"How the main image placeholder techniques compare on cost and benefit, and how to implement them without hurting LCP or adding layout shift.\",\n  \"datePublished\": \"2026-10-06\",\n  \"dateModified\": \"2026-10-06\",\n  \"author\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"publisher\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"mainEntityOfPage\": {\n    \"@type\": \"WebPage\",\n    \"@id\": \"https:\u002F\u002Ffrontend-performance.com\u002Fimage-media-optimization\u002Fimage-decoding-and-placeholders\u002Flqip-vs-blurhash-placeholders\u002F\"\n  }\n}\n",[1116,1124,1125],{"type":1118},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"BreadcrumbList\",\n  \"itemListElement\": [\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 1,\n      \"name\": \"Home\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 2,\n      \"name\": \"Image & Media Optimization\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fimage-media-optimization\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 3,\n      \"name\": \"Image Decoding & Placeholders\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fimage-media-optimization\u002Fimage-decoding-and-placeholders\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 4,\n      \"name\": \"LQIP vs BlurHash Placeholders\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fimage-media-optimization\u002Fimage-decoding-and-placeholders\u002Flqip-vs-blurhash-placeholders\u002F\"\n    }\n  ]\n}\n",[1127,1128,1129],"style",{},"html pre.shiki code .saISM, html code.shiki .saISM{--shiki-default:#0E1116;--shiki-dark:#F0F3F6;--shiki-light:#0E1116}html pre.shiki code .sZBmE, html code.shiki .sZBmE{--shiki-default:#024C1A;--shiki-dark:#72F088;--shiki-light:#024C1A}html pre.shiki code .sPXB4, html code.shiki .sPXB4{--shiki-default:#023B95;--shiki-dark:#91CBFF;--shiki-light:#023B95}html pre.shiki code .sZ8jY, html code.shiki .sZ8jY{--shiki-default:#032563;--shiki-dark:#ADDCFF;--shiki-light:#032563}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html pre.shiki code .sQw3B, html code.shiki .sQw3B{--shiki-default:#702C00;--shiki-dark:#FFB757;--shiki-light:#702C00}html pre.shiki code .sPARh, html code.shiki .sPARh{--shiki-default:#A0111F;--shiki-dark:#FF9492;--shiki-light:#A0111F}html pre.shiki code .sjfSM, html code.shiki .sjfSM{--shiki-default:#66707B;--shiki-dark:#BDC4CC;--shiki-light:#66707B}html pre.shiki code .smZ65, html code.shiki .smZ65{--shiki-default:#622CBC;--shiki-dark:#DBB7FF;--shiki-light:#622CBC}",{"title":376,"searchDepth":416,"depth":416,"links":1131},[1132,1133,1134,1140,1141,1142,1143,1144,1145,1146],{"id":219,"depth":416,"text":220},{"id":256,"depth":416,"text":257},{"id":363,"depth":416,"text":364,"children":1135},[1136,1137,1138,1139],{"id":368,"depth":474,"text":369},{"id":601,"depth":474,"text":602},{"id":708,"depth":474,"text":709},{"id":783,"depth":474,"text":784},{"id":928,"depth":416,"text":929},{"id":935,"depth":416,"text":936},{"id":950,"depth":416,"text":951},{"id":960,"depth":416,"text":961},{"id":993,"depth":416,"text":994},{"id":1021,"depth":416,"text":1022},{"id":1090,"depth":416,"text":1091},"How the main image placeholder techniques compare on cost and benefit, and how to implement them without hurting LCP or adding layout shift.","md",{"slug":1150,"type":1151,"breadcrumb":1152,"datePublished":1160,"dateModified":1160},"lqip-vs-blurhash-placeholders","article",[1153,1156,1157,1158],{"name":1154,"url":1155},"Home","\u002F",{"name":27,"url":26},{"name":22,"url":21},{"name":5,"url":1159},"\u002Fimage-media-optimization\u002Fimage-decoding-and-placeholders\u002Flqip-vs-blurhash-placeholders\u002F","2026-10-06",true,"\u002Fimage-media-optimization\u002Fimage-decoding-and-placeholders\u002Flqip-vs-blurhash-placeholders",{"title":1164,"description":1165},"LQIP vs BlurHash vs Dominant Colour Placeholders","Compare image placeholders: dominant colour, tiny LQIP previews, BlurHash and ThumbHash. Bytes, JavaScript cost, CLS safety and risk of becoming the LCP element.","image-media-optimization\u002Fimage-decoding-and-placeholders\u002Flqip-vs-blurhash-placeholders\u002Findex","RwEytjRzw7BKGGQm3Edz_7tP44ZEejV30ZU77MZN0r0",[1169,1173],{"title":1170,"path":1171,"stem":1172},"CSS Background Images as LCP Elements","\u002Fimage-media-optimization\u002Fimage-decoding-and-placeholders\u002Fcss-background-images-as-lcp-elements","image-media-optimization\u002Fimage-decoding-and-placeholders\u002Fcss-background-images-as-lcp-elements\u002Findex",{"title":1106,"path":1174,"stem":1175},"\u002Fimage-media-optimization\u002Fimage-decoding-and-placeholders\u002Fusing-decoding-async-and-the-decode-api","image-media-optimization\u002Fimage-decoding-and-placeholders\u002Fusing-decoding-async-and-the-decode-api\u002Findex",1791308079677]