[{"data":1,"prerenderedAt":1200},["ShallowReactive",2],{"blog-\u002Fblog\u002Fwhat-runtime-means-in-panda":3,"cover-\u002Fblog\u002Fwhat-runtime-means-in-panda":1199},{"id":4,"title":5,"body":6,"canonical":1185,"date":1186,"description":1187,"draft":1188,"duration":1185,"extension":1189,"lang":1185,"meta":1190,"navigation":83,"part":1191,"path":1192,"place":1185,"placeLink":1185,"readingTime":1193,"seo":1194,"seoTitle":1195,"series":1196,"stem":1197,"updated":1185,"__hash__":1198},"blog\u002Fblog\u002Fwhat-runtime-means-in-panda.md","What \"runtime\" means in Panda",{"type":7,"value":8,"toc":1176},"minimark",[9,16,19,31,34,37,40,45,48,152,155,164,183,193,203,214,221,224,228,238,241,258,262,275,332,335,338,407,422,425,465,469,472,475,866,915,930,944,955,958,989,993,999,1002,1057,1060,1063,1103,1110,1134,1138,1144,1148,1151,1160,1172],[10,11,12],"subtitle",{},[13,14,15],"p",{},"What actually ships to the browser when you use Panda.",[17,18],"post-cover",{},[13,20,21],{},[22,23,24,25,30],"em",{},"An interlude in the Panda internals series, between ",[26,27,29],"a",{"href":28},"\u002Fblog\u002Fpanda-never-runs-your-code","part 4"," and part 5. Call it the series' OVA. I've had to explain what \"runtime\" means in Panda more than once, so this one clears it up before we go deeper.",[13,32,33],{},"The question comes up every time Panda is compared to another styling library: does it have a runtime?",[13,35,36],{},"Yes. A small one. It never creates CSS.",[13,38,39],{},"Both halves of that answer matter, and people usually only hear one of them. \"It has a runtime\" turns into \"it's CSS-in-JS like Emotion\". \"It's build time\" turns into \"nothing ships\". Neither is right. Here's what does ship.",[41,42,44],"h2",{"id":43},"three-things-by-default","Three things by default",[13,46,47],{},"Take one component:",[49,50,55],"pre",{"className":51,"code":52,"language":53,"meta":54,"style":54},"language-tsx shiki shiki-themes github-light github-dark","import { css } from '..\u002Fstyled-system\u002Fcss'\n\nexport function Title() {\n  return \u003Ch1 className={css({ color: 'red.300', fontSize: '2xl' })}>Hi\u003C\u002Fh1>\n}\n","tsx","",[56,57,58,78,85,101,146],"code",{"__ignoreMap":54},[59,60,63,67,71,74],"span",{"class":61,"line":62},"line",1,[59,64,66],{"class":65},"szBVR","import",[59,68,70],{"class":69},"sVt8B"," { css } ",[59,72,73],{"class":65},"from",[59,75,77],{"class":76},"sZZnC"," '..\u002Fstyled-system\u002Fcss'\n",[59,79,81],{"class":61,"line":80},2,[59,82,84],{"emptyLinePlaceholder":83},true,"\n",[59,86,88,91,94,98],{"class":61,"line":87},3,[59,89,90],{"class":65},"export",[59,92,93],{"class":65}," function",[59,95,97],{"class":96},"sScJk"," Title",[59,99,100],{"class":69},"() {\n",[59,102,104,107,110,114,117,120,123,126,129,132,135,138,141,143],{"class":61,"line":103},4,[59,105,106],{"class":65},"  return",[59,108,109],{"class":69}," \u003C",[59,111,113],{"class":112},"s9eBZ","h1",[59,115,116],{"class":96}," className",[59,118,119],{"class":65},"=",[59,121,122],{"class":69},"{",[59,124,125],{"class":96},"css",[59,127,128],{"class":69},"({ color: ",[59,130,131],{"class":76},"'red.300'",[59,133,134],{"class":69},", fontSize: ",[59,136,137],{"class":76},"'2xl'",[59,139,140],{"class":69}," })}>Hi\u003C\u002F",[59,142,113],{"class":112},[59,144,145],{"class":69},">\n",[59,147,149],{"class":61,"line":148},5,[59,150,151],{"class":69},"}\n",[13,153,154],{},"With Panda's default setup, three things reach the browser.",[13,156,157],{},[158,159],"img",{"alt":160,"src":161,"width":162,"height":163},"By default, three things ship: the stylesheet, your style objects and the css() function. With transform: true, the same stylesheet ships with plain class strings, and the objects and the function are gone.","\u002Fimages\u002Fblog\u002Fwhat-runtime-means-in-panda\u002Fships.svg",1200,675,[13,165,166,170,171,174,175,178,179,182],{},[167,168,169],"strong",{},"1. A stylesheet."," Panda generates CSS at build time and writes it to a real ",[56,172,173],{},".css"," file. You load it like any other stylesheet. The rules for ",[56,176,177],{},"color: red.300"," and ",[56,180,181],{},"fontSize: 2xl"," are in there before your app starts.",[13,184,185,188,189,192],{},[167,186,187],{},"2. Your style objects."," ",[56,190,191],{},"{ color: 'red.300', fontSize: '2xl' }"," is an argument in your component code, so it stays in your JavaScript bundle. Panda extracted it for the stylesheet, but it didn't remove it from your source.",[13,194,195,202],{},[167,196,197,198,201],{},"3. The ",[56,199,200],{},"css()"," function."," It takes that object and returns class names:",[49,204,208],{"className":205,"code":206,"language":207,"meta":54,"style":54},"language-ts shiki shiki-themes github-light github-dark","'c_red.300 fs_2xl'\n","ts",[56,209,210],{"__ignoreMap":54},[59,211,212],{"class":61,"line":62},[59,213,206],{"class":76},[13,215,216,217,220],{},"To do that, it walks the object, resolves shorthands, sorts conditions and builds each name from a small table of utility names that Panda generates into ",[56,218,219],{},"styled-system\u002Fcss",".",[13,222,223],{},"So when someone says Panda leaves styles in your bundle, they're right about the objects. The CSS is a different story.",[41,225,227],{"id":226},"what-the-runtime-never-does","What the runtime never does",[13,229,230,231,233,234,237],{},"The ",[56,232,200],{}," function doesn't generate CSS. It doesn't inject a ",[56,235,236],{},"\u003Cstyle>"," tag or touch the DOM. It builds strings that point at rules the stylesheet already has.",[13,239,240],{},"That's the line between Panda and runtime CSS-in-JS. Emotion and styled-components generate CSS in the browser and insert it while your app renders. Panda did that work during the build, so all the browser does is look up the class names.",[13,242,243,244,250,251,254,255,257],{},"There's one opt-in exception. If you use ",[26,245,249],{"href":246,"rel":247},"https:\u002F\u002Fpanda-css.com\u002Fdocs\u002Ftheming\u002Fmultiple-themes",[248],"nofollow","multiple themes"," and load one on demand, ",[56,252,253],{},"injectTheme"," puts that theme's CSS into a ",[56,256,236],{}," tag. Even then, the CSS was generated at build time. The browser only inserts it.",[41,259,261],{"id":260},"removing-the-runtime","Removing the runtime",[13,263,264,265,270,271,274],{},"In v2, you can remove the last two items as well. Turn on ",[26,266,269],{"href":267,"rel":268},"https:\u002F\u002Fpanda-css.com\u002Fdocs\u002Fstyling\u002Fsource-transforms",[248],"source transforms"," with ",[56,272,273],{},"transform: true"," on the bundler plugin:",[49,276,278],{"className":205,"code":277,"language":207,"meta":54,"style":54},"import pandacss from '@pandacss\u002Fvite'\n\nexport default defineConfig({\n  plugins: [pandacss({ transform: true })],\n})\n",[56,279,280,292,296,309,327],{"__ignoreMap":54},[59,281,282,284,287,289],{"class":61,"line":62},[59,283,66],{"class":65},[59,285,286],{"class":69}," pandacss ",[59,288,73],{"class":65},[59,290,291],{"class":76}," '@pandacss\u002Fvite'\n",[59,293,294],{"class":61,"line":80},[59,295,84],{"emptyLinePlaceholder":83},[59,297,298,300,303,306],{"class":61,"line":87},[59,299,90],{"class":65},[59,301,302],{"class":65}," default",[59,304,305],{"class":96}," defineConfig",[59,307,308],{"class":69},"({\n",[59,310,311,314,317,320,324],{"class":61,"line":103},[59,312,313],{"class":69},"  plugins: [",[59,315,316],{"class":96},"pandacss",[59,318,319],{"class":69},"({ transform: ",[59,321,323],{"class":322},"sj4cs","true",[59,325,326],{"class":69}," })],\n",[59,328,329],{"class":61,"line":148},[59,330,331],{"class":69},"})\n",[13,333,334],{},"The same option works on the webpack, Rollup and Bun plugins. Rspack and Rolldown go through the webpack and Rollup ones.",[13,336,337],{},"With it on, the bundler rewrites each call to the class string Panda already worked out:",[49,339,341],{"className":51,"code":340,"language":53,"meta":54,"style":54},"\u002F\u002F you write\n\u003Ch1 className={css({ color: 'red.300', fontSize: '2xl' })}>Hi\u003C\u002Fh1>\n\n\u002F\u002F your bundle ships\n\u003Ch1 className=\"c_red.300 fs_2xl\">Hi\u003C\u002Fh1>\n",[56,342,343,349,378,382,387],{"__ignoreMap":54},[59,344,345],{"class":61,"line":62},[59,346,348],{"class":347},"sJ8bj","\u002F\u002F you write\n",[59,350,351,354,356,358,360,362,364,366,368,370,372,374,376],{"class":61,"line":80},[59,352,353],{"class":69},"\u003C",[59,355,113],{"class":112},[59,357,116],{"class":96},[59,359,119],{"class":65},[59,361,122],{"class":69},[59,363,125],{"class":96},[59,365,128],{"class":69},[59,367,131],{"class":76},[59,369,134],{"class":69},[59,371,137],{"class":76},[59,373,140],{"class":69},[59,375,113],{"class":112},[59,377,145],{"class":69},[59,379,380],{"class":61,"line":87},[59,381,84],{"emptyLinePlaceholder":83},[59,383,384],{"class":61,"line":103},[59,385,386],{"class":347},"\u002F\u002F your bundle ships\n",[59,388,389,391,393,395,397,400,403,405],{"class":61,"line":148},[59,390,353],{"class":69},[59,392,113],{"class":112},[59,394,116],{"class":96},[59,396,119],{"class":65},[59,398,399],{"class":76},"\"c_red.300 fs_2xl\"",[59,401,402],{"class":69},">Hi\u003C\u002F",[59,404,113],{"class":112},[59,406,145],{"class":69},[13,408,409,410,413,414,417,418,421],{},"The object is gone, and so is the call. Pattern calls, recipe calls and style props on the ",[56,411,412],{},"styled"," factory get the same treatment. ",[56,415,416],{},"\u003CStack gap=\"4\">"," becomes a plain ",[56,419,420],{},"\u003Cdiv>"," with a class string.",[13,423,424],{},"A few things stay:",[426,427,428,439,452],"ul",{},[429,430,431,434,435,438],"li",{},[167,432,433],{},"Calls Panda can't resolve."," If a value only exists at runtime, the call keeps its runtime form. That's by design. ",[26,436,437],{"href":28},"Part 4"," covers what Panda can follow and where it stops.",[429,440,441,444,445,448,449,220],{},[167,442,443],{},"Joins with your own class names."," When a call site mixes Panda styles with a class from somewhere else, Panda rewrites what it can and joins the rest. Where the merge needs real conflict resolution, it imports ",[56,446,447],{},"cx"," from your ",[56,450,451],{},"styled-system",[429,453,454,457,458,178,461,464],{},[167,455,456],{},"Turbopack."," It has no plugin API, so there's no Turbopack adapter yet. On Next.js 16, that means running ",[56,459,460],{},"next dev --webpack",[56,462,463],{},"next build --webpack",", or keeping transforms off. There's also an unofficial workaround, below.",[41,466,468],{"id":467},"an-unofficial-turbopack-workaround","An unofficial Turbopack workaround",[13,470,471],{},"Turbopack can't take a plugin, but it does run loaders, and a loader can rewrite JavaScript. The hard part of a Turbopack adapter is the CSS, and you can skip that entirely: let the Panda CLI write the stylesheet, import it, and leave the bundler only the JavaScript to rewrite.",[13,473,474],{},"The loader asks Panda's compiler to transform each file:",[49,476,480],{"className":477,"code":478,"language":479,"meta":54,"style":54},"language-js shiki shiki-themes github-light github-dark","\u002F\u002F panda-turbopack-loader.cjs\nlet ready\nasync function getCompiler(cwd) {\n  if (!ready) ready = (async () => {\n    const { createNodeDriver } = await import('@pandacss\u002Fcompiler')\n    const driver = await createNodeDriver({ cwd })\n    driver.codegen({ cwd })\n    driver.parseFiles()\n    return driver.compiler ?? driver\n  })()\n  return ready\n}\n\nmodule.exports = function pandaLoader(source) {\n  const callback = this.async()\n  const id = this.resourcePath\n  ;(async () => {\n    const { transformSource, shouldTransform } = await import('@pandacss\u002Ftransformer')\n    if (!shouldTransform(id)) return callback(null, source)\n    const compiler = await getCompiler(this.rootContext)\n    const result = transformSource({ path: id, source, compiler })\n    callback(null, result.changed ? result.code : source, result.map)\n  })().catch(callback)\n}\n","js",[56,481,482,487,495,515,544,574,593,604,615,630,636,643,648,653,678,698,713,727,758,786,808,824,849,861],{"__ignoreMap":54},[59,483,484],{"class":61,"line":62},[59,485,486],{"class":347},"\u002F\u002F panda-turbopack-loader.cjs\n",[59,488,489,492],{"class":61,"line":80},[59,490,491],{"class":65},"let",[59,493,494],{"class":69}," ready\n",[59,496,497,500,502,505,508,512],{"class":61,"line":87},[59,498,499],{"class":65},"async",[59,501,93],{"class":65},[59,503,504],{"class":96}," getCompiler",[59,506,507],{"class":69},"(",[59,509,511],{"class":510},"s4XuR","cwd",[59,513,514],{"class":69},") {\n",[59,516,517,520,523,526,529,531,533,535,538,541],{"class":61,"line":103},[59,518,519],{"class":65},"  if",[59,521,522],{"class":69}," (",[59,524,525],{"class":65},"!",[59,527,528],{"class":69},"ready) ready ",[59,530,119],{"class":65},[59,532,522],{"class":69},[59,534,499],{"class":65},[59,536,537],{"class":69}," () ",[59,539,540],{"class":65},"=>",[59,542,543],{"class":69}," {\n",[59,545,546,549,552,555,558,560,563,566,568,571],{"class":61,"line":148},[59,547,548],{"class":65},"    const",[59,550,551],{"class":69}," { ",[59,553,554],{"class":322},"createNodeDriver",[59,556,557],{"class":69}," } ",[59,559,119],{"class":65},[59,561,562],{"class":65}," await",[59,564,565],{"class":65}," import",[59,567,507],{"class":69},[59,569,570],{"class":76},"'@pandacss\u002Fcompiler'",[59,572,573],{"class":69},")\n",[59,575,577,579,582,585,587,590],{"class":61,"line":576},6,[59,578,548],{"class":65},[59,580,581],{"class":322}," driver",[59,583,584],{"class":65}," =",[59,586,562],{"class":65},[59,588,589],{"class":96}," createNodeDriver",[59,591,592],{"class":69},"({ cwd })\n",[59,594,596,599,602],{"class":61,"line":595},7,[59,597,598],{"class":69},"    driver.",[59,600,601],{"class":96},"codegen",[59,603,592],{"class":69},[59,605,607,609,612],{"class":61,"line":606},8,[59,608,598],{"class":69},[59,610,611],{"class":96},"parseFiles",[59,613,614],{"class":69},"()\n",[59,616,618,621,624,627],{"class":61,"line":617},9,[59,619,620],{"class":65},"    return",[59,622,623],{"class":69}," driver.compiler ",[59,625,626],{"class":65},"??",[59,628,629],{"class":69}," driver\n",[59,631,633],{"class":61,"line":632},10,[59,634,635],{"class":69},"  })()\n",[59,637,639,641],{"class":61,"line":638},11,[59,640,106],{"class":65},[59,642,494],{"class":69},[59,644,646],{"class":61,"line":645},12,[59,647,151],{"class":69},[59,649,651],{"class":61,"line":650},13,[59,652,84],{"emptyLinePlaceholder":83},[59,654,656,659,661,664,666,668,671,673,676],{"class":61,"line":655},14,[59,657,658],{"class":322},"module",[59,660,220],{"class":69},[59,662,663],{"class":322},"exports",[59,665,584],{"class":65},[59,667,93],{"class":65},[59,669,670],{"class":96}," pandaLoader",[59,672,507],{"class":69},[59,674,675],{"class":510},"source",[59,677,514],{"class":69},[59,679,681,684,687,689,692,694,696],{"class":61,"line":680},15,[59,682,683],{"class":65},"  const",[59,685,686],{"class":322}," callback",[59,688,584],{"class":65},[59,690,691],{"class":322}," this",[59,693,220],{"class":69},[59,695,499],{"class":96},[59,697,614],{"class":69},[59,699,701,703,706,708,710],{"class":61,"line":700},16,[59,702,683],{"class":65},[59,704,705],{"class":322}," id",[59,707,584],{"class":65},[59,709,691],{"class":322},[59,711,712],{"class":69},".resourcePath\n",[59,714,716,719,721,723,725],{"class":61,"line":715},17,[59,717,718],{"class":69},"  ;(",[59,720,499],{"class":65},[59,722,537],{"class":69},[59,724,540],{"class":65},[59,726,543],{"class":69},[59,728,730,732,734,737,740,743,745,747,749,751,753,756],{"class":61,"line":729},18,[59,731,548],{"class":65},[59,733,551],{"class":69},[59,735,736],{"class":322},"transformSource",[59,738,739],{"class":69},", ",[59,741,742],{"class":322},"shouldTransform",[59,744,557],{"class":69},[59,746,119],{"class":65},[59,748,562],{"class":65},[59,750,565],{"class":65},[59,752,507],{"class":69},[59,754,755],{"class":76},"'@pandacss\u002Ftransformer'",[59,757,573],{"class":69},[59,759,761,764,766,768,770,773,776,778,780,783],{"class":61,"line":760},19,[59,762,763],{"class":65},"    if",[59,765,522],{"class":69},[59,767,525],{"class":65},[59,769,742],{"class":96},[59,771,772],{"class":69},"(id)) ",[59,774,775],{"class":65},"return",[59,777,686],{"class":96},[59,779,507],{"class":69},[59,781,782],{"class":322},"null",[59,784,785],{"class":69},", source)\n",[59,787,789,791,794,796,798,800,802,805],{"class":61,"line":788},20,[59,790,548],{"class":65},[59,792,793],{"class":322}," compiler",[59,795,584],{"class":65},[59,797,562],{"class":65},[59,799,504],{"class":96},[59,801,507],{"class":69},[59,803,804],{"class":322},"this",[59,806,807],{"class":69},".rootContext)\n",[59,809,811,813,816,818,821],{"class":61,"line":810},21,[59,812,548],{"class":65},[59,814,815],{"class":322}," result",[59,817,584],{"class":65},[59,819,820],{"class":96}," transformSource",[59,822,823],{"class":69},"({ path: id, source, compiler })\n",[59,825,827,830,832,834,837,840,843,846],{"class":61,"line":826},22,[59,828,829],{"class":96},"    callback",[59,831,507],{"class":69},[59,833,782],{"class":322},[59,835,836],{"class":69},", result.changed ",[59,838,839],{"class":65},"?",[59,841,842],{"class":69}," result.code ",[59,844,845],{"class":65},":",[59,847,848],{"class":69}," source, result.map)\n",[59,850,852,855,858],{"class":61,"line":851},23,[59,853,854],{"class":69},"  })().",[59,856,857],{"class":96},"catch",[59,859,860],{"class":69},"(callback)\n",[59,862,864],{"class":61,"line":863},24,[59,865,151],{"class":69},[49,867,869],{"className":477,"code":868,"language":479,"meta":54,"style":54},"\u002F\u002F next.config.mjs\nexport default {\n  turbopack: {\n    rules: { '.\u002Fapp\u002F**\u002F*.tsx': { loaders: ['.\u002Fpanda-turbopack-loader.cjs'] } },\n  },\n}\n",[56,870,871,876,884,889,906,911],{"__ignoreMap":54},[59,872,873],{"class":61,"line":62},[59,874,875],{"class":347},"\u002F\u002F next.config.mjs\n",[59,877,878,880,882],{"class":61,"line":80},[59,879,90],{"class":65},[59,881,302],{"class":65},[59,883,543],{"class":69},[59,885,886],{"class":61,"line":87},[59,887,888],{"class":69},"  turbopack: {\n",[59,890,891,894,897,900,903],{"class":61,"line":103},[59,892,893],{"class":69},"    rules: { ",[59,895,896],{"class":76},"'.\u002Fapp\u002F**\u002F*.tsx'",[59,898,899],{"class":69},": { loaders: [",[59,901,902],{"class":76},"'.\u002Fpanda-turbopack-loader.cjs'",[59,904,905],{"class":69},"] } },\n",[59,907,908],{"class":61,"line":148},[59,909,910],{"class":69},"  },\n",[59,912,913],{"class":61,"line":576},[59,914,151],{"class":69},[13,916,917,918,921,922,925,926,929],{},"Run ",[56,919,920],{},"panda --watch"," (or ",[56,923,924],{},"panda cssgen"," before a build) and import ",[56,927,928],{},"styled-system\u002Fstyles.css"," in your root layout.",[13,931,932,933,936,937,939,940,943],{},"On Next.js 16.4.3 with Panda 2.4.0, a plain ",[56,934,935],{},"next build"," gives HTML with the final class names in it, and the ",[56,938,200],{}," runtime is gone from the client chunks. ",[56,941,942],{},"next dev"," gives the same result, and hot reload works: change a style and the new class name shows up without a page reload, with component state intact.",[13,945,946,947,950,951,954],{},"Leave out the ",[56,948,949],{},"as: '*.tsx'"," option you'll see in older loader examples. On 16.4 it renames files to ",[56,952,953],{},"card.tsx.tsx"," and the build fails.",[13,956,957],{},"It's unofficial, so know the limits:",[426,959,960,975,983],{},[429,961,962,967,968,971,972,974],{},[167,963,964,966],{},[56,965,447],{}," brings the runtime back."," When a call mixes in a dynamic class name, the loader leaves ",[56,969,970],{},"import { cx } from '..\u002Fstyled-system\u002Fcss'",". That file also sets up ",[56,973,200],{},", so the whole runtime ships again. The same component built with the Vite plugin ships without it.",[429,976,977,982],{},[167,978,979,980,220],{},"Hot reload needs ",[56,981,920],{}," The loader updates the class name on every save, but the rule behind it only exists once the CLI rewrites the stylesheet. Without the watcher, a new value gives you a class name with no CSS.",[429,984,985,988],{},[167,986,987],{},"Each build worker starts its own Panda."," Next runs several, and each one loads the compiler.",[41,990,992],{"id":991},"the-numbers","The numbers",[13,994,995,996,998],{},"I built a small Preact app with Vite and Panda 2.4.0, using the default presets. Preact is small enough that Panda's share of the bundle is easy to see. Each component has four ",[56,997,200],{}," calls, with hover, focus and responsive styles, and one ternary.",[13,1000,1001],{},"All sizes are gzipped:",[1003,1004,1005,1021],"table",{},[1006,1007,1008],"thead",{},[1009,1010,1011,1015,1018],"tr",{},[1012,1013,1014],"th",{},"JS",[1012,1016,1017],{},"Transforms off",[1012,1019,1020],{},"Transforms on",[1022,1023,1024,1035,1046],"tbody",{},[1009,1025,1026,1030,1033],{},[1027,1028,1029],"td",{},"Preact alone, no Panda",[1027,1031,1032],{},"5.1 kB",[1027,1034,1032],{},[1009,1036,1037,1040,1043],{},[1027,1038,1039],{},"1 component",[1027,1041,1042],{},"11.8 kB",[1027,1044,1045],{},"5.3 kB",[1009,1047,1048,1051,1054],{},[1027,1049,1050],{},"40 components",[1027,1052,1053],{},"13.0 kB",[1027,1055,1056],{},"6.5 kB",[13,1058,1059],{},"The stylesheet for 40 components was 7.0 kB both times.",[13,1061,1062],{},"A few things stand out:",[1064,1065,1066,1072,1078,1084,1090],"ol",{},[429,1067,1068,1071],{},[167,1069,1070],{},"The stylesheet didn't change."," Same file, same hash. The transform only touches JavaScript.",[429,1073,1074,1077],{},[167,1075,1076],{},"The saving is fixed."," About 6.4 kB goes with one component, and about the same with forty. That's the runtime leaving.",[429,1079,1080,1083],{},[167,1081,1082],{},"With transforms on, Panda costs almost nothing in JS."," One component adds 0.2 kB over plain Preact. That's the class strings.",[429,1085,1086,1089],{},[167,1087,1088],{},"Objects compress well."," Going from 1 to 40 components adds 1.2 kB either way. The strings that replace the objects compress about as well as the objects did.",[429,1091,1092,1095,1096,1099,1100,1102],{},[167,1093,1094],{},"Neither build injects CSS."," No ",[56,1097,1098],{},"insertRule",", no ",[56,1101,236],{}," element, with transforms on or off.",[13,1104,1105,1106,1109],{},"The ternary is worth a look too. ",[56,1107,1108],{},"color: active ? 'red.700' : 'gray.700'"," didn't stay a runtime call. It became a ternary between two finished strings:",[49,1111,1113],{"className":477,"code":1112,"language":479,"meta":54,"style":54},"className: e ? `c_red.700 fs_xl fw_bold lh_tight` : `c_gray.700 fs_xl fw_bold lh_tight`\n",[56,1114,1115],{"__ignoreMap":54},[59,1116,1117,1120,1123,1125,1128,1131],{"class":61,"line":62},[59,1118,1119],{"class":96},"className",[59,1121,1122],{"class":69},": e ",[59,1124,839],{"class":65},[59,1126,1127],{"class":76}," `c_red.700 fs_xl fw_bold lh_tight`",[59,1129,1130],{"class":65}," :",[59,1132,1133],{"class":76}," `c_gray.700 fs_xl fw_bold lh_tight`\n",[41,1135,1137],{"id":1136},"should-you-turn-it-on","Should you turn it on?",[13,1139,1140,1141,1143],{},"The win is real but fixed: a few kilobytes gzipped, and it doesn't grow much with your app. Your numbers will differ, so measure your own bundle before and after. If you're on Turbopack, or a lot of your ",[56,1142,200],{}," calls depend on runtime values, leaving it off is fine. Your CSS is still generated at build time either way.",[41,1145,1147],{"id":1146},"the-short-version","The short version",[13,1149,1150],{},"Next time someone asks, here's the whole answer:",[1152,1153,1154],"blockquote",{},[13,1155,1156,1157,1159],{},"Panda generates all your CSS at build time. By default, your style objects and a small ",[56,1158,200],{}," function ship to the browser, and that function only turns objects into class names. It never creates CSS. Turn on source transforms and those are replaced with plain strings at build time.",[13,1161,1162],{},[22,1163,1164,1165,1167,1168,220],{},"If you want the full trip a ",[56,1166,200],{}," call takes through the build, start with ",[26,1169,1171],{"href":1170},"\u002Fblog\u002Fbuild-once-at-build-time","Build once, at build time",[1173,1174,1175],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":54,"searchDepth":80,"depth":80,"links":1177},[1178,1179,1180,1181,1182,1183,1184],{"id":43,"depth":80,"text":44},{"id":226,"depth":80,"text":227},{"id":260,"depth":80,"text":261},{"id":467,"depth":80,"text":468},{"id":991,"depth":80,"text":992},{"id":1136,"depth":80,"text":1137},{"id":1146,"depth":80,"text":1147},null,"2026-10-28","Does Panda CSS have a runtime? Yes, a small one, and it never creates CSS. What ships to the browser by default, what it does there, and how source transforms remove it.",false,"md",{},4.5,"\u002Fblog\u002Fwhat-runtime-means-in-panda","8min",{"title":5,"description":1187},"Does Panda CSS have a runtime? What ships to the browser, and how to remove it","Panda internals","blog\u002Fwhat-runtime-means-in-panda","19oYgOuqajCfolXjqJ4kUrXbT8jSQIL0AgzokSIWORA",{"series":1196,"part":1191,"total":103},1793193908451]