[{"data":1,"prerenderedAt":1360},["ShallowReactive",2],{"page-\u002Fcss\u002F15-css-variables":3},{"id":4,"title":5,"body":6,"description":1352,"extension":1353,"meta":1354,"navigation":1355,"path":1356,"seo":1357,"stem":1358,"__hash__":1359},"content\u002Fcss\u002F15-css-variables.md","15 — CSS Variables: Custom Properties as the Theming Engine",{"type":7,"value":8,"toc":1336},"minimark",[9,13,31,36,211,215,322,326,387,392,438,543,554,738,818,829,928,934,1028,1032,1101,1105,1229,1233,1272,1332],[10,11,5],"h1",{"id":12},"_15-css-variables-custom-properties-as-the-theming-engine",[14,15,16,17,21,22,26,27,30],"p",{},"CSS custom properties (",[18,19,20],"code",{},"--name",") are real properties that cascade, inherit, and are readable\u002Fwritable from JS at runtime. They are ",[23,24,25],"em",{},"not"," preprocessor text substitution. This is what makes them the theming engine: change a variable on ",[18,28,29],{},":root",", and every consumer re-paints in one frame.",[32,33,35],"h2",{"id":34},"defining-and-using-with-fallback-semantics","Defining and Using — with fallback semantics",[37,38,40],"code-wrapper",{"language":39},"css",[41,42,46],"pre",{"className":43,"code":44,"language":39,"meta":45,"style":45},"language-css shiki shiki-themes github-light github-dark",":root {\n  --primary: #3498db;\n  --spacing: 1rem;\n  --radius: 8px;\n}\n.button {\n  background: var(--primary);\n  padding: var(--spacing);\n  border-radius: var(--radius);\n  color: var(--text-color, #333);  \u002F* fallback: used ONLY if --text-color is UNSET, not if it's invalid *\u002F\n}\n","",[18,47,48,60,77,94,110,116,124,144,161,178,206],{"__ignoreMap":45},[49,50,53,56],"span",{"class":51,"line":52},"line",1,[49,54,29],{"class":55},"sIsaT",[49,57,59],{"class":58},"ssxIu"," {\n",[49,61,63,67,70,74],{"class":51,"line":62},2,[49,64,66],{"class":65},"sCrzJ","  --primary",[49,68,69],{"class":58},": ",[49,71,73],{"class":72},"snvgF","#3498db",[49,75,76],{"class":58},";\n",[49,78,80,83,85,88,92],{"class":51,"line":79},3,[49,81,82],{"class":65},"  --spacing",[49,84,69],{"class":58},[49,86,87],{"class":72},"1",[49,89,91],{"class":90},"svdQ7","rem",[49,93,76],{"class":58},[49,95,97,100,102,105,108],{"class":51,"line":96},4,[49,98,99],{"class":65},"  --radius",[49,101,69],{"class":58},[49,103,104],{"class":72},"8",[49,106,107],{"class":90},"px",[49,109,76],{"class":58},[49,111,113],{"class":51,"line":112},5,[49,114,115],{"class":58},"}\n",[49,117,119,122],{"class":51,"line":118},6,[49,120,121],{"class":55},".button",[49,123,59],{"class":58},[49,125,127,130,132,135,138,141],{"class":51,"line":126},7,[49,128,129],{"class":72},"  background",[49,131,69],{"class":58},[49,133,134],{"class":72},"var",[49,136,137],{"class":58},"(",[49,139,140],{"class":65},"--primary",[49,142,143],{"class":58},");\n",[49,145,147,150,152,154,156,159],{"class":51,"line":146},8,[49,148,149],{"class":72},"  padding",[49,151,69],{"class":58},[49,153,134],{"class":72},[49,155,137],{"class":58},[49,157,158],{"class":65},"--spacing",[49,160,143],{"class":58},[49,162,164,167,169,171,173,176],{"class":51,"line":163},9,[49,165,166],{"class":72},"  border-radius",[49,168,69],{"class":58},[49,170,134],{"class":72},[49,172,137],{"class":58},[49,174,175],{"class":65},"--radius",[49,177,143],{"class":58},[49,179,181,184,186,188,190,193,196,199,202],{"class":51,"line":180},10,[49,182,183],{"class":72},"  color",[49,185,69],{"class":58},[49,187,134],{"class":72},[49,189,137],{"class":58},[49,191,192],{"class":65},"--text-color",[49,194,195],{"class":58},", ",[49,197,198],{"class":72},"#333",[49,200,201],{"class":58},");  ",[49,203,205],{"class":204},"sdCPZ","\u002F* fallback: used ONLY if --text-color is UNSET, not if it's invalid *\u002F\n",[49,207,209],{"class":51,"line":208},11,[49,210,115],{"class":58},[32,212,214],{"id":213},"the-cascade-variables-inherit-and-cascade","The Cascade — variables inherit and cascade",[37,216,217],{"language":39},[41,218,220],{"className":43,"code":219,"language":39,"meta":45,"style":45},":root { --color: blue; }              \u002F* global — every descendant inherits *\u002F\n.card { --color: red; }               \u002F* .card and descendants see red; others still blue *\u002F\n.card .title { color: var(--color); } \u002F* red (inherits from .card) *\u002F\n.other { color: var(--color); }       \u002F* blue (inherits from :root) *\u002F\n\u002F* Variables follow the normal cascade: later\u002Fmore-specific rules override. They are\n   NOT static text substitution — they're real properties that inherit and cascade. *\u002F\n",[18,221,222,243,263,289,312,317],{"__ignoreMap":45},[49,223,224,226,229,232,234,237,240],{"class":51,"line":52},[49,225,29],{"class":55},[49,227,228],{"class":58}," { ",[49,230,231],{"class":65},"--color",[49,233,69],{"class":58},[49,235,236],{"class":72},"blue",[49,238,239],{"class":58},"; }              ",[49,241,242],{"class":204},"\u002F* global — every descendant inherits *\u002F\n",[49,244,245,248,250,252,254,257,260],{"class":51,"line":62},[49,246,247],{"class":55},".card",[49,249,228],{"class":58},[49,251,231],{"class":65},[49,253,69],{"class":58},[49,255,256],{"class":72},"red",[49,258,259],{"class":58},"; }               ",[49,261,262],{"class":204},"\u002F* .card and descendants see red; others still blue *\u002F\n",[49,264,265,267,270,272,275,277,279,281,283,286],{"class":51,"line":79},[49,266,247],{"class":55},[49,268,269],{"class":55}," .title",[49,271,228],{"class":58},[49,273,274],{"class":72},"color",[49,276,69],{"class":58},[49,278,134],{"class":72},[49,280,137],{"class":58},[49,282,231],{"class":65},[49,284,285],{"class":58},"); } ",[49,287,288],{"class":204},"\u002F* red (inherits from .card) *\u002F\n",[49,290,291,294,296,298,300,302,304,306,309],{"class":51,"line":96},[49,292,293],{"class":55},".other",[49,295,228],{"class":58},[49,297,274],{"class":72},[49,299,69],{"class":58},[49,301,134],{"class":72},[49,303,137],{"class":58},[49,305,231],{"class":65},[49,307,308],{"class":58},"); }       ",[49,310,311],{"class":204},"\u002F* blue (inherits from :root) *\u002F\n",[49,313,314],{"class":51,"line":112},[49,315,316],{"class":204},"\u002F* Variables follow the normal cascade: later\u002Fmore-specific rules override. They are\n",[49,318,319],{"class":51,"line":118},[49,320,321],{"class":204},"   NOT static text substitution — they're real properties that inherit and cascade. *\u002F\n",[32,323,325],{"id":324},"the-invalid-value-trap-fallback-invalid","The Invalid-Value Trap — fallback ≠ invalid",[37,327,328],{"language":39},[41,329,331],{"className":43,"code":330,"language":39,"meta":45,"style":45},":root { --gap: 10; }  \u002F* unitless — invalid when used in padding *\u002F\n.box { padding: var(--gap); }  \u002F* var(--gap) → \"10\" → padding: 10 → INVALID → property set to INITIAL (0) *\u002F\n\u002F* ⚠️ The fallback in var(--gap, 10px) applies ONLY if --gap is UNSET, NOT if its value is invalid.\n   An invalid variable value makes the WHOLE property invalid → it goes to initial\u002Finherited, not the fallback. *\u002F\n",[18,332,333,353,377,382],{"__ignoreMap":45},[49,334,335,337,339,342,344,347,350],{"class":51,"line":52},[49,336,29],{"class":55},[49,338,228],{"class":58},[49,340,341],{"class":65},"--gap",[49,343,69],{"class":58},[49,345,346],{"class":72},"10",[49,348,349],{"class":58},"; }  ",[49,351,352],{"class":204},"\u002F* unitless — invalid when used in padding *\u002F\n",[49,354,355,358,360,363,365,367,369,371,374],{"class":51,"line":62},[49,356,357],{"class":55},".box",[49,359,228],{"class":58},[49,361,362],{"class":72},"padding",[49,364,69],{"class":58},[49,366,134],{"class":72},[49,368,137],{"class":58},[49,370,341],{"class":65},[49,372,373],{"class":58},"); }  ",[49,375,376],{"class":204},"\u002F* var(--gap) → \"10\" → padding: 10 → INVALID → property set to INITIAL (0) *\u002F\n",[49,378,379],{"class":51,"line":79},[49,380,381],{"class":204},"\u002F* ⚠️ The fallback in var(--gap, 10px) applies ONLY if --gap is UNSET, NOT if its value is invalid.\n",[49,383,384],{"class":51,"line":96},[49,385,386],{"class":204},"   An invalid variable value makes the WHOLE property invalid → it goes to initial\u002Finherited, not the fallback. *\u002F\n",[388,389,391],"h3",{"id":390},"anti-pattern-missing-unit-in-a-variable-value","Anti-pattern: missing unit in a variable value",[37,393,394],{"language":39},[41,395,397],{"className":43,"code":396,"language":39,"meta":45,"style":45},"\u002F* ❌ --gap: 10 (no unit) → padding: 10 is invalid → padding becomes 0 (initial), not the fallback *\u002F\n:root { --gap: 10; }\n.box { padding: var(--gap); }\n",[18,398,399,404,419],{"__ignoreMap":45},[49,400,401],{"class":51,"line":52},[49,402,403],{"class":204},"\u002F* ❌ --gap: 10 (no unit) → padding: 10 is invalid → padding becomes 0 (initial), not the fallback *\u002F\n",[49,405,406,408,410,412,414,416],{"class":51,"line":62},[49,407,29],{"class":55},[49,409,228],{"class":58},[49,411,341],{"class":65},[49,413,69],{"class":58},[49,415,346],{"class":72},[49,417,418],{"class":58},"; }\n",[49,420,421,423,425,427,429,431,433,435],{"class":51,"line":79},[49,422,357],{"class":55},[49,424,228],{"class":58},[49,426,362],{"class":72},[49,428,69],{"class":58},[49,430,134],{"class":72},[49,432,137],{"class":58},[49,434,341],{"class":65},[49,436,437],{"class":58},"); }\n",[37,439,440],{"language":39},[41,441,443],{"className":43,"code":442,"language":39,"meta":45,"style":45},"\u002F* ✓ Give the variable a unit, or multiply by 1px in calc(). *\u002F\n:root { --gap: 10px; }\n.box { padding: var(--gap); }  \u002F* 10px *\u002F\n\u002F* or *\u002F\n:root { --gap: 10; }\n.box { padding: calc(var(--gap) * 1px); }  \u002F* 10px — adds the unit at use-site *\u002F\n",[18,444,445,450,466,487,492,506],{"__ignoreMap":45},[49,446,447],{"class":51,"line":52},[49,448,449],{"class":204},"\u002F* ✓ Give the variable a unit, or multiply by 1px in calc(). *\u002F\n",[49,451,452,454,456,458,460,462,464],{"class":51,"line":62},[49,453,29],{"class":55},[49,455,228],{"class":58},[49,457,341],{"class":65},[49,459,69],{"class":58},[49,461,346],{"class":72},[49,463,107],{"class":90},[49,465,418],{"class":58},[49,467,468,470,472,474,476,478,480,482,484],{"class":51,"line":79},[49,469,357],{"class":55},[49,471,228],{"class":58},[49,473,362],{"class":72},[49,475,69],{"class":58},[49,477,134],{"class":72},[49,479,137],{"class":58},[49,481,341],{"class":65},[49,483,373],{"class":58},[49,485,486],{"class":204},"\u002F* 10px *\u002F\n",[49,488,489],{"class":51,"line":96},[49,490,491],{"class":204},"\u002F* or *\u002F\n",[49,493,494,496,498,500,502,504],{"class":51,"line":112},[49,495,29],{"class":55},[49,497,228],{"class":58},[49,499,341],{"class":65},[49,501,69],{"class":58},[49,503,346],{"class":72},[49,505,418],{"class":58},[49,507,508,510,512,514,516,519,521,523,525,527,530,533,536,538,540],{"class":51,"line":118},[49,509,357],{"class":55},[49,511,228],{"class":58},[49,513,362],{"class":72},[49,515,69],{"class":58},[49,517,518],{"class":72},"calc",[49,520,137],{"class":58},[49,522,134],{"class":72},[49,524,137],{"class":58},[49,526,341],{"class":65},[49,528,529],{"class":58},") ",[49,531,532],{"class":90},"*",[49,534,535],{"class":72}," 1",[49,537,107],{"class":90},[49,539,373],{"class":58},[49,541,542],{"class":204},"\u002F* 10px — adds the unit at use-site *\u002F\n",[32,544,546,547,550,551],{"id":545},"theming-lightdark-with-prefers-color-scheme-data-theme","Theming — light\u002Fdark with ",[18,548,549],{},"prefers-color-scheme"," + ",[18,552,553],{},"data-theme",[37,555,556],{"language":39},[41,557,559],{"className":43,"code":558,"language":39,"meta":45,"style":45},":root {\n  --bg: #fff; --fg: #333; --primary: #3498db;\n}\n@media (prefers-color-scheme: dark) {  \u002F* system preference *\u002F\n  :root { --bg: #1a1a1a; --fg: #eee; --primary: #5dade2; }\n}\n[data-theme=\"dark\"] {  \u002F* manual toggle override (wins via attribute specificity) *\u002F\n  --bg: #1a1a1a; --fg: #eee; --primary: #5dade2;\n}\nbody { background: var(--bg); color: var(--fg); }  \u002F* one rule, themed by variables *\u002F\n",[18,560,561,567,597,601,612,647,651,671,697,701],{"__ignoreMap":45},[49,562,563,565],{"class":51,"line":52},[49,564,29],{"class":55},[49,566,59],{"class":58},[49,568,569,572,574,577,580,583,585,587,589,591,593,595],{"class":51,"line":62},[49,570,571],{"class":65},"  --bg",[49,573,69],{"class":58},[49,575,576],{"class":72},"#fff",[49,578,579],{"class":58},"; ",[49,581,582],{"class":65},"--fg",[49,584,69],{"class":58},[49,586,198],{"class":72},[49,588,579],{"class":58},[49,590,140],{"class":65},[49,592,69],{"class":58},[49,594,73],{"class":72},[49,596,76],{"class":58},[49,598,599],{"class":51,"line":79},[49,600,115],{"class":58},[49,602,603,606,609],{"class":51,"line":96},[49,604,605],{"class":90},"@media",[49,607,608],{"class":58}," (prefers-color-scheme: dark) {  ",[49,610,611],{"class":204},"\u002F* system preference *\u002F\n",[49,613,614,617,619,622,624,627,629,631,633,636,638,640,642,645],{"class":51,"line":112},[49,615,616],{"class":55},"  :root",[49,618,228],{"class":58},[49,620,621],{"class":65},"--bg",[49,623,69],{"class":58},[49,625,626],{"class":72},"#1a1a1a",[49,628,579],{"class":58},[49,630,582],{"class":65},[49,632,69],{"class":58},[49,634,635],{"class":72},"#eee",[49,637,579],{"class":58},[49,639,140],{"class":65},[49,641,69],{"class":58},[49,643,644],{"class":72},"#5dade2",[49,646,418],{"class":58},[49,648,649],{"class":51,"line":118},[49,650,115],{"class":58},[49,652,653,656,658,661,665,668],{"class":51,"line":126},[49,654,655],{"class":58},"[",[49,657,553],{"class":55},[49,659,660],{"class":90},"=",[49,662,664],{"class":663},"sJ6F3","\"dark\"",[49,666,667],{"class":58},"] {  ",[49,669,670],{"class":204},"\u002F* manual toggle override (wins via attribute specificity) *\u002F\n",[49,672,673,675,677,679,681,683,685,687,689,691,693,695],{"class":51,"line":146},[49,674,571],{"class":65},[49,676,69],{"class":58},[49,678,626],{"class":72},[49,680,579],{"class":58},[49,682,582],{"class":65},[49,684,69],{"class":58},[49,686,635],{"class":72},[49,688,579],{"class":58},[49,690,140],{"class":65},[49,692,69],{"class":58},[49,694,644],{"class":72},[49,696,76],{"class":58},[49,698,699],{"class":51,"line":163},[49,700,115],{"class":58},[49,702,703,707,709,712,714,716,718,720,723,725,727,729,731,733,735],{"class":51,"line":180},[49,704,706],{"class":705},"sk71V","body",[49,708,228],{"class":58},[49,710,711],{"class":72},"background",[49,713,69],{"class":58},[49,715,134],{"class":72},[49,717,137],{"class":58},[49,719,621],{"class":65},[49,721,722],{"class":58},"); ",[49,724,274],{"class":72},[49,726,69],{"class":58},[49,728,134],{"class":72},[49,730,137],{"class":58},[49,732,582],{"class":65},[49,734,373],{"class":58},[49,736,737],{"class":204},"\u002F* one rule, themed by variables *\u002F\n",[37,739,741],{"language":740},"javascript",[41,742,745],{"className":743,"code":744,"language":740,"meta":45,"style":45},"language-javascript shiki shiki-themes github-light github-dark","\u002F\u002F Toggle theme at runtime — set the attribute, CSS variables update, page re-paints. No reload.\ndocument.documentElement.setAttribute('data-theme', 'dark');\n\u002F\u002F Persist + respect system preference on load:\nconst saved = localStorage.getItem('theme');\nif (saved) document.documentElement.setAttribute('data-theme', saved);\n",[18,746,747,752,772,777,801],{"__ignoreMap":45},[49,748,749],{"class":51,"line":52},[49,750,751],{"class":204},"\u002F\u002F Toggle theme at runtime — set the attribute, CSS variables update, page re-paints. No reload.\n",[49,753,754,757,760,762,765,767,770],{"class":51,"line":62},[49,755,756],{"class":58},"document.documentElement.",[49,758,759],{"class":55},"setAttribute",[49,761,137],{"class":58},[49,763,764],{"class":663},"'data-theme'",[49,766,195],{"class":58},[49,768,769],{"class":663},"'dark'",[49,771,143],{"class":58},[49,773,774],{"class":51,"line":79},[49,775,776],{"class":204},"\u002F\u002F Persist + respect system preference on load:\n",[49,778,779,782,785,788,791,794,796,799],{"class":51,"line":96},[49,780,781],{"class":90},"const",[49,783,784],{"class":72}," saved",[49,786,787],{"class":90}," =",[49,789,790],{"class":58}," localStorage.",[49,792,793],{"class":55},"getItem",[49,795,137],{"class":58},[49,797,798],{"class":663},"'theme'",[49,800,143],{"class":58},[49,802,803,806,809,811,813,815],{"class":51,"line":112},[49,804,805],{"class":90},"if",[49,807,808],{"class":58}," (saved) document.documentElement.",[49,810,759],{"class":55},[49,812,137],{"class":58},[49,814,764],{"class":663},[49,816,817],{"class":58},", saved);\n",[32,819,821,822,825,826],{"id":820},"js-css-bridge-setproperty-getpropertyvalue","JS ↔ CSS Bridge — ",[18,823,824],{},"setProperty"," \u002F ",[18,827,828],{},"getPropertyValue",[37,830,831],{"language":740},[41,832,834],{"className":743,"code":833,"language":740,"meta":45,"style":45},"\u002F\u002F Read\nconst primary = getComputedStyle(document.documentElement).getPropertyValue('--primary').trim();\n\u002F\u002F Set globally\ndocument.documentElement.style.setProperty('--primary', '#ff0000');\n\u002F\u002F Set per-element (scoped to that element + descendants)\nel.style.setProperty('--x', `${pointerX}px');\n\u002F\u002F CSS: transform: translateX(var(--x)) — JS drives the value, CSS owns the logic.\n",[18,835,836,841,872,877,895,900,923],{"__ignoreMap":45},[49,837,838],{"class":51,"line":52},[49,839,840],{"class":204},"\u002F\u002F Read\n",[49,842,843,845,848,850,853,856,858,860,863,866,869],{"class":51,"line":62},[49,844,781],{"class":90},[49,846,847],{"class":72}," primary",[49,849,787],{"class":90},[49,851,852],{"class":55}," getComputedStyle",[49,854,855],{"class":58},"(document.documentElement).",[49,857,828],{"class":55},[49,859,137],{"class":58},[49,861,862],{"class":663},"'--primary'",[49,864,865],{"class":58},").",[49,867,868],{"class":55},"trim",[49,870,871],{"class":58},"();\n",[49,873,874],{"class":51,"line":79},[49,875,876],{"class":204},"\u002F\u002F Set globally\n",[49,878,879,882,884,886,888,890,893],{"class":51,"line":96},[49,880,881],{"class":58},"document.documentElement.style.",[49,883,824],{"class":55},[49,885,137],{"class":58},[49,887,862],{"class":663},[49,889,195],{"class":58},[49,891,892],{"class":663},"'#ff0000'",[49,894,143],{"class":58},[49,896,897],{"class":51,"line":112},[49,898,899],{"class":204},"\u002F\u002F Set per-element (scoped to that element + descendants)\n",[49,901,902,905,907,909,912,914,917,920],{"class":51,"line":118},[49,903,904],{"class":58},"el.style.",[49,906,824],{"class":55},[49,908,137],{"class":58},[49,910,911],{"class":663},"'--x'",[49,913,195],{"class":58},[49,915,916],{"class":663},"`${",[49,918,919],{"class":58},"pointerX",[49,921,922],{"class":663},"}px');\n",[49,924,925],{"class":51,"line":126},[49,926,927],{"class":663},"\u002F\u002F CSS: transform: translateX(var(--x)) — JS drives the value, CSS owns the logic.\n",[32,929,931,932],{"id":930},"responsive-tokens-redefining-in-media","Responsive Tokens — redefining in ",[18,933,605],{},[37,935,936],{"language":39},[41,937,939],{"className":43,"code":938,"language":39,"meta":45,"style":45},":root { --spacing: 1rem; }\n@media (min-width: 768px) { :root { --spacing: 2rem; } }  \u002F* token becomes responsive *\u002F\n.container { padding: var(--spacing); }  \u002F* 1rem mobile, 2rem tablet+ — no per-use-site media queries *\u002F\n\u002F* You CANNOT use var() inside @media conditions: @media (min-width: var(--break)) is invalid.\n   But you CAN redefine variables INSIDE @media blocks (as above). *\u002F\n",[18,940,941,957,996,1018,1023],{"__ignoreMap":45},[49,942,943,945,947,949,951,953,955],{"class":51,"line":52},[49,944,29],{"class":55},[49,946,228],{"class":58},[49,948,158],{"class":65},[49,950,69],{"class":58},[49,952,87],{"class":72},[49,954,91],{"class":90},[49,956,418],{"class":58},[49,958,959,961,964,967,969,972,974,977,979,981,983,985,988,990,993],{"class":51,"line":62},[49,960,605],{"class":90},[49,962,963],{"class":58}," (",[49,965,966],{"class":72},"min-width",[49,968,69],{"class":58},[49,970,971],{"class":72},"768",[49,973,107],{"class":90},[49,975,976],{"class":58},") { ",[49,978,29],{"class":55},[49,980,228],{"class":58},[49,982,158],{"class":65},[49,984,69],{"class":58},[49,986,987],{"class":72},"2",[49,989,91],{"class":90},[49,991,992],{"class":58},"; } }  ",[49,994,995],{"class":204},"\u002F* token becomes responsive *\u002F\n",[49,997,998,1001,1003,1005,1007,1009,1011,1013,1015],{"class":51,"line":79},[49,999,1000],{"class":55},".container",[49,1002,228],{"class":58},[49,1004,362],{"class":72},[49,1006,69],{"class":58},[49,1008,134],{"class":72},[49,1010,137],{"class":58},[49,1012,158],{"class":65},[49,1014,373],{"class":58},[49,1016,1017],{"class":204},"\u002F* 1rem mobile, 2rem tablet+ — no per-use-site media queries *\u002F\n",[49,1019,1020],{"class":51,"line":96},[49,1021,1022],{"class":204},"\u002F* You CANNOT use var() inside @media conditions: @media (min-width: var(--break)) is invalid.\n",[49,1024,1025],{"class":51,"line":112},[49,1026,1027],{"class":204},"   But you CAN redefine variables INSIDE @media blocks (as above). *\u002F\n",[32,1029,1031],{"id":1030},"tips-tricks","💡 Tips & Tricks",[1033,1034,1035,1054,1068,1081,1089],"ul",{},[1036,1037,1038,1042,1043,963,1045,195,1048,195,1051,1053],"li",{},[1039,1040,1041],"strong",{},"Idiom",": design tokens on ",[18,1044,29],{},[18,1046,1047],{},"--color-primary",[18,1049,1050],{},"--space-md",[18,1052,175],{},") — change one value, the whole UI updates in one paint. This is the modern theming foundation.",[1036,1055,1056,69,1058,1060,1061,1064,1065,1067],{},[1039,1057,1041],{},[18,1059,553],{}," attribute + CSS variables for manual theme toggles — instant, no reload. Persist in ",[18,1062,1063],{},"localStorage",", respect ",[18,1066,549],{}," on first load.",[1036,1069,1070,1072,1073,1076,1077,1080],{},[1039,1071,1041],{},": JS↔CSS bridge via custom properties — JS sets ",[18,1074,1075],{},"el.style.setProperty('--x', '100px')",", CSS uses ",[18,1078,1079],{},"transform: translateX(var(--x))",". JS drives values, CSS owns the presentation logic (overridable by classes).",[1036,1082,1083,1085,1086,1088],{},[1039,1084,1041],{},": redefine variables in ",[18,1087,605],{}," for responsive tokens — the token adapts, every use-site updates. No per-component media queries.",[1036,1090,1091,69,1093,1096,1097,1100],{},[1039,1092,1041],{},[18,1094,1095],{},"var(--name, fallback)"," for robustness — the fallback applies if the variable is ",[23,1098,1099],{},"unset",". Useful for components that should work even if the consumer didn't define the token.",[32,1102,1104],{"id":1103},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[1033,1106,1107,1134,1147,1163,1189,1205,1220],{},[1036,1108,1109,69,1116,1119,1120,1123,1124,1126,1127,1130,1131,1133],{},[1039,1110,1111,1112,1115],{},"Invalid variable values make the ",[23,1113,1114],{},"property"," invalid, not the fallback",[18,1117,1118],{},"--gap: 10"," (no unit) + ",[18,1121,1122],{},"padding: var(--gap)"," → ",[18,1125,362],{}," invalid → ",[18,1128,1129],{},"initial"," (0). The fallback only applies if the variable is ",[23,1132,1099],{},".",[1036,1135,1136,69,1139,1142,1143,1146],{},[1039,1137,1138],{},"Variables are for VALUES only",[18,1140,1141],{},"var(--prop): red"," (property name) and ",[18,1144,1145],{},".var(--cls)"," (selector) don't work. No variable in media query conditions either.",[1036,1148,1149,69,1155,1158,1159,1162],{},[1039,1150,1151,1154],{},[18,1152,1153],{},"var()"," in shorthand can invalidate the whole shorthand",[18,1156,1157],{},"margin: var(--gap) var(--gap2)"," — if either is invalid, the whole ",[18,1160,1161],{},"margin"," is invalid.",[1036,1164,1165,69,1168,1171,1172,1175,1176,1171,1179,1182,1183,1185,1186,865],{},[1039,1166,1167],{},"URLs in variables",[18,1169,1170],{},"--img: url(\"x.png\")"," then ",[18,1173,1174],{},"background: var(--img)"," works. But ",[18,1177,1178],{},"--url: \"x.png\"",[18,1180,1181],{},"background: url(var(--url))"," doesn't (can't use ",[18,1184,1153],{}," inside ",[18,1187,1188],{},"url()",[1036,1190,1191,69,1197,1200,1201,1204],{},[1039,1192,1193,1196],{},[18,1194,1195],{},"!important"," on variables",[18,1198,1199],{},"--primary: blue !important"," makes the ",[23,1202,1203],{},"variable"," important (harder to override). Rarely needed; avoid.",[1036,1206,1207,69,1210,1213,1214,1216,1217,865],{},[1039,1208,1209],{},"CSS variables are case-sensitive",[18,1211,1212],{},"--Color"," ≠ ",[18,1215,231],{},". Stick to kebab-case (",[18,1218,1219],{},"--primary-color",[1036,1221,1222,69,1225,1228],{},[1039,1223,1224],{},"Initial value is guaranteed-invalid (unset)",[18,1226,1227],{},"var(--undefined)"," with no fallback makes the property invalid → initial\u002Finherited.",[32,1230,1232],{"id":1231},"spot-the-bug","🧠 Spot the Bug",[37,1234,1235],{"language":39},[41,1236,1238],{"className":43,"code":1237,"language":39,"meta":45,"style":45},":root { --gap: 10; }\n.box { padding: var(--gap); }\n",[18,1239,1240,1254],{"__ignoreMap":45},[49,1241,1242,1244,1246,1248,1250,1252],{"class":51,"line":52},[49,1243,29],{"class":55},[49,1245,228],{"class":58},[49,1247,341],{"class":65},[49,1249,69],{"class":58},[49,1251,346],{"class":72},[49,1253,418],{"class":58},[49,1255,1256,1258,1260,1262,1264,1266,1268,1270],{"class":51,"line":62},[49,1257,357],{"class":55},[49,1259,228],{"class":58},[49,1261,362],{"class":72},[49,1263,69],{"class":58},[49,1265,134],{"class":72},[49,1267,137],{"class":58},[49,1269,341],{"class":65},[49,1271,437],{"class":58},[1273,1274,1275,1279],"details",{},[1276,1277,1278],"summary",{},"Answer",[14,1280,1281,1283,1284,1286,1287,1290,1291,195,1294,1297,1298,1300,1301,1304,1305,1307,1308,1310,1311,963,1313,1316,1317,1319,1320,1323,1324,1327,1328,1331],{},[18,1282,1118],{}," is unitless. ",[18,1285,1122],{}," resolves to ",[18,1288,1289],{},"padding: 10"," — invalid (lengths need a unit: ",[18,1292,1293],{},"10px",[18,1295,1296],{},"10rem","). When ",[18,1299,1153],{}," resolves to an invalid value, the ",[23,1302,1303],{},"whole property"," is invalid → ",[18,1306,362],{}," is set to its ",[18,1309,1129],{}," value (0), not a fallback. The fallback only applies if the variable is ",[23,1312,1099],{},[18,1314,1315],{},"var(--undefined, 10px)","), not if its value is invalid. Fix: give ",[18,1318,341],{}," a unit (",[18,1321,1322],{},"--gap: 10px","), or multiply by ",[18,1325,1326],{},"1px"," in calc (",[18,1329,1330],{},"calc(var(--gap) * 1px)","). Always include units in variable values used as lengths.",[1333,1334,1335],"style",{},"html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .sCrzJ, html code.shiki .sCrzJ{--shiki-default:#E36209;--shiki-github-dark:#FFAB70}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}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 .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}html pre.shiki code .sk71V, html code.shiki .sk71V{--shiki-default:#22863A;--shiki-github-dark:#85E89D}",{"title":45,"searchDepth":62,"depth":62,"links":1337},[1338,1339,1340,1343,1345,1347,1349,1350,1351],{"id":34,"depth":62,"text":35},{"id":213,"depth":62,"text":214},{"id":324,"depth":62,"text":325,"children":1341},[1342],{"id":390,"depth":79,"text":391},{"id":545,"depth":62,"text":1344},"Theming — light\u002Fdark with prefers-color-scheme + data-theme",{"id":820,"depth":62,"text":1346},"JS ↔ CSS Bridge — setProperty \u002F getPropertyValue",{"id":930,"depth":62,"text":1348},"Responsive Tokens — redefining in @media",{"id":1030,"depth":62,"text":1031},{"id":1103,"depth":62,"text":1104},{"id":1231,"depth":62,"text":1232},"Custom property cascade and inheritance, var() fallback vs invalid-value semantics, runtime theming via data-theme + prefers-color-scheme, JS setProperty bridge, and redefinition in @media. Code-first reference for production design-token systems.","md",{},true,"\u002Fcss\u002F15-css-variables",{"title":5,"description":1352},"css\u002F15-css-variables","V6vYZwhlbC1mnRcy3WKsdURQAHSADKnj_UBtdQluBLU",1789924647430]