[{"data":1,"prerenderedAt":1000},["ShallowReactive",2],{"content:\u002Frendering-css-performance\u002Flayout-thrashing-and-forced-reflow\u002Ffinding-forced-reflows-in-the-performance-panel":3,"surroundings:\u002Frendering-css-performance\u002Flayout-thrashing-and-forced-reflow\u002Ffinding-forced-reflows-in-the-performance-panel":991},{"id":4,"title":5,"body":6,"description":970,"extension":971,"meta":972,"navigation":984,"path":985,"seo":986,"stem":989,"__hash__":990},"content\u002Frendering-css-performance\u002Flayout-thrashing-and-forced-reflow\u002Ffinding-forced-reflows-in-the-performance-panel\u002Findex.md","Finding Forced Reflows in the Performance Panel",{"type":7,"value":8,"toc":953},"minimark",[9,14,29,41,192,197,225,229,235,241,247,253,257,262,265,269,289,293,296,441,445,448,522,526,529,533,552,615,619,626,775,779,805,809,819,825,831,837,841,853,862,871,880,889,902,911,915,938,943,946,949],[10,11,13],"h1",{"id":12},"how-to-find-forced-reflows-in-the-performance-panel","How to Find Forced Reflows in the Performance Panel",[15,16,17,18,23,24,28],"p",{},"This guide is part of ",[19,20,22],"a",{"href":21},"\u002Frendering-css-performance\u002Flayout-thrashing-and-forced-reflow\u002F","Layout Thrashing & Forced Reflow",", within ",[19,25,27],{"href":26},"\u002Frendering-css-performance\u002F","Rendering & CSS Performance",". A forced reflow happens when JavaScript reads layout information after changing something that invalidated layout. The browser has to stop and compute layout immediately. Chrome's Performance panel detects this and labels it, but the information is spread across the flame chart, the event details and the Bottom-Up view, and the code at fault is often not where the warning first points.",[15,30,31,32,36,37,40],{},"Every forced reflow has two halves: the ",[33,34,35],"strong",{},"write"," that made layout dirty and the ",[33,38,39],{},"read"," that forced it to be computed. DevTools shows the read directly, with a stack trace. Finding the write takes a little more work, and fixing the problem usually means moving one of the two. This guide walks through recording, reading and fixing them.",[15,42,43],{},[44,45,51,52,51,59,51,63,51,66,51,84,51,92,51,98,51,106,51,113,51,118,51,122,51,125,51,129,51,132,51,135,51,138,51,142,51,145,51,148,51,154,51,158,51,161,51,164,51,168,51,171,51,180,51,184,51,188,51],"svg",{"viewBox":46,"width":47,"role":48,"ariaLabel":49,"style":50},"0 0 760 149","100%","img","Steps from recording an interaction to identifying the read, finding the invalidating write and confirming the fix.","height:auto;max-width:760px;display:block;margin:1.75rem auto;font-family:inherit;color:var(--fp-svg-ink)"," ",[53,54],"rect",{"className":55,"x":57,"y":57,"width":47,"height":47,"fill":58},[56],"svg-canvas","0","#ffffff",[60,61,62],"title",{},"Forced reflow investigation workflow",[64,65,49],"desc",{},[67,68,69],"defs",{},[70,71,78],"marker",{"id":72,"viewBox":73,"refX":74,"refY":75,"markerWidth":76,"markerHeight":76,"orient":77},"fad98b5a05","0 0 10 10","9","5","7","auto-start-reverse",[79,80],"path",{"d":81,"fill":82,"style":83},"M0 0 L10 5 L0 10 z","currentColor","fill-opacity:0.7",[53,85],{"x":86,"y":86,"width":87,"height":88,"rx":89,"fill":90,"stroke":82,"style":91},"1","758","147","10","none","stroke-opacity:0.18",[93,94,62],"text",{"x":95,"y":96,"fill":82,"style":97},"28.0","34.0","font-size:16px;font-weight:700",[53,99],{"x":95,"y":100,"width":101,"height":102,"rx":103,"fill":104,"stroke":104,"style":105},"56.0","108.8","71.0","6","#0466c8","fill-opacity:0.14;stroke-opacity:0.9",[93,107,112],{"x":108,"y":109,"fill":82,"style":110,"textAnchor":111},"82.4","78.0","font-size:13px;font-weight:700","middle","Record",[93,114,117],{"x":108,"y":115,"fill":82,"style":116,"textAnchor":111},"96.0","font-size:12px","throttled",[93,119,121],{"x":108,"y":120,"fill":82,"style":116,"textAnchor":111},"112.0","interaction",[53,123],{"x":124,"y":100,"width":101,"height":102,"rx":103,"fill":104,"stroke":104,"style":105},"176.8",[93,126,128],{"x":127,"y":109,"fill":82,"style":110,"textAnchor":111},"231.2","Find warnings",[93,130,131],{"x":127,"y":115,"fill":82,"style":116,"textAnchor":111},"red triangles on",[93,133,134],{"x":127,"y":120,"fill":82,"style":116,"textAnchor":111},"Layout",[53,136],{"x":137,"y":100,"width":101,"height":102,"rx":103,"fill":104,"stroke":104,"style":105},"325.6",[93,139,141],{"x":140,"y":109,"fill":82,"style":110,"textAnchor":111},"380.0","Read stack",[93,143,144],{"x":140,"y":115,"fill":82,"style":116,"textAnchor":111},"which line read",[93,146,147],{"x":140,"y":120,"fill":82,"style":116,"textAnchor":111},"layout",[53,149],{"x":150,"y":100,"width":101,"height":102,"rx":103,"fill":151,"stroke":152,"style":153},"474.4","#ffc300","#b8860b","fill-opacity:0.24;stroke-opacity:0.9",[93,155,157],{"x":156,"y":109,"fill":82,"style":110,"textAnchor":111},"528.8","Find write",[93,159,160],{"x":156,"y":115,"fill":82,"style":116,"textAnchor":111},"what invalidated it",[53,162],{"x":163,"y":100,"width":101,"height":102,"rx":103,"fill":104,"stroke":104,"style":105},"623.2",[93,165,167],{"x":166,"y":109,"fill":82,"style":110,"textAnchor":111},"677.6","Fix + re-record",[93,169,170],{"x":166,"y":115,"fill":82,"style":116,"textAnchor":111},"warning gone",[172,173],"line",{"x1":174,"y1":175,"x2":176,"y2":175,"stroke":82,"strokeWidth":177,"style":178,"markerEnd":179},"136.8","91.5","174.8","1.5","stroke-opacity:0.6","url(#fad98b5a05)",[172,181],{"x1":182,"y1":175,"x2":183,"y2":175,"stroke":82,"strokeWidth":177,"style":178,"markerEnd":179},"285.6","323.6",[172,185],{"x1":186,"y1":175,"x2":187,"y2":175,"stroke":82,"strokeWidth":177,"style":178,"markerEnd":179},"434.4","472.4",[172,189],{"x1":190,"y1":175,"x2":191,"y2":175,"stroke":82,"strokeWidth":177,"style":178,"markerEnd":179},"583.2","621.2",[193,194,196],"h2",{"id":195},"rapid-diagnosis","Rapid Diagnosis",[198,199,200,207,213,219],"ul",{},[201,202,203,206],"li",{},[33,204,205],{},"Record with 4x CPU throttling"," so costs are visible.",[201,208,209,212],{},[33,210,211],{},"Look for purple Layout blocks nested inside yellow script blocks"," in the Main track.",[201,214,215,218],{},[33,216,217],{},"Look for red triangles"," on tasks and Layout events; hover to see \"Forced reflow is a likely performance bottleneck\".",[201,220,221,224],{},[33,222,223],{},"Count Layout events"," inside one task: many thin ones indicate thrashing.",[193,226,228],{"id":227},"root-cause-analysis","Root Cause Analysis",[15,230,231,234],{},[33,232,233],{},"1. A write before a read in the same task."," Style changes, DOM insertions or class toggles followed by geometry reads.",[15,236,237,240],{},[33,238,239],{},"2. Hidden reads."," Helpers and libraries that read layout without it being obvious at the call site.",[15,242,243,246],{},[33,244,245],{},"3. Loops."," Repeated write-read pairs multiply the cost.",[15,248,249,252],{},[33,250,251],{},"4. Large invalidation scope."," Each forced layout covers much of the page when there is no containment.",[193,254,256],{"id":255},"step-by-step-resolution","Step-by-Step Resolution",[258,259,261],"h3",{"id":260},"_1-record-a-focused-trace","1. Record a focused trace",[15,263,264],{},"Open DevTools, select the Performance panel, set CPU throttling to 4x, start recording, perform the single interaction, and stop. Keep traces short so the interaction is easy to find. Enable \"Enable advanced paint instrumentation\" only if you also need paint details; it adds overhead.",[258,266,268],{"id":267},"_2-read-the-forced-reflow-event","2. Read the forced reflow event",[15,270,271,272,275,276,280,281,284,285,288],{},"Click a Layout event with a red triangle. The Summary tab shows \"Forced reflow\" with a ",[33,273,274],{},"stack trace",": the function that read layout (for example ",[277,278,279],"code",{},"getBoundingClientRect"," called from ",[277,282,283],{},"positionTooltip"," at ",[277,286,287],{},"tooltip.js:42","). The event details also show \"Nodes that need layout\" and the layout root, indicating how large the invalidated area was.",[258,290,292],{"id":291},"_3-find-the-write-that-invalidated-layout","3. Find the write that invalidated layout",[15,294,295],{},"Look earlier in the same task for the code that changed styles or DOM: in the flame chart, the calls before the forced layout. Recent Chrome versions show an \"Invalidations\" or \"Layout invalidation\" section listing what triggered it (with stack traces) when advanced instrumentation is enabled.",[297,298,303],"pre",{"className":299,"code":300,"language":301,"meta":302,"style":302},"language-javascript shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","\u002F\u002F Example: the read (line 42) is innocent; the write (line 38) made it costly.\nfunction positionTooltip(tip, anchor) {\n  tip.classList.add('visible');               \u002F\u002F line 38: write — layout dirty\n  const r = anchor.getBoundingClientRect();   \u002F\u002F line 42: read — forced layout\n  tip.style.transform = `translate(${r.left}px, ${r.bottom}px)`;\n}\n\u002F\u002F trade-off: reading the anchor before showing the tooltip avoids the forced\n\u002F\u002F layout, but the tooltip's own size is then unknown until the next frame.\n","javascript","",[277,304,305,313,341,362,386,423,429,435],{"__ignoreMap":302},[306,307,309],"span",{"class":172,"line":308},1,[306,310,312],{"class":311},"sjfSM","\u002F\u002F Example: the read (line 42) is innocent; the write (line 38) made it costly.\n",[306,314,316,320,324,328,332,335,338],{"class":172,"line":315},2,[306,317,319],{"class":318},"sPARh","function",[306,321,323],{"class":322},"smZ65"," positionTooltip",[306,325,327],{"class":326},"saISM","(",[306,329,331],{"class":330},"sQw3B","tip",[306,333,334],{"class":326},", ",[306,336,337],{"class":330},"anchor",[306,339,340],{"class":326},") {\n",[306,342,344,347,350,352,356,359],{"class":172,"line":343},3,[306,345,346],{"class":326},"  tip.classList.",[306,348,349],{"class":322},"add",[306,351,327],{"class":326},[306,353,355],{"class":354},"sZ8jY","'visible'",[306,357,358],{"class":326},");               ",[306,360,361],{"class":311},"\u002F\u002F line 38: write — layout dirty\n",[306,363,365,368,372,375,378,380,383],{"class":172,"line":364},4,[306,366,367],{"class":318},"  const",[306,369,371],{"class":370},"sPXB4"," r",[306,373,374],{"class":318}," =",[306,376,377],{"class":326}," anchor.",[306,379,279],{"class":322},[306,381,382],{"class":326},"();   ",[306,384,385],{"class":311},"\u002F\u002F line 42: read — forced layout\n",[306,387,389,392,395,398,401,404,407,410,412,414,417,420],{"class":172,"line":388},5,[306,390,391],{"class":326},"  tip.style.transform ",[306,393,394],{"class":318},"=",[306,396,397],{"class":354}," `translate(${",[306,399,400],{"class":326},"r",[306,402,403],{"class":354},".",[306,405,406],{"class":326},"left",[306,408,409],{"class":354},"}px, ${",[306,411,400],{"class":326},[306,413,403],{"class":354},[306,415,416],{"class":326},"bottom",[306,418,419],{"class":354},"}px)`",[306,421,422],{"class":326},";\n",[306,424,426],{"class":172,"line":425},6,[306,427,428],{"class":326},"}\n",[306,430,432],{"class":172,"line":431},7,[306,433,434],{"class":311},"\u002F\u002F trade-off: reading the anchor before showing the tooltip avoids the forced\n",[306,436,438],{"class":172,"line":437},8,[306,439,440],{"class":311},"\u002F\u002F layout, but the tooltip's own size is then unknown until the next frame.\n",[258,442,444],{"id":443},"_4-use-bottom-up-to-find-the-worst-offenders","4. Use Bottom-Up to find the worst offenders",[15,446,447],{},"In the Bottom-Up tab, group by Activity and select \"Layout\"; expand to see which functions caused most layout time. This is useful when there are many small forced reflows spread across code.",[15,449,450],{},[44,451,51,454,51,457,51,460,51,462,51,465,51,467,51,471,51,477,51,481,51,484,51,488,51,491,51,495,51,499,51,502,51,505,51,509,51,512,51,515,51,519,51],{"viewBox":452,"width":47,"role":48,"ariaLabel":453,"style":50},"0 0 760 318","The parts of the Performance panel that reveal forced reflows and what each shows.",[53,455],{"className":456,"x":57,"y":57,"width":47,"height":47,"fill":58},[56],[60,458,459],{},"Where to look in the Performance panel",[64,461,453],{},[53,463],{"x":86,"y":86,"width":87,"height":464,"rx":89,"fill":90,"stroke":82,"style":91},"316",[93,466,459],{"x":95,"y":96,"fill":82,"style":97},[53,468],{"x":95,"y":100,"width":469,"height":470,"rx":103,"fill":104,"stroke":104,"style":105},"704.0","40.0",[93,472,476],{"x":473,"y":474,"fill":82,"style":110,"textAnchor":475},"42.0","80.5","start","Main track flame chart",[93,478,480],{"x":479,"y":474,"fill":82,"style":116,"textAnchor":475},"207.7","Purple Layout nested in script; red triangles",[53,482],{"x":95,"y":483,"width":469,"height":470,"rx":103,"fill":104,"stroke":104,"style":105},"106.0",[93,485,487],{"x":473,"y":486,"fill":82,"style":110,"textAnchor":475},"130.5","Summary tab",[93,489,490],{"x":479,"y":486,"fill":82,"style":116,"textAnchor":475},"Forced reflow warning and stack trace of the read",[53,492],{"x":95,"y":493,"width":469,"height":470,"rx":103,"fill":82,"stroke":82,"style":494},"156.0","fill-opacity:0.06;stroke-opacity:0.4",[93,496,498],{"x":473,"y":497,"fill":82,"style":110,"textAnchor":475},"180.5","Layout event details",[93,500,501],{"x":479,"y":497,"fill":82,"style":116,"textAnchor":475},"Nodes needing layout and layout root",[53,503],{"x":95,"y":504,"width":469,"height":470,"rx":103,"fill":82,"stroke":82,"style":494},"206.0",[93,506,508],{"x":473,"y":507,"fill":82,"style":110,"textAnchor":475},"230.5","Invalidations (advanced)",[93,510,511],{"x":479,"y":507,"fill":82,"style":116,"textAnchor":475},"The writes that made layout dirty",[53,513],{"x":95,"y":514,"width":469,"height":470,"rx":103,"fill":151,"stroke":152,"style":153},"256.0",[93,516,518],{"x":473,"y":517,"fill":82,"style":110,"textAnchor":475},"280.5","Bottom-Up by activity",[93,520,521],{"x":479,"y":517,"fill":82,"style":116,"textAnchor":475},"Total layout time by calling function",[193,523,525],{"id":524},"verification","Verification",[15,527,528],{},"After fixing, record the same interaction under the same throttling. The red triangles should disappear, the number of Layout events within the task should drop to one or zero, and the task duration should decrease. Compare the total time of the interaction in the Interactions track, which approximates INP for that interaction.",[193,530,532],{"id":531},"worked-example-a-mega-menu","Worked Example: A Mega Menu",[15,534,535,536,539,540,543,544,547,548,551],{},"A retailer's mega menu took 280ms to open on a mid-range phone. The trace showed 48 forced reflows, each about 5ms, inside ",[277,537,538],{},"alignColumns()",". The stack traces pointed to ",[277,541,542],{},"offsetHeight"," reads; earlier in each loop iteration, ",[277,545,546],{},"column.style.height = ''"," reset the height. The fix split the loop into reset, measure and apply phases, cutting forced reflows to one and the task to 40ms. A second trace then revealed a remaining 25ms layout on the whole document, which ",[277,549,550],{},"contain: content"," on the menu panel reduced to 6ms. INP p75 for menu opening went from 320ms to 130ms.",[15,553,554],{},[44,555,51,558,51,561,51,564,51,566,51,569,51,571,51,578,51,585,51,590,51,594,51,599,51,602,51,606,51,611,51],{"viewBox":556,"width":47,"role":48,"ariaLabel":557,"style":50},"0 0 760 163","Bar chart of task duration and forced reflow count when opening a mega menu before and after restructuring.",[53,559],{"className":560,"x":57,"y":57,"width":47,"height":47,"fill":58},[56],[60,562,563],{},"Mega menu open: before and after the fix",[64,565,557],{},[53,567],{"x":86,"y":86,"width":87,"height":568,"rx":89,"fill":90,"stroke":82,"style":91},"161",[93,570,563],{"x":95,"y":96,"fill":82,"style":97},[93,572,577],{"x":573,"y":574,"fill":82,"style":575,"textAnchor":576},"197.0","70.0","font-size:13px","end","Before (48 forced reflows)",[53,579],{"x":580,"y":100,"width":581,"height":582,"rx":583,"fill":90,"stroke":82,"style":584},"209.0","459.0","19","3","fill-opacity:0.7;stroke-opacity:0.35",[93,586,589],{"x":587,"y":574,"fill":82,"style":588},"674.0","font-size:12px;font-weight:600","280ms",[93,591,593],{"x":573,"y":592,"fill":82,"style":575,"textAnchor":576},"101.0","Phases split (1 forced reflow)",[53,595],{"x":580,"y":596,"width":597,"height":582,"rx":583,"fill":104,"stroke":104,"style":598},"87.0","65.6","fill-opacity:0.55;stroke-opacity:0.9",[93,600,601],{"x":517,"y":592,"fill":82,"style":588},"40ms",[93,603,605],{"x":573,"y":604,"fill":82,"style":575,"textAnchor":576},"132.0","+ contain: content on panel",[53,607],{"x":580,"y":608,"width":609,"height":582,"rx":583,"fill":151,"stroke":152,"style":610},"118.0","34.4","fill-opacity:0.7;stroke-opacity:0.9",[93,612,614],{"x":613,"y":604,"fill":82,"style":588},"249.4","21ms",[193,616,618],{"id":617},"automating-detection","Automating Detection",[15,620,621,622,625],{},"Manual tracing finds individual problems; automation stops new ones. Puppeteer or Playwright can record a trace during scripted interactions, then scan it for Layout events that occur inside a function call and exceed a threshold. A simpler approach uses the Long Animation Frames API in a test page: interactions whose frames show large ",[277,623,624],{},"forcedStyleAndLayoutDuration"," values on script entries indicate forced layout. Failing a CI job when a key interaction exceeds a few milliseconds of forced layout catches regressions introduced by new components and library upgrades before they reach users.",[297,627,629],{"className":299,"code":628,"language":301,"meta":302,"style":302},"\u002F\u002F In a test page: log forced layout time per long animation frame.\nnew PerformanceObserver((list) => {\n  for (const frame of list.getEntries()) {\n    for (const s of frame.scripts) {\n      if (s.forcedStyleAndLayoutDuration > 5) console.warn('forced layout', s.sourceURL, s.sourceFunctionName, s.forcedStyleAndLayoutDuration);\n    }\n  }\n}).observe({ type: 'long-animation-frame', buffered: true });\n\u002F\u002F trade-off: only frames over 50ms are reported, so small forced reflows in fast\n\u002F\u002F frames are missed; use traces for detailed investigation.\n",[277,630,631,636,659,685,702,730,735,740,763,769],{"__ignoreMap":302},[306,632,633],{"class":172,"line":308},[306,634,635],{"class":311},"\u002F\u002F In a test page: log forced layout time per long animation frame.\n",[306,637,638,641,644,647,650,653,656],{"class":172,"line":315},[306,639,640],{"class":318},"new",[306,642,643],{"class":322}," PerformanceObserver",[306,645,646],{"class":326},"((",[306,648,649],{"class":330},"list",[306,651,652],{"class":326},") ",[306,654,655],{"class":318},"=>",[306,657,658],{"class":326}," {\n",[306,660,661,664,667,670,673,676,679,682],{"class":172,"line":343},[306,662,663],{"class":318},"  for",[306,665,666],{"class":326}," (",[306,668,669],{"class":318},"const",[306,671,672],{"class":370}," frame",[306,674,675],{"class":318}," of",[306,677,678],{"class":326}," list.",[306,680,681],{"class":322},"getEntries",[306,683,684],{"class":326},"()) {\n",[306,686,687,690,692,694,697,699],{"class":172,"line":364},[306,688,689],{"class":318},"    for",[306,691,666],{"class":326},[306,693,669],{"class":318},[306,695,696],{"class":370}," s",[306,698,675],{"class":318},[306,700,701],{"class":326}," frame.scripts) {\n",[306,703,704,707,710,713,716,719,722,724,727],{"class":172,"line":388},[306,705,706],{"class":318},"      if",[306,708,709],{"class":326}," (s.forcedStyleAndLayoutDuration ",[306,711,712],{"class":318},">",[306,714,715],{"class":370}," 5",[306,717,718],{"class":326},") console.",[306,720,721],{"class":322},"warn",[306,723,327],{"class":326},[306,725,726],{"class":354},"'forced layout'",[306,728,729],{"class":326},", s.sourceURL, s.sourceFunctionName, s.forcedStyleAndLayoutDuration);\n",[306,731,732],{"class":172,"line":425},[306,733,734],{"class":326},"    }\n",[306,736,737],{"class":172,"line":431},[306,738,739],{"class":326},"  }\n",[306,741,742,745,748,751,754,757,760],{"class":172,"line":437},[306,743,744],{"class":326},"}).",[306,746,747],{"class":322},"observe",[306,749,750],{"class":326},"({ type: ",[306,752,753],{"class":354},"'long-animation-frame'",[306,755,756],{"class":326},", buffered: ",[306,758,759],{"class":370},"true",[306,761,762],{"class":326}," });\n",[306,764,766],{"class":172,"line":765},9,[306,767,768],{"class":311},"\u002F\u002F trade-off: only frames over 50ms are reported, so small forced reflows in fast\n",[306,770,772],{"class":172,"line":771},10,[306,773,774],{"class":311},"\u002F\u002F frames are missed; use traces for detailed investigation.\n",[193,776,778],{"id":777},"common-mistakes","Common Mistakes",[198,780,781,787,793,799],{},[201,782,783,786],{},[33,784,785],{},"Fixing the read instead of the order."," Removing one read often just moves the forced layout to the next read.",[201,788,789,792],{},[33,790,791],{},"Recording without throttling."," Small costs hide on fast machines.",[201,794,795,798],{},[33,796,797],{},"Ignoring library code."," Stack traces point into dependencies; the fix may be configuration or replacement.",[201,800,801,804],{},[33,802,803],{},"Recording long sessions."," Interactions get lost among unrelated activity.",[193,806,808],{"id":807},"edge-cases","Edge Cases",[15,810,811,814,815,818],{},[33,812,813],{},"Forced style recalculation."," Reads like ",[277,816,817],{},"getComputedStyle()"," for non-layout properties force style recalculation without layout; they appear as Recalculate Style inside script.",[15,820,821,824],{},[33,822,823],{},"Iframes."," Forced reflows in iframes appear in their own frame tracks; select the right one.",[15,826,827,830],{},[33,828,829],{},"Minified code."," Without source maps, stack traces point to minified functions; enable source maps in staging builds.",[15,832,833,836],{},[33,834,835],{},"Extensions."," Browser extensions can inject scripts that force layout; profile in a clean profile or incognito window.",[193,838,840],{"id":839},"faq","FAQ",[842,843,846,850],"details",{"className":844},[845],"faq-item",[847,848,849],"summary",{},"What does \"Forced reflow is a likely performance bottleneck\" mean?",[15,851,852],{},"Chrome detected a layout computed synchronously because script read layout information while layout was dirty. The stack trace shows where the read happened.",[842,854,856,859],{"className":855},[845],[847,857,858],{},"How many forced reflows are acceptable?",[15,860,861],{},"One per interaction is common and usually fine. Many in the same task, or a single one on a very large DOM, are worth fixing.",[842,863,865,868],{"className":864},[845],[847,866,867],{},"Why does the stack trace point to a library?",[15,869,870],{},"The library is reading layout. Check whether your code wrote styles just before calling it, whether the library has options to avoid measuring, or whether a CSS alternative exists.",[842,872,874,877],{"className":873},[845],[847,875,876],{},"Can Lighthouse detect forced reflows?",[15,878,879],{},"Lighthouse reports long tasks and main-thread work, and newer versions include forced reflow insights in performance traces. DevTools traces remain the most detailed source.",[842,881,883,886],{"className":882},[845],[847,884,885],{},"Does Firefox show forced reflows?",[15,887,888],{},"Firefox Profiler shows synchronous reflows with stack traces as well, under layout markers. The concepts are the same.",[842,890,892,895],{"className":891},[845],[847,893,894],{},"What is the Layout root?",[15,896,897,898,901],{},"The element from which layout was recomputed. A root of ",[277,899,900],{},"#document"," means the whole page; a smaller root means containment or the browser limited the work.",[842,903,905,908],{"className":904},[845],[847,906,907],{},"Should I profile on real devices?",[15,909,910],{},"Yes, for final numbers. Remote debugging an Android phone gives the same Performance panel with real CPU costs, which are often higher than throttled desktop estimates.",[193,912,914],{"id":913},"related","Related",[198,916,917,924,931],{},[201,918,919,923],{},[19,920,922],{"href":921},"\u002Frendering-css-performance\u002Flayout-thrashing-and-forced-reflow\u002Fbatching-dom-reads-and-writes\u002F","Batching DOM reads and writes"," — the standard fix.",[201,925,926,930],{},[19,927,929],{"href":928},"\u002Fcore-web-vitals-measurement\u002Fprofiling-event-handlers-for-inp\u002F","Profiling event handlers for INP"," — broader handler profiling.",[201,932,933,937],{},[19,934,936],{"href":935},"\u002Frendering-css-performance\u002Fcss-containment-and-content-visibility\u002Fisolating-widgets-with-css-contain\u002F","Isolating widgets with CSS contain"," — reduce the cost of each layout.",[939,940,942],"script",{"type":941},"application\u002Fld+json","\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"HowTo\",\n  \"name\": \"How to Find Forced Reflows in the Performance Panel\",\n  \"description\": \"A practical walkthrough of finding forced reflows and layout thrashing in Chrome DevTools, tracing them to the code responsible, and confirming the fix.\",\n  \"step\": [\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 1,\n      \"name\": \"Record a focused trace\",\n      \"text\": \"Open DevTools, select the Performance panel, set CPU throttling to 4x, start recording, perform the single interaction, and stop.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 2,\n      \"name\": \"Read the forced reflow event\",\n      \"text\": \"Click a Layout event with a red triangle.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 3,\n      \"name\": \"Find the write that invalidated layout\",\n      \"text\": \"Look earlier in the same task for the code that changed styles or DOM: in the flame chart, the calls before the forced layout.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 4,\n      \"name\": \"Use Bottom-Up to find the worst offenders\",\n      \"text\": \"In the Bottom-Up tab, group by Activity and select \\\"Layout\\\"; expand to see which functions caused most layout time.\"\n    }\n  ]\n}\n",[939,944,945],{"type":941},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"TechArticle\",\n  \"headline\": \"How to Find Forced Reflows in the Performance Panel\",\n  \"description\": \"A practical walkthrough of finding forced reflows and layout thrashing in Chrome DevTools, tracing them to the code responsible, and confirming the fix.\",\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\u002Frendering-css-performance\u002Flayout-thrashing-and-forced-reflow\u002Ffinding-forced-reflows-in-the-performance-panel\u002F\"\n  }\n}\n",[939,947,948],{"type":941},"\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\": \"Rendering & CSS Performance\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Frendering-css-performance\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 3,\n      \"name\": \"Layout Thrashing & Forced Reflow\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Frendering-css-performance\u002Flayout-thrashing-and-forced-reflow\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 4,\n      \"name\": \"Finding Forced Reflows in the Performance Panel\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Frendering-css-performance\u002Flayout-thrashing-and-forced-reflow\u002Ffinding-forced-reflows-in-the-performance-panel\u002F\"\n    }\n  ]\n}\n",[950,951,952],"style",{},"html pre.shiki code .sjfSM, html code.shiki .sjfSM{--shiki-default:#66707B;--shiki-dark:#BDC4CC;--shiki-light:#66707B}html pre.shiki code .sPARh, html code.shiki .sPARh{--shiki-default:#A0111F;--shiki-dark:#FF9492;--shiki-light:#A0111F}html pre.shiki code .smZ65, html code.shiki .smZ65{--shiki-default:#622CBC;--shiki-dark:#DBB7FF;--shiki-light:#622CBC}html pre.shiki code .saISM, html code.shiki .saISM{--shiki-default:#0E1116;--shiki-dark:#F0F3F6;--shiki-light:#0E1116}html pre.shiki code .sQw3B, html code.shiki .sQw3B{--shiki-default:#702C00;--shiki-dark:#FFB757;--shiki-light:#702C00}html pre.shiki code .sZ8jY, html code.shiki .sZ8jY{--shiki-default:#032563;--shiki-dark:#ADDCFF;--shiki-light:#032563}html pre.shiki code .sPXB4, html code.shiki .sPXB4{--shiki-default:#023B95;--shiki-dark:#91CBFF;--shiki-light:#023B95}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}",{"title":302,"searchDepth":315,"depth":315,"links":954},[955,956,957,963,964,965,966,967,968,969],{"id":195,"depth":315,"text":196},{"id":227,"depth":315,"text":228},{"id":255,"depth":315,"text":256,"children":958},[959,960,961,962],{"id":260,"depth":343,"text":261},{"id":267,"depth":343,"text":268},{"id":291,"depth":343,"text":292},{"id":443,"depth":343,"text":444},{"id":524,"depth":315,"text":525},{"id":531,"depth":315,"text":532},{"id":617,"depth":315,"text":618},{"id":777,"depth":315,"text":778},{"id":807,"depth":315,"text":808},{"id":839,"depth":315,"text":840},{"id":913,"depth":315,"text":914},"A practical walkthrough of finding forced reflows and layout thrashing in Chrome DevTools, tracing them to the code responsible, and confirming the fix.","md",{"slug":973,"type":974,"breadcrumb":975,"datePublished":983,"dateModified":983},"finding-forced-reflows-in-the-performance-panel","article",[976,979,980,981],{"name":977,"url":978},"Home","\u002F",{"name":27,"url":26},{"name":22,"url":21},{"name":5,"url":982},"\u002Frendering-css-performance\u002Flayout-thrashing-and-forced-reflow\u002Ffinding-forced-reflows-in-the-performance-panel\u002F","2026-10-06",true,"\u002Frendering-css-performance\u002Flayout-thrashing-and-forced-reflow\u002Ffinding-forced-reflows-in-the-performance-panel",{"title":987,"description":988},"Finding Forced Reflows in the Chrome Performance Panel","Locate forced synchronous layouts in Chrome DevTools: read the Forced reflow warning, follow its stack trace, find the invalidating write, and confirm the fix.","rendering-css-performance\u002Flayout-thrashing-and-forced-reflow\u002Ffinding-forced-reflows-in-the-performance-panel\u002Findex","t7p24b9LpMQRs-8S8AIO6ymvKtXazB6Pdri2cU1mT0k",[992,996],{"title":993,"path":994,"stem":995,"children":-1},"Batching DOM Reads and Writes","\u002Frendering-css-performance\u002Flayout-thrashing-and-forced-reflow\u002Fbatching-dom-reads-and-writes","rendering-css-performance\u002Flayout-thrashing-and-forced-reflow\u002Fbatching-dom-reads-and-writes\u002Findex",{"title":997,"path":998,"stem":999,"children":-1},"ResizeObserver vs Resize and Scroll Handlers","\u002Frendering-css-performance\u002Flayout-thrashing-and-forced-reflow\u002Fresizeobserver-vs-resize-and-scroll-handlers","rendering-css-performance\u002Flayout-thrashing-and-forced-reflow\u002Fresizeobserver-vs-resize-and-scroll-handlers\u002Findex",1791308072309]