[{"data":1,"prerenderedAt":881},["ShallowReactive",2],{"content:\u002Frendering-css-performance\u002Fcritical-css-and-render-blocking-resources\u002Fruntime-css-in-js-performance-cost":3,"surroundings:\u002Frendering-css-performance\u002Fcritical-css-and-render-blocking-resources\u002Fruntime-css-in-js-performance-cost":872},{"id":4,"title":5,"body":6,"description":852,"extension":853,"meta":854,"navigation":866,"path":867,"seo":868,"stem":870,"__hash__":871},"content\u002Frendering-css-performance\u002Fcritical-css-and-render-blocking-resources\u002Fruntime-css-in-js-performance-cost\u002Findex.md","Runtime CSS-in-JS Performance Cost",{"type":7,"value":8,"toc":834},"minimark",[9,14,29,32,127,132,161,165,171,177,183,189,193,198,201,205,354,358,361,365,368,507,511,514,518,521,650,654,657,661,664,668,694,698,704,710,716,722,726,738,747,756,765,774,783,792,796,819,824,827,830],[10,11,13],"h1",{"id":12},"the-performance-cost-of-runtime-css-in-js","The Performance Cost of Runtime CSS-in-JS",[15,16,17,18,23,24,28],"p",{},"This guide is part of ",[19,20,22],"a",{"href":21},"\u002Frendering-css-performance\u002Fcritical-css-and-render-blocking-resources\u002F","Critical CSS & Render-Blocking Resources",", within ",[19,25,27],{"href":26},"\u002Frendering-css-performance\u002F","Rendering & CSS Performance",". Runtime CSS-in-JS libraries — styled-components, Emotion and similar — let developers write styles inside components, with props-based dynamic values. They work by generating CSS during rendering: each styled component serialises its style object or template string, hashes it into a class name, and injects a rule into a style sheet if it has not been seen before. On the server, the collected styles are inlined into the HTML.",[15,30,31],{},"That convenience has costs that show up mainly on the client: the library's JavaScript must download and run; serialisation and hashing run during every render of styled components; injecting new rules triggers style recalculation across the document; and during hydration, the same work runs again for the whole page. On slower devices, these costs are measurable in total blocking time and INP. Many teams have migrated to zero-runtime approaches that extract static CSS at build time, keeping component-scoped authoring without the runtime work.",[15,33,34],{},[35,36,42,43,42,50,42,54,42,57,42,66,42,72,42,79,42,87,42,92,42,96,42,102,42,106,42,110,42,117,42,121,42],"svg",{"viewBox":37,"width":38,"role":39,"ariaLabel":40,"style":41},"0 0 760 189","100%","img","Bar chart comparing main-thread rendering time for the same grid styled with runtime CSS-in-JS, a zero-runtime library and CSS modules.","height:auto;max-width:760px;display:block;margin:1.75rem auto;font-family:inherit;color:var(--fp-svg-ink)"," ",[44,45],"rect",{"className":46,"x":48,"y":48,"width":38,"height":38,"fill":49},[47],"svg-canvas","0","#ffffff",[51,52,53],"title",{},"Main-thread time rendering a 400-item product grid",[55,56,40],"desc",{},[44,58],{"x":59,"y":59,"width":60,"height":61,"rx":62,"fill":63,"stroke":64,"style":65},"1","758","187","10","none","currentColor","stroke-opacity:0.18",[67,68,53],"text",{"x":69,"y":70,"fill":64,"style":71},"28.0","34.0","font-size:16px;font-weight:700",[67,73,78],{"x":74,"y":75,"fill":64,"style":76,"textAnchor":77},"171.0","70.0","font-size:13px","end","Runtime CSS-in-JS",[44,80],{"x":81,"y":82,"width":83,"height":84,"rx":85,"fill":63,"stroke":64,"style":86},"183.0","56.0","485.0","19","3","fill-opacity:0.7;stroke-opacity:0.35",[67,88,91],{"x":89,"y":75,"fill":64,"style":90},"674.0","font-size:12px;font-weight:600","186ms",[67,93,95],{"x":74,"y":94,"fill":64,"style":76,"textAnchor":77},"101.0","Zero-runtime (extracted)",[44,97],{"x":81,"y":98,"width":99,"height":84,"rx":85,"fill":100,"stroke":100,"style":101},"87.0","292.1","#0466c8","fill-opacity:0.55;stroke-opacity:0.9",[67,103,105],{"x":104,"y":94,"fill":64,"style":90},"481.0","112ms",[67,107,109],{"x":74,"y":108,"fill":64,"style":76,"textAnchor":77},"132.0","CSS modules",[44,111],{"x":81,"y":112,"width":113,"height":84,"rx":85,"fill":114,"stroke":115,"style":116},"118.0","281.6","#ffc300","#b8860b","fill-opacity:0.7;stroke-opacity:0.9",[67,118,120],{"x":119,"y":108,"fill":64,"style":90},"470.6","108ms",[67,122,126],{"x":69,"y":123,"fill":124,"style":125},"167.0","#51617a","font-size:12.5px","Mid-range phone profile; same React components and markup.",[128,129,131],"h2",{"id":130},"rapid-diagnosis","Rapid Diagnosis",[133,134,135,143,149,155],"ul",{},[136,137,138,142],"li",{},[139,140,141],"strong",{},"Check bundle composition"," for styled-components, Emotion or similar packages and their size.",[136,144,145,148],{},[139,146,147],{},"Record a Performance profile"," of hydration and a typical interaction; look for library functions (serialise, hash, insertRule) in the flame chart.",[136,150,151,154],{},[139,152,153],{},"Look for frequent style recalculations"," right after component renders.",[136,156,157,160],{},[139,158,159],{},"Check for dynamic styles driven by props"," that change often (for example, on hover or scroll), which create new rules repeatedly.",[128,162,164],{"id":163},"root-cause-analysis","Root Cause Analysis",[15,166,167,170],{},[139,168,169],{},"1. Style generation at render time."," Each render of a styled component computes its styles.",[15,172,173,176],{},[139,174,175],{},"2. Rule injection."," Inserting new CSS rules invalidates styles and triggers recalculation.",[15,178,179,182],{},[139,180,181],{},"3. Hydration doubles the work."," The client recomputes styles that the server already rendered.",[15,184,185,188],{},[139,186,187],{},"4. Prop-driven styles."," Values that change frequently generate many unique classes.",[128,190,192],{"id":191},"step-by-step-resolution","Step-by-Step Resolution",[194,195,197],"h3",{"id":196},"_1-measure-the-cost-in-your-app","1. Measure the cost in your app",[15,199,200],{},"Profile hydration and key interactions with 4x CPU throttling. Sum self time in the library's functions and the style recalculations that follow injection. This gives a concrete budget for the migration decision.",[194,202,204],{"id":203},"_2-move-frequently-changing-values-to-css-variables","2. Move frequently changing values to CSS variables",[206,207,212],"pre",{"className":208,"code":209,"language":210,"meta":211,"style":211},"language-javascript shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","\u002F\u002F Instead of generating a new class per progress value:\nconst Bar = styled.div`width: ${(p) => p.pct}%;`;\n\u002F\u002F Set a CSS variable inline and keep one static rule:\nconst Bar = styled.div`width: var(--pct);`;\n\u003CBar style={{ '--pct': `${pct}%` }} \u002F>\n\u002F\u002F trade-off: inline custom properties are not visible in the stylesheet, which\n\u002F\u002F can make debugging slightly harder, but avoid rule churn completely.\n","javascript","",[213,214,215,224,276,282,300,342,348],"code",{"__ignoreMap":211},[216,217,220],"span",{"class":218,"line":219},"line",1,[216,221,223],{"class":222},"sjfSM","\u002F\u002F Instead of generating a new class per progress value:\n",[216,225,227,231,235,238,242,246,250,253,255,258,261,264,267,270,273],{"class":218,"line":226},2,[216,228,230],{"class":229},"sPARh","const",[216,232,234],{"class":233},"sPXB4"," Bar",[216,236,237],{"class":229}," =",[216,239,241],{"class":240},"saISM"," styled.",[216,243,245],{"class":244},"smZ65","div",[216,247,249],{"class":248},"sZ8jY","`width: ${",[216,251,252],{"class":248},"(",[216,254,15],{"class":233},[216,256,257],{"class":248},") ",[216,259,260],{"class":229},"=>",[216,262,263],{"class":240}," p",[216,265,266],{"class":248},".",[216,268,269],{"class":240},"pct",[216,271,272],{"class":248},"}%;`",[216,274,275],{"class":240},";\n",[216,277,279],{"class":218,"line":278},3,[216,280,281],{"class":222},"\u002F\u002F Set a CSS variable inline and keep one static rule:\n",[216,283,285,287,289,291,293,295,298],{"class":218,"line":284},4,[216,286,230],{"class":229},[216,288,234],{"class":233},[216,290,237],{"class":229},[216,292,241],{"class":240},[216,294,245],{"class":244},[216,296,297],{"class":248},"`width: var(--pct);`",[216,299,275],{"class":240},[216,301,303,306,310,313,316,319,322,325,328,330,333,336,339],{"class":218,"line":302},5,[216,304,305],{"class":240},"\u003C",[216,307,309],{"class":308},"sZBmE","Bar",[216,311,312],{"class":233}," style",[216,314,315],{"class":229},"={",[216,317,318],{"class":240},"{ ",[216,320,321],{"class":248},"'--pct'",[216,323,324],{"class":240},": ",[216,326,327],{"class":248},"`${",[216,329,269],{"class":240},[216,331,332],{"class":248},"}%`",[216,334,335],{"class":240}," }",[216,337,338],{"class":229},"}",[216,340,341],{"class":240}," \u002F>\n",[216,343,345],{"class":218,"line":344},6,[216,346,347],{"class":222},"\u002F\u002F trade-off: inline custom properties are not visible in the stylesheet, which\n",[216,349,351],{"class":218,"line":350},7,[216,352,353],{"class":222},"\u002F\u002F can make debugging slightly harder, but avoid rule churn completely.\n",[194,355,357],{"id":356},"_3-hoist-static-styles","3. Hoist static styles",[15,359,360],{},"Define styled components at module level (not inside render functions) and keep variants as a small set of static classes rather than arbitrary prop interpolation.",[194,362,364],{"id":363},"_4-migrate-to-zero-runtime-styling","4. Migrate to zero-runtime styling",[15,366,367],{},"Libraries such as vanilla-extract, Linaria, Panda CSS and StyleX extract CSS at build time. CSS modules and plain CSS are other options. Migrate incrementally: start with components that render most often (list rows, cards, buttons).",[15,369,370],{},[35,371,42,374,42,377,42,380,42,382,42,385,42,387,42,392,42,399,42,403,42,408,42,411,42,415,42,418,42,422,42,426,42,429,42,432,42,436,42,439,42,442,42,444,42,447,42,450,42,454,42,456,42,458,42,460,42,463,42,465,42,467,42,470,42,473,42,475,42,477,42,479,42,481,42,483,42,486,42,489,42,493,42,495,42,497,42,499,42,502,42,504,42],{"viewBox":372,"width":38,"role":39,"ariaLabel":373,"style":41},"0 0 760 228","Comparison of runtime CSS-in-JS, zero-runtime CSS-in-JS and CSS modules on runtime cost, dynamic styling and authoring.",[44,375],{"className":376,"x":48,"y":48,"width":38,"height":38,"fill":49},[47],[51,378,379],{},"Styling approaches compared",[55,381,373],{},[44,383],{"x":59,"y":59,"width":60,"height":384,"rx":62,"fill":63,"stroke":64,"style":65},"226",[67,386,379],{"x":69,"y":70,"fill":64,"style":71},[44,388],{"x":69,"y":82,"width":389,"height":390,"rx":48,"fill":64,"stroke":64,"style":391},"159.0","30.0","fill-opacity:0.06;stroke-opacity:0.4",[67,393,398],{"x":394,"y":395,"fill":64,"style":396,"textAnchor":397},"38.0","75.5","font-size:12.5px;font-weight:700","start","Approach",[44,400],{"x":401,"y":82,"width":402,"height":390,"rx":48,"fill":64,"stroke":64,"style":391},"187.0","181.7",[67,404,407],{"x":405,"y":395,"fill":64,"style":396,"textAnchor":406},"277.9","middle","Runtime cost",[44,409],{"x":410,"y":82,"width":402,"height":390,"rx":48,"fill":64,"stroke":64,"style":391},"368.7",[67,412,414],{"x":413,"y":395,"fill":64,"style":396,"textAnchor":406},"459.5","Dynamic values",[44,416],{"x":417,"y":82,"width":402,"height":390,"rx":48,"fill":64,"stroke":64,"style":391},"550.3",[67,419,421],{"x":420,"y":395,"fill":64,"style":396,"textAnchor":406},"641.2","Co-location",[44,423],{"x":69,"y":424,"width":389,"height":390,"rx":48,"fill":63,"stroke":64,"style":425},"86.0","stroke-opacity:0.35",[67,427,78],{"x":394,"y":428,"fill":64,"style":396,"textAnchor":397},"105.5",[44,430],{"x":401,"y":424,"width":402,"height":390,"rx":48,"fill":114,"stroke":115,"style":431},"fill-opacity:0.24;stroke-opacity:0.9",[67,433,435],{"x":405,"y":428,"fill":64,"style":434,"textAnchor":406},"font-size:12px","serialise + inject",[44,437],{"x":410,"y":424,"width":402,"height":390,"rx":48,"fill":100,"stroke":100,"style":438},"fill-opacity:0.14;stroke-opacity:0.9",[67,440,441],{"x":413,"y":428,"fill":64,"style":434,"textAnchor":406},"any prop",[44,443],{"x":417,"y":424,"width":402,"height":390,"rx":48,"fill":100,"stroke":100,"style":438},[67,445,446],{"x":420,"y":428,"fill":64,"style":434,"textAnchor":406},"in component",[44,448],{"x":69,"y":449,"width":389,"height":390,"rx":48,"fill":63,"stroke":64,"style":425},"116.0",[67,451,453],{"x":394,"y":452,"fill":64,"style":396,"textAnchor":397},"135.5","Zero-runtime CSS-in-JS",[44,455],{"x":401,"y":449,"width":402,"height":390,"rx":48,"fill":100,"stroke":100,"style":438},[67,457,63],{"x":405,"y":452,"fill":64,"style":434,"textAnchor":406},[44,459],{"x":410,"y":449,"width":402,"height":390,"rx":48,"fill":64,"stroke":64,"style":391},[67,461,462],{"x":413,"y":452,"fill":64,"style":434,"textAnchor":406},"via CSS variables",[44,464],{"x":417,"y":449,"width":402,"height":390,"rx":48,"fill":100,"stroke":100,"style":438},[67,466,446],{"x":420,"y":452,"fill":64,"style":434,"textAnchor":406},[44,468],{"x":69,"y":469,"width":389,"height":390,"rx":48,"fill":63,"stroke":64,"style":425},"146.0",[67,471,109],{"x":394,"y":472,"fill":64,"style":396,"textAnchor":397},"165.5",[44,474],{"x":401,"y":469,"width":402,"height":390,"rx":48,"fill":100,"stroke":100,"style":438},[67,476,63],{"x":405,"y":472,"fill":64,"style":434,"textAnchor":406},[44,478],{"x":410,"y":469,"width":402,"height":390,"rx":48,"fill":64,"stroke":64,"style":391},[67,480,462],{"x":413,"y":472,"fill":64,"style":434,"textAnchor":406},[44,482],{"x":417,"y":469,"width":402,"height":390,"rx":48,"fill":64,"stroke":64,"style":391},[67,484,485],{"x":420,"y":472,"fill":64,"style":434,"textAnchor":406},"sibling file",[44,487],{"x":69,"y":488,"width":389,"height":390,"rx":48,"fill":63,"stroke":64,"style":425},"176.0",[67,490,492],{"x":394,"y":491,"fill":64,"style":396,"textAnchor":397},"195.5","Utility classes",[44,494],{"x":401,"y":488,"width":402,"height":390,"rx":48,"fill":100,"stroke":100,"style":438},[67,496,63],{"x":405,"y":491,"fill":64,"style":434,"textAnchor":406},[44,498],{"x":410,"y":488,"width":402,"height":390,"rx":48,"fill":64,"stroke":64,"style":391},[67,500,501],{"x":413,"y":491,"fill":64,"style":434,"textAnchor":406},"class switching",[44,503],{"x":417,"y":488,"width":402,"height":390,"rx":48,"fill":100,"stroke":100,"style":438},[67,505,506],{"x":420,"y":491,"fill":64,"style":434,"textAnchor":406},"in markup",[128,508,510],{"id":509},"verification","Verification",[15,512,513],{},"Compare profiles before and after: scripting time during hydration and interactions should drop, and style recalculation after renders should shrink. Check JavaScript bundle size for the removed library. In the field, compare INP p75 and TBT on affected templates.",[128,515,517],{"id":516},"worked-example-an-e-commerce-product-listing","Worked Example: An E-commerce Product Listing",[15,519,520],{},"An e-commerce React app used a runtime CSS-in-JS library for all components. Profiling a category page with 48 product cards on a mid-range phone showed 140ms of hydration time inside style serialisation and injection, and filter interactions spent 60ms per change regenerating classes for cards with price-dependent styles. The team moved price-based styling to CSS variables and migrated card, button and grid components to a zero-runtime library. Hydration TBT fell by 180ms, INP p75 on category pages improved from 290ms to 210ms, and the JavaScript bundle shrank by 13KB compressed.",[15,522,523],{},[35,524,42,527,42,530,42,533,42,535,42,552,42,555,42,557,42,562,42,568,42,572,42,576,42,579,42,583,42,586,42,589,42,592,42,596,42,599,42,601,42,604,42,608,42,612,42,616,42,620,42,623,42,627,42,630,42,638,42,642,42,646,42],{"viewBox":525,"width":38,"role":39,"ariaLabel":526,"style":41},"0 0 760 166","Order of steps for migrating from runtime CSS-in-JS to zero-runtime styling with minimal risk.",[44,528],{"className":529,"x":48,"y":48,"width":38,"height":38,"fill":49},[47],[51,531,532],{},"Incremental migration away from runtime styles",[55,534,526],{},[536,537,538],"defs",{},[539,540,547],"marker",{"id":541,"viewBox":542,"refX":543,"refY":544,"markerWidth":545,"markerHeight":545,"orient":546},"fa04a639a1","0 0 10 10","9","5","7","auto-start-reverse",[548,549],"path",{"d":550,"fill":64,"style":551},"M0 0 L10 5 L0 10 z","fill-opacity:0.7",[44,553],{"x":59,"y":59,"width":60,"height":554,"rx":62,"fill":63,"stroke":64,"style":65},"164",[67,556,532],{"x":69,"y":70,"fill":64,"style":71},[44,558],{"x":69,"y":82,"width":559,"height":560,"rx":561,"fill":100,"stroke":100,"style":438},"108.8","88.0","6",[67,563,567],{"x":564,"y":565,"fill":64,"style":566,"textAnchor":406},"82.4","78.0","font-size:13px;font-weight:700","Profile",[67,569,571],{"x":564,"y":570,"fill":64,"style":434,"textAnchor":406},"96.0","find hot",[67,573,575],{"x":564,"y":574,"fill":64,"style":434,"textAnchor":406},"112.0","components",[44,577],{"x":578,"y":82,"width":559,"height":560,"rx":561,"fill":100,"stroke":100,"style":438},"176.8",[67,580,582],{"x":581,"y":565,"fill":64,"style":566,"textAnchor":406},"231.2","CSS variables",[67,584,585],{"x":581,"y":570,"fill":64,"style":434,"textAnchor":406},"for dynamic",[67,587,588],{"x":581,"y":574,"fill":64,"style":434,"textAnchor":406},"values",[44,590],{"x":591,"y":82,"width":559,"height":560,"rx":561,"fill":100,"stroke":100,"style":438},"325.6",[67,593,595],{"x":594,"y":565,"fill":64,"style":566,"textAnchor":406},"380.0","Hoist",[67,597,598],{"x":594,"y":570,"fill":64,"style":434,"textAnchor":406},"static styled",[67,600,575],{"x":594,"y":574,"fill":64,"style":434,"textAnchor":406},[44,602],{"x":603,"y":82,"width":559,"height":560,"rx":561,"fill":114,"stroke":115,"style":431},"474.4",[67,605,607],{"x":606,"y":565,"fill":64,"style":566,"textAnchor":406},"528.8","Migrate hot",[67,609,611],{"x":606,"y":610,"fill":64,"style":566,"textAnchor":406},"95.0","paths",[67,613,615],{"x":606,"y":614,"fill":64,"style":434,"textAnchor":406},"113.0","cards, rows,",[67,617,619],{"x":606,"y":618,"fill":64,"style":434,"textAnchor":406},"129.0","buttons",[44,621],{"x":622,"y":82,"width":559,"height":560,"rx":561,"fill":100,"stroke":100,"style":438},"623.2",[67,624,626],{"x":625,"y":565,"fill":64,"style":566,"textAnchor":406},"677.6","Remove library",[67,628,629],{"x":625,"y":570,"fill":64,"style":434,"textAnchor":406},"when unused",[218,631],{"x1":632,"y1":633,"x2":634,"y2":633,"stroke":64,"strokeWidth":635,"style":636,"markerEnd":637},"136.8","100.0","174.8","1.5","stroke-opacity:0.6","url(#fa04a639a1)",[218,639],{"x1":640,"y1":633,"x2":641,"y2":633,"stroke":64,"strokeWidth":635,"style":636,"markerEnd":637},"285.6","323.6",[218,643],{"x1":644,"y1":633,"x2":645,"y2":633,"stroke":64,"strokeWidth":635,"style":636,"markerEnd":637},"434.4","472.4",[218,647],{"x1":648,"y1":633,"x2":649,"y2":633,"stroke":64,"strokeWidth":635,"style":636,"markerEnd":637},"583.2","621.2",[128,651,653],{"id":652},"server-components-and-streaming","Server Components and Streaming",[15,655,656],{},"React Server Components and streaming SSR change the picture. Runtime CSS-in-JS libraries that rely on React context for style collection need special support for server components and streaming, and some do not support server components at all. Zero-runtime approaches emit plain CSS files and work naturally with streaming and server components. If you are planning a move to the App Router or a similar architecture, factor styling into the migration — it is often the hardest dependency to change later.",[128,658,660],{"id":659},"estimating-the-benefit-before-migrating","Estimating the Benefit Before Migrating",[15,662,663],{},"A migration is a significant investment, so estimate the benefit first. Pick the most frequently rendered component on a key page — a product card, a table row, a list item — and reimplement it with CSS modules or a zero-runtime library on a branch. Profile both versions on the same page with CPU throttling, rendering the full list and performing a typical interaction such as filtering. The difference in scripting and style recalculation time, multiplied by how often that component renders across the app, gives a realistic picture of the gain. If the difference is under a few milliseconds per interaction on a mid-range device, the migration is probably not your highest-value performance work; if it is tens of milliseconds, it likely is.",[128,665,667],{"id":666},"common-mistakes","Common Mistakes",[133,669,670,676,682,688],{},[136,671,672,675],{},[139,673,674],{},"Defining styled components inside render."," A new component type on every render, with new styles each time.",[136,677,678,681],{},[139,679,680],{},"Interpolating frequently changing values."," Endless rule generation.",[136,683,684,687],{},[139,685,686],{},"Assuming SSR removes the cost."," Hydration recomputes styles on the client.",[136,689,690,693],{},[139,691,692],{},"Big-bang migration."," Rewriting every component at once; migrate hot paths first.",[128,695,697],{"id":696},"edge-cases","Edge Cases",[15,699,700,703],{},[139,701,702],{},"Theming."," Runtime themes can be replaced with CSS custom properties set on a root element, which zero-runtime libraries support well.",[15,705,706,709],{},[139,707,708],{},"Design systems shared across apps."," Publish the design system with extracted CSS so consuming apps do not inherit the runtime.",[15,711,712,715],{},[139,713,714],{},"Critical CSS."," Runtime libraries inline styles for server-rendered components, which acts like critical CSS; after migration, ensure extracted CSS is inlined or loaded appropriately.",[15,717,718,721],{},[139,719,720],{},"Animation libraries."," Some animation libraries generate styles at runtime too; profile them separately.",[128,723,725],{"id":724},"faq","FAQ",[727,728,731,735],"details",{"className":729},[730],"faq-item",[732,733,734],"summary",{},"Is runtime CSS-in-JS always slow?",[15,736,737],{},"It adds overhead proportional to the number of styled components rendered and the amount of dynamic styling. Small apps may not notice; large, interactive apps on mid-range phones often do.",[727,739,741,744],{"className":740},[730],[732,742,743],{},"What is zero-runtime CSS-in-JS?",[15,745,746],{},"Libraries that let you author styles in JavaScript or TypeScript but extract them to static CSS at build time, so no styling code runs in the browser.",[727,748,750,753],{"className":749},[730],[732,751,752],{},"Does runtime CSS-in-JS affect LCP?",[15,754,755],{},"It can, through larger bundles and longer hydration, especially for client-rendered apps. Server-rendered pages with inlined styles usually see more effect on INP and TBT than on LCP.",[727,757,759,762],{"className":758},[730],[732,760,761],{},"Can I keep styled-components and still improve performance?",[15,763,764],{},"Yes: hoist components, use CSS variables for dynamic values, avoid prop interpolation in hot paths, and keep the library up to date.",[727,766,768,771],{"className":767},[730],[732,769,770],{},"How do I measure style injection cost?",[15,772,773],{},"In a Performance profile, look for the library's internal functions and the Recalculate Style events that follow DOM updates. Compare against a branch with a component migrated.",[727,775,777,780],{"className":776},[730],[732,778,779],{},"Which zero-runtime library should I choose?",[15,781,782],{},"Choose based on your framework and team preferences — type-safe authoring, atomic output, or familiar syntax. Performance differences among zero-runtime options are small compared with the difference from runtime libraries.",[727,784,786,789],{"className":785},[730],[732,787,788],{},"Does runtime CSS-in-JS work with the browser cache?",[15,790,791],{},"The generated styles are part of the HTML or created in the browser, so they are not cached as a separate file. Extracted CSS files can be cached long-term with hashed names, which helps repeat visits.",[128,793,795],{"id":794},"related","Related",[133,797,798,805,812],{},[136,799,800,804],{},[19,801,803],{"href":802},"\u002Frendering-css-performance\u002Fcritical-css-and-render-blocking-resources\u002Fremoving-unused-css-with-purgecss\u002F","Removing unused CSS with PurgeCSS"," — reducing static CSS overhead.",[136,806,807,811],{},[19,808,810],{"href":809},"\u002Frendering-css-performance\u002Fdom-size-and-list-virtualization\u002Freducing-style-recalculation-cost\u002F","Reducing style recalculation cost"," — the rendering cost behind rule injection.",[136,813,814,818],{},[19,815,817],{"href":816},"\u002Fframework-performance\u002Freact-rendering-performance\u002F","React performance"," — wider React rendering costs.",[820,821,823],"script",{"type":822},"application\u002Fld+json","\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"HowTo\",\n  \"name\": \"The Performance Cost of Runtime CSS-in-JS\",\n  \"description\": \"How runtime CSS-in-JS affects hydration, rendering and INP, how to measure its cost, and the options for reducing or removing it.\",\n  \"step\": [\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 1,\n      \"name\": \"Measure the cost in your app\",\n      \"text\": \"Profile hydration and key interactions with 4x CPU throttling.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 2,\n      \"name\": \"Move frequently changing values to CSS variables\",\n      \"text\": \"Move frequently changing values to CSS variables\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 3,\n      \"name\": \"Hoist static styles\",\n      \"text\": \"Define styled components at module level (not inside render functions) and keep variants as a small set of static classes rather than arbitrary prop interpolation.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 4,\n      \"name\": \"Migrate to zero-runtime styling\",\n      \"text\": \"Libraries such as vanilla-extract, Linaria, Panda CSS and StyleX extract CSS at build time.\"\n    }\n  ]\n}\n",[820,825,826],{"type":822},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"TechArticle\",\n  \"headline\": \"The Performance Cost of Runtime CSS-in-JS\",\n  \"description\": \"How runtime CSS-in-JS affects hydration, rendering and INP, how to measure its cost, and the options for reducing or removing it.\",\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\u002Fcritical-css-and-render-blocking-resources\u002Fruntime-css-in-js-performance-cost\u002F\"\n  }\n}\n",[820,828,829],{"type":822},"\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\": \"Critical CSS & Render-Blocking Resources\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Frendering-css-performance\u002Fcritical-css-and-render-blocking-resources\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 4,\n      \"name\": \"Runtime CSS-in-JS Performance Cost\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Frendering-css-performance\u002Fcritical-css-and-render-blocking-resources\u002Fruntime-css-in-js-performance-cost\u002F\"\n    }\n  ]\n}\n",[831,832,833],"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 .sPXB4, html code.shiki .sPXB4{--shiki-default:#023B95;--shiki-dark:#91CBFF;--shiki-light:#023B95}html pre.shiki code .saISM, html code.shiki .saISM{--shiki-default:#0E1116;--shiki-dark:#F0F3F6;--shiki-light:#0E1116}html pre.shiki code .smZ65, html code.shiki .smZ65{--shiki-default:#622CBC;--shiki-dark:#DBB7FF;--shiki-light:#622CBC}html pre.shiki code .sZ8jY, html code.shiki .sZ8jY{--shiki-default:#032563;--shiki-dark:#ADDCFF;--shiki-light:#032563}html pre.shiki code .sZBmE, html code.shiki .sZBmE{--shiki-default:#024C1A;--shiki-dark:#72F088;--shiki-light:#024C1A}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":211,"searchDepth":226,"depth":226,"links":835},[836,837,838,844,845,846,847,848,849,850,851],{"id":130,"depth":226,"text":131},{"id":163,"depth":226,"text":164},{"id":191,"depth":226,"text":192,"children":839},[840,841,842,843],{"id":196,"depth":278,"text":197},{"id":203,"depth":278,"text":204},{"id":356,"depth":278,"text":357},{"id":363,"depth":278,"text":364},{"id":509,"depth":226,"text":510},{"id":516,"depth":226,"text":517},{"id":652,"depth":226,"text":653},{"id":659,"depth":226,"text":660},{"id":666,"depth":226,"text":667},{"id":696,"depth":226,"text":697},{"id":724,"depth":226,"text":725},{"id":794,"depth":226,"text":795},"How runtime CSS-in-JS affects hydration, rendering and INP, how to measure its cost, and the options for reducing or removing it.","md",{"slug":855,"type":856,"breadcrumb":857,"datePublished":865,"dateModified":865},"runtime-css-in-js-performance-cost","article",[858,861,862,863],{"name":859,"url":860},"Home","\u002F",{"name":27,"url":26},{"name":22,"url":21},{"name":5,"url":864},"\u002Frendering-css-performance\u002Fcritical-css-and-render-blocking-resources\u002Fruntime-css-in-js-performance-cost\u002F","2026-10-06",true,"\u002Frendering-css-performance\u002Fcritical-css-and-render-blocking-resources\u002Fruntime-css-in-js-performance-cost",{"title":13,"description":869},"Runtime CSS-in-JS libraries serialise and inject styles during render, adding scripting and style recalculation. Measure the cost and migrate to zero-runtime CSS.","rendering-css-performance\u002Fcritical-css-and-render-blocking-resources\u002Fruntime-css-in-js-performance-cost\u002Findex","FWfnXzqR5CALKmbe6GYKjGsd-qGC4JDONjb3sbdWulM",[873,877],{"title":874,"path":875,"stem":876,"children":-1},"Removing Unused CSS with PurgeCSS","\u002Frendering-css-performance\u002Fcritical-css-and-render-blocking-resources\u002Fremoving-unused-css-with-purgecss","rendering-css-performance\u002Fcritical-css-and-render-blocking-resources\u002Fremoving-unused-css-with-purgecss\u002Findex",{"title":878,"path":879,"stem":880,"children":-1},"CSS Containment & content-visibility","\u002Frendering-css-performance\u002Fcss-containment-and-content-visibility","rendering-css-performance\u002Fcss-containment-and-content-visibility\u002Findex",1791308077663]