[{"data":1,"prerenderedAt":2699},["ShallowReactive",2],{"en-post-\u002Fen\u002Fcss-has-selector":3},{"id":4,"title":5,"body":6,"description":2688,"extension":2689,"meta":2690,"navigation":767,"path":2694,"seo":2695,"sitemap":2696,"stem":2697,"__hash__":2698},"blogEn\u002Fen\u002Fcss-has-selector.md","A Practical Guide to the CSS :has() Selector: Selecting Parents Without JavaScript",{"type":7,"value":8,"toc":2675},"minimark",[9,14,32,35,122,129,173,186,189,262,265,268,272,278,834,847,849,853,858,1346,1353,1371,1373,1377,1399,1652,1655,1704,1707,1709,1713,1716,2266,2280,2282,2286,2299,2406,2413,2415,2419,2424,2433,2480,2484,2548,2550,2554,2641,2671],[10,11,13],"h2",{"id":12},"csss-long-awaited-parent-selector","CSS's long-awaited \"parent selector\"",[15,16,17,18,22,23,27,28,31],"p",{},"For a long time, CSS selectors could only go ",[19,20,21],"strong",{},"downward",". You could select a child inside a parent with ",[24,25,26],"code",{},".card img",", but there was no way to select a parent based on its children, like \"a card that ",[19,29,30],{},"has"," an image.\"",[15,33,34],{},"So code like this was everywhere:",[36,37,42],"pre",{"className":38,"code":39,"language":40,"meta":41,"style":41},"language-js shiki shiki-themes github-light github-dark","\u002F\u002F Add a class to the parent card when its checkbox is checked\ncheckbox.addEventListener(\"change\", (e) => {\n  e.target.closest(\".card\").classList.toggle(\"is-selected\", e.target.checked);\n});\n","js","",[24,43,44,53,88,116],{"__ignoreMap":41},[45,46,49],"span",{"class":47,"line":48},"line",1,[45,50,52],{"class":51},"sJ8bj","\u002F\u002F Add a class to the parent card when its checkbox is checked\n",[45,54,56,60,64,67,71,74,78,81,85],{"class":47,"line":55},2,[45,57,59],{"class":58},"sVt8B","checkbox.",[45,61,63],{"class":62},"sScJk","addEventListener",[45,65,66],{"class":58},"(",[45,68,70],{"class":69},"sZZnC","\"change\"",[45,72,73],{"class":58},", (",[45,75,77],{"class":76},"s4XuR","e",[45,79,80],{"class":58},") ",[45,82,84],{"class":83},"szBVR","=>",[45,86,87],{"class":58}," {\n",[45,89,91,94,97,99,102,105,108,110,113],{"class":47,"line":90},3,[45,92,93],{"class":58},"  e.target.",[45,95,96],{"class":62},"closest",[45,98,66],{"class":58},[45,100,101],{"class":69},"\".card\"",[45,103,104],{"class":58},").classList.",[45,106,107],{"class":62},"toggle",[45,109,66],{"class":58},[45,111,112],{"class":69},"\"is-selected\"",[45,114,115],{"class":58},", e.target.checked);\n",[45,117,119],{"class":47,"line":118},4,[45,120,121],{"class":58},"});\n",[15,123,124,125,128],{},"With ",[24,126,127],{},":has()",", that becomes one line of CSS:",[36,130,134],{"className":131,"code":132,"language":133,"meta":41,"style":41},"language-css shiki shiki-themes github-light github-dark",".card:has(input:checked) {\n  border-color: orange;\n}\n","css",[24,135,136,153,168],{"__ignoreMap":41},[45,137,138,141,143,147,150],{"class":47,"line":48},[45,139,140],{"class":62},".card:has",[45,142,66],{"class":58},[45,144,146],{"class":145},"s9eBZ","input",[45,148,149],{"class":62},":checked",[45,151,152],{"class":58},") {\n",[45,154,155,159,162,165],{"class":47,"line":55},[45,156,158],{"class":157},"sj4cs","  border-color",[45,160,161],{"class":58},": ",[45,163,164],{"class":157},"orange",[45,166,167],{"class":58},";\n",[45,169,170],{"class":47,"line":90},[45,171,172],{"class":58},"}\n",[174,175,176],"blockquote",{},[15,177,178,181,182,185],{},[24,179,180],{},"A:has(B)"," selects \"an A that contains a B.\" The style applies to the ",[19,183,184],{},"outer element"," that satisfies the condition in the parentheses.",[15,187,188],{},"The parentheses can describe siblings as well as descendants, so it effectively works as a \"conditional selector.\"",[190,191,192,205],"table",{},[193,194,195],"thead",{},[196,197,198,202],"tr",{},[199,200,201],"th",{},"Syntax",[199,203,204],{},"Meaning",[206,207,208,218,228,238,248],"tbody",{},[196,209,210,215],{},[211,212,213],"td",{},[24,214,180],{},[211,216,217],{},"An A with a B somewhere among its descendants",[196,219,220,225],{},[211,221,222],{},[24,223,224],{},"A:has(> B)",[211,226,227],{},"An A with a B as a direct child",[196,229,230,235],{},[211,231,232],{},[24,233,234],{},"A:has(+ B)",[211,236,237],{},"An A whose very next sibling is a B",[196,239,240,245],{},[211,241,242],{},[24,243,244],{},"A:has(~ B)",[211,246,247],{},"An A with a B somewhere among its following siblings",[196,249,250,255],{},[211,251,252],{},[24,253,254],{},"A:not(:has(B))",[211,256,257,258,261],{},"An A that does ",[19,259,260],{},"not"," contain a B",[15,263,264],{},"Let's try some practical examples. In each one, the top is the live result and the tabs below show the code.",[266,267],"hr",{},[10,269,271],{"id":270},"example-1-cards-that-highlight-when-selected","Example 1. Cards that highlight when selected",[15,273,274,275],{},"You see this UI on pricing pages all the time: pick a radio button and the whole card is highlighted. ",[19,276,277],{},"There's no JavaScript at all.",[279,280,281,546],"code-group",{},[36,282,286],{"className":283,"code":284,"language":285,"meta":41,"style":41},"language-html shiki shiki-themes github-light github-dark","\u003Cdiv class=\"plans\">\n  \u003Clabel class=\"plan\">\n    \u003Cinput type=\"radio\" name=\"plan\" \u002F>\n    \u003Cstrong>Basic\u003C\u002Fstrong>\n    \u003Cspan>$0\u002Fmo\u003C\u002Fspan>\n  \u003C\u002Flabel>\n  \u003Clabel class=\"plan\">\n    \u003Cinput type=\"radio\" name=\"plan\" checked \u002F>\n    \u003Cstrong>Pro\u003C\u002Fstrong>\n    \u003Cspan>$9\u002Fmo\u003C\u002Fspan>\n  \u003C\u002Flabel>\n  \u003Clabel class=\"plan\">\n    \u003Cinput type=\"radio\" name=\"plan\" \u002F>\n    \u003Cstrong>Team\u003C\u002Fstrong>\n    \u003Cspan>$29\u002Fmo\u003C\u002Fspan>\n  \u003C\u002Flabel>\n\u003C\u002Fdiv>\n","html",[24,287,288,308,325,350,363,377,387,402,426,440,454,463,478,499,513,527,536],{"__ignoreMap":41},[45,289,290,293,296,299,302,305],{"class":47,"line":48},[45,291,292],{"class":58},"\u003C",[45,294,295],{"class":145},"div",[45,297,298],{"class":62}," class",[45,300,301],{"class":58},"=",[45,303,304],{"class":69},"\"plans\"",[45,306,307],{"class":58},">\n",[45,309,310,313,316,318,320,323],{"class":47,"line":55},[45,311,312],{"class":58},"  \u003C",[45,314,315],{"class":145},"label",[45,317,298],{"class":62},[45,319,301],{"class":58},[45,321,322],{"class":69},"\"plan\"",[45,324,307],{"class":58},[45,326,327,330,332,335,337,340,343,345,347],{"class":47,"line":90},[45,328,329],{"class":58},"    \u003C",[45,331,146],{"class":145},[45,333,334],{"class":62}," type",[45,336,301],{"class":58},[45,338,339],{"class":69},"\"radio\"",[45,341,342],{"class":62}," name",[45,344,301],{"class":58},[45,346,322],{"class":69},[45,348,349],{"class":58}," \u002F>\n",[45,351,352,354,356,359,361],{"class":47,"line":118},[45,353,329],{"class":58},[45,355,19],{"class":145},[45,357,358],{"class":58},">Basic\u003C\u002F",[45,360,19],{"class":145},[45,362,307],{"class":58},[45,364,366,368,370,373,375],{"class":47,"line":365},5,[45,367,329],{"class":58},[45,369,45],{"class":145},[45,371,372],{"class":58},">$0\u002Fmo\u003C\u002F",[45,374,45],{"class":145},[45,376,307],{"class":58},[45,378,380,383,385],{"class":47,"line":379},6,[45,381,382],{"class":58},"  \u003C\u002F",[45,384,315],{"class":145},[45,386,307],{"class":58},[45,388,390,392,394,396,398,400],{"class":47,"line":389},7,[45,391,312],{"class":58},[45,393,315],{"class":145},[45,395,298],{"class":62},[45,397,301],{"class":58},[45,399,322],{"class":69},[45,401,307],{"class":58},[45,403,405,407,409,411,413,415,417,419,421,424],{"class":47,"line":404},8,[45,406,329],{"class":58},[45,408,146],{"class":145},[45,410,334],{"class":62},[45,412,301],{"class":58},[45,414,339],{"class":69},[45,416,342],{"class":62},[45,418,301],{"class":58},[45,420,322],{"class":69},[45,422,423],{"class":62}," checked",[45,425,349],{"class":58},[45,427,429,431,433,436,438],{"class":47,"line":428},9,[45,430,329],{"class":58},[45,432,19],{"class":145},[45,434,435],{"class":58},">Pro\u003C\u002F",[45,437,19],{"class":145},[45,439,307],{"class":58},[45,441,443,445,447,450,452],{"class":47,"line":442},10,[45,444,329],{"class":58},[45,446,45],{"class":145},[45,448,449],{"class":58},">$9\u002Fmo\u003C\u002F",[45,451,45],{"class":145},[45,453,307],{"class":58},[45,455,457,459,461],{"class":47,"line":456},11,[45,458,382],{"class":58},[45,460,315],{"class":145},[45,462,307],{"class":58},[45,464,466,468,470,472,474,476],{"class":47,"line":465},12,[45,467,312],{"class":58},[45,469,315],{"class":145},[45,471,298],{"class":62},[45,473,301],{"class":58},[45,475,322],{"class":69},[45,477,307],{"class":58},[45,479,481,483,485,487,489,491,493,495,497],{"class":47,"line":480},13,[45,482,329],{"class":58},[45,484,146],{"class":145},[45,486,334],{"class":62},[45,488,301],{"class":58},[45,490,339],{"class":69},[45,492,342],{"class":62},[45,494,301],{"class":58},[45,496,322],{"class":69},[45,498,349],{"class":58},[45,500,502,504,506,509,511],{"class":47,"line":501},14,[45,503,329],{"class":58},[45,505,19],{"class":145},[45,507,508],{"class":58},">Team\u003C\u002F",[45,510,19],{"class":145},[45,512,307],{"class":58},[45,514,516,518,520,523,525],{"class":47,"line":515},15,[45,517,329],{"class":58},[45,519,45],{"class":145},[45,521,522],{"class":58},">$29\u002Fmo\u003C\u002F",[45,524,45],{"class":145},[45,526,307],{"class":58},[45,528,530,532,534],{"class":47,"line":529},16,[45,531,382],{"class":58},[45,533,315],{"class":145},[45,535,307],{"class":58},[45,537,539,542,544],{"class":47,"line":538},17,[45,540,541],{"class":58},"\u003C\u002F",[45,543,295],{"class":145},[45,545,307],{"class":58},[36,547,549],{"className":131,"code":548,"language":133,"meta":41,"style":41},".plans { display: flex; gap: 10px; flex-wrap: wrap; }\n.plan { display: grid; gap: 4px; padding: 14px 18px; border: 2px solid #ddd; border-radius: 12px; cursor: pointer; min-width: 110px; transition: all 0.15s; }\n.plan input { margin: 0 0 4px; }\n.plan span { color: #666; font-size: 14px; }\n\n\u002F* The card that contains the checked radio *\u002F\n.plan:has(input:checked) {\n  border-color: #f59e0b;\n  background: #fffbeb;\n  transform: translateY(-2px);\n}\n",[24,550,551,594,706,733,763,769,774,787,798,810,830],{"__ignoreMap":41},[45,552,553,556,559,562,564,567,570,573,575,578,581,583,586,588,591],{"class":47,"line":48},[45,554,555],{"class":62},".plans",[45,557,558],{"class":58}," { ",[45,560,561],{"class":157},"display",[45,563,161],{"class":58},[45,565,566],{"class":157},"flex",[45,568,569],{"class":58},"; ",[45,571,572],{"class":157},"gap",[45,574,161],{"class":58},[45,576,577],{"class":157},"10",[45,579,580],{"class":83},"px",[45,582,569],{"class":58},[45,584,585],{"class":157},"flex-wrap",[45,587,161],{"class":58},[45,589,590],{"class":157},"wrap",[45,592,593],{"class":58},"; }\n",[45,595,596,599,601,603,605,608,610,612,614,617,619,621,624,626,629,631,634,636,638,641,643,646,648,651,654,656,659,661,664,666,668,671,673,676,678,681,683,686,688,690,693,695,698,701,704],{"class":47,"line":55},[45,597,598],{"class":62},".plan",[45,600,558],{"class":58},[45,602,561],{"class":157},[45,604,161],{"class":58},[45,606,607],{"class":157},"grid",[45,609,569],{"class":58},[45,611,572],{"class":157},[45,613,161],{"class":58},[45,615,616],{"class":157},"4",[45,618,580],{"class":83},[45,620,569],{"class":58},[45,622,623],{"class":157},"padding",[45,625,161],{"class":58},[45,627,628],{"class":157},"14",[45,630,580],{"class":83},[45,632,633],{"class":157}," 18",[45,635,580],{"class":83},[45,637,569],{"class":58},[45,639,640],{"class":157},"border",[45,642,161],{"class":58},[45,644,645],{"class":157},"2",[45,647,580],{"class":83},[45,649,650],{"class":157}," solid",[45,652,653],{"class":157}," #ddd",[45,655,569],{"class":58},[45,657,658],{"class":157},"border-radius",[45,660,161],{"class":58},[45,662,663],{"class":157},"12",[45,665,580],{"class":83},[45,667,569],{"class":58},[45,669,670],{"class":157},"cursor",[45,672,161],{"class":58},[45,674,675],{"class":157},"pointer",[45,677,569],{"class":58},[45,679,680],{"class":157},"min-width",[45,682,161],{"class":58},[45,684,685],{"class":157},"110",[45,687,580],{"class":83},[45,689,569],{"class":58},[45,691,692],{"class":157},"transition",[45,694,161],{"class":58},[45,696,697],{"class":157},"all",[45,699,700],{"class":157}," 0.15",[45,702,703],{"class":83},"s",[45,705,593],{"class":58},[45,707,708,710,713,715,718,720,723,726,729,731],{"class":47,"line":90},[45,709,598],{"class":62},[45,711,712],{"class":145}," input",[45,714,558],{"class":58},[45,716,717],{"class":157},"margin",[45,719,161],{"class":58},[45,721,722],{"class":157},"0",[45,724,725],{"class":157}," 0",[45,727,728],{"class":157}," 4",[45,730,580],{"class":83},[45,732,593],{"class":58},[45,734,735,737,740,742,745,747,750,752,755,757,759,761],{"class":47,"line":118},[45,736,598],{"class":62},[45,738,739],{"class":145}," span",[45,741,558],{"class":58},[45,743,744],{"class":157},"color",[45,746,161],{"class":58},[45,748,749],{"class":157},"#666",[45,751,569],{"class":58},[45,753,754],{"class":157},"font-size",[45,756,161],{"class":58},[45,758,628],{"class":157},[45,760,580],{"class":83},[45,762,593],{"class":58},[45,764,765],{"class":47,"line":365},[45,766,768],{"emptyLinePlaceholder":767},true,"\n",[45,770,771],{"class":47,"line":379},[45,772,773],{"class":51},"\u002F* The card that contains the checked radio *\u002F\n",[45,775,776,779,781,783,785],{"class":47,"line":389},[45,777,778],{"class":62},".plan:has",[45,780,66],{"class":58},[45,782,146],{"class":145},[45,784,149],{"class":62},[45,786,152],{"class":58},[45,788,789,791,793,796],{"class":47,"line":404},[45,790,158],{"class":157},[45,792,161],{"class":58},[45,794,795],{"class":157},"#f59e0b",[45,797,167],{"class":58},[45,799,800,803,805,808],{"class":47,"line":428},[45,801,802],{"class":157},"  background",[45,804,161],{"class":58},[45,806,807],{"class":157},"#fffbeb",[45,809,167],{"class":58},[45,811,812,815,817,820,822,825,827],{"class":47,"line":442},[45,813,814],{"class":157},"  transform",[45,816,161],{"class":58},[45,818,819],{"class":157},"translateY",[45,821,66],{"class":58},[45,823,824],{"class":157},"-2",[45,826,580],{"class":83},[45,828,829],{"class":58},");\n",[45,831,832],{"class":47,"line":456},[45,833,172],{"class":58},[15,835,836,837,839,840,842,843,846],{},"It all comes down to the last rule: select the ",[24,838,598],{}," that ",[19,841,30],{}," an ",[24,844,845],{},"input:checked",".",[266,848],{},[10,850,852],{"id":851},"example-2-the-whole-form-reacts-to-a-bad-input","Example 2. The whole form reacts to a bad input",[15,854,855,857],{},[24,856,127],{}," pairs especially well with form state. In the example below, type anything into the email field and then click somewhere else.",[279,859,860,999],{},[36,861,863],{"className":283,"code":862,"language":285,"meta":41,"style":41},"\u003Cform class=\"signup\">\n  \u003Cdiv class=\"field\">\n    \u003Clabel for=\"email\">Email\u003C\u002Flabel>\n    \u003Cinput id=\"email\" type=\"email\" required placeholder=\"you@example.com\" \u002F>\n  \u003C\u002Fdiv>\n  \u003Cp class=\"hint\">That doesn't look like a valid email.\u003C\u002Fp>\n  \u003Cbutton>Sign up\u003C\u002Fbutton>\n\u003C\u002Fform>\n",[24,864,865,881,896,917,949,957,977,991],{"__ignoreMap":41},[45,866,867,869,872,874,876,879],{"class":47,"line":48},[45,868,292],{"class":58},[45,870,871],{"class":145},"form",[45,873,298],{"class":62},[45,875,301],{"class":58},[45,877,878],{"class":69},"\"signup\"",[45,880,307],{"class":58},[45,882,883,885,887,889,891,894],{"class":47,"line":55},[45,884,312],{"class":58},[45,886,295],{"class":145},[45,888,298],{"class":62},[45,890,301],{"class":58},[45,892,893],{"class":69},"\"field\"",[45,895,307],{"class":58},[45,897,898,900,902,905,907,910,913,915],{"class":47,"line":90},[45,899,329],{"class":58},[45,901,315],{"class":145},[45,903,904],{"class":62}," for",[45,906,301],{"class":58},[45,908,909],{"class":69},"\"email\"",[45,911,912],{"class":58},">Email\u003C\u002F",[45,914,315],{"class":145},[45,916,307],{"class":58},[45,918,919,921,923,926,928,930,932,934,936,939,942,944,947],{"class":47,"line":118},[45,920,329],{"class":58},[45,922,146],{"class":145},[45,924,925],{"class":62}," id",[45,927,301],{"class":58},[45,929,909],{"class":69},[45,931,334],{"class":62},[45,933,301],{"class":58},[45,935,909],{"class":69},[45,937,938],{"class":62}," required",[45,940,941],{"class":62}," placeholder",[45,943,301],{"class":58},[45,945,946],{"class":69},"\"you@example.com\"",[45,948,349],{"class":58},[45,950,951,953,955],{"class":47,"line":365},[45,952,382],{"class":58},[45,954,295],{"class":145},[45,956,307],{"class":58},[45,958,959,961,963,965,967,970,973,975],{"class":47,"line":379},[45,960,312],{"class":58},[45,962,15],{"class":145},[45,964,298],{"class":62},[45,966,301],{"class":58},[45,968,969],{"class":69},"\"hint\"",[45,971,972],{"class":58},">That doesn't look like a valid email.\u003C\u002F",[45,974,15],{"class":145},[45,976,307],{"class":58},[45,978,979,981,984,987,989],{"class":47,"line":389},[45,980,312],{"class":58},[45,982,983],{"class":145},"button",[45,985,986],{"class":58},">Sign up\u003C\u002F",[45,988,983],{"class":145},[45,990,307],{"class":58},[45,992,993,995,997],{"class":47,"line":404},[45,994,541],{"class":58},[45,996,871],{"class":145},[45,998,307],{"class":58},[36,1000,1002],{"className":131,"code":1001,"language":133,"meta":41,"style":41},".signup { display: grid; gap: 8px; max-width: 280px; padding: 16px; border: 2px solid #ddd; border-radius: 12px; }\n.field { display: grid; gap: 4px; }\ninput { font: inherit; padding: 6px 8px; }\n.hint { display: none; margin: 0; color: crimson; font-size: 14px; }\nbutton { font: inherit; padding: 6px; }\n\n\u002F* Change the label color while its input has focus *\u002F\n.field:has(input:focus) label { color: #f59e0b; font-weight: 700; }\n\n\u002F* When there's an invalid input: the form border, hint, and button change together *\u002F\n.signup:has(input:user-invalid) { border-color: crimson; }\n.signup:has(input:user-invalid) .hint { display: block; }\n.signup:has(input:user-invalid) button { opacity: 0.4; pointer-events: none; }\n",[24,1003,1004,1077,1102,1134,1177,1201,1205,1210,1246,1250,1255,1282,1309],{"__ignoreMap":41},[45,1005,1006,1009,1011,1013,1015,1017,1019,1021,1023,1026,1028,1030,1033,1035,1038,1040,1042,1044,1046,1049,1051,1053,1055,1057,1059,1061,1063,1065,1067,1069,1071,1073,1075],{"class":47,"line":48},[45,1007,1008],{"class":62},".signup",[45,1010,558],{"class":58},[45,1012,561],{"class":157},[45,1014,161],{"class":58},[45,1016,607],{"class":157},[45,1018,569],{"class":58},[45,1020,572],{"class":157},[45,1022,161],{"class":58},[45,1024,1025],{"class":157},"8",[45,1027,580],{"class":83},[45,1029,569],{"class":58},[45,1031,1032],{"class":157},"max-width",[45,1034,161],{"class":58},[45,1036,1037],{"class":157},"280",[45,1039,580],{"class":83},[45,1041,569],{"class":58},[45,1043,623],{"class":157},[45,1045,161],{"class":58},[45,1047,1048],{"class":157},"16",[45,1050,580],{"class":83},[45,1052,569],{"class":58},[45,1054,640],{"class":157},[45,1056,161],{"class":58},[45,1058,645],{"class":157},[45,1060,580],{"class":83},[45,1062,650],{"class":157},[45,1064,653],{"class":157},[45,1066,569],{"class":58},[45,1068,658],{"class":157},[45,1070,161],{"class":58},[45,1072,663],{"class":157},[45,1074,580],{"class":83},[45,1076,593],{"class":58},[45,1078,1079,1082,1084,1086,1088,1090,1092,1094,1096,1098,1100],{"class":47,"line":55},[45,1080,1081],{"class":62},".field",[45,1083,558],{"class":58},[45,1085,561],{"class":157},[45,1087,161],{"class":58},[45,1089,607],{"class":157},[45,1091,569],{"class":58},[45,1093,572],{"class":157},[45,1095,161],{"class":58},[45,1097,616],{"class":157},[45,1099,580],{"class":83},[45,1101,593],{"class":58},[45,1103,1104,1106,1108,1111,1113,1116,1118,1120,1122,1125,1127,1130,1132],{"class":47,"line":90},[45,1105,146],{"class":145},[45,1107,558],{"class":58},[45,1109,1110],{"class":157},"font",[45,1112,161],{"class":58},[45,1114,1115],{"class":157},"inherit",[45,1117,569],{"class":58},[45,1119,623],{"class":157},[45,1121,161],{"class":58},[45,1123,1124],{"class":157},"6",[45,1126,580],{"class":83},[45,1128,1129],{"class":157}," 8",[45,1131,580],{"class":83},[45,1133,593],{"class":58},[45,1135,1136,1139,1141,1143,1145,1148,1150,1152,1154,1156,1158,1160,1162,1165,1167,1169,1171,1173,1175],{"class":47,"line":118},[45,1137,1138],{"class":62},".hint",[45,1140,558],{"class":58},[45,1142,561],{"class":157},[45,1144,161],{"class":58},[45,1146,1147],{"class":157},"none",[45,1149,569],{"class":58},[45,1151,717],{"class":157},[45,1153,161],{"class":58},[45,1155,722],{"class":157},[45,1157,569],{"class":58},[45,1159,744],{"class":157},[45,1161,161],{"class":58},[45,1163,1164],{"class":157},"crimson",[45,1166,569],{"class":58},[45,1168,754],{"class":157},[45,1170,161],{"class":58},[45,1172,628],{"class":157},[45,1174,580],{"class":83},[45,1176,593],{"class":58},[45,1178,1179,1181,1183,1185,1187,1189,1191,1193,1195,1197,1199],{"class":47,"line":365},[45,1180,983],{"class":145},[45,1182,558],{"class":58},[45,1184,1110],{"class":157},[45,1186,161],{"class":58},[45,1188,1115],{"class":157},[45,1190,569],{"class":58},[45,1192,623],{"class":157},[45,1194,161],{"class":58},[45,1196,1124],{"class":157},[45,1198,580],{"class":83},[45,1200,593],{"class":58},[45,1202,1203],{"class":47,"line":379},[45,1204,768],{"emptyLinePlaceholder":767},[45,1206,1207],{"class":47,"line":389},[45,1208,1209],{"class":51},"\u002F* Change the label color while its input has focus *\u002F\n",[45,1211,1212,1215,1217,1219,1222,1224,1226,1228,1230,1232,1234,1236,1239,1241,1244],{"class":47,"line":404},[45,1213,1214],{"class":62},".field:has",[45,1216,66],{"class":58},[45,1218,146],{"class":145},[45,1220,1221],{"class":62},":focus",[45,1223,80],{"class":58},[45,1225,315],{"class":145},[45,1227,558],{"class":58},[45,1229,744],{"class":157},[45,1231,161],{"class":58},[45,1233,795],{"class":157},[45,1235,569],{"class":58},[45,1237,1238],{"class":157},"font-weight",[45,1240,161],{"class":58},[45,1242,1243],{"class":157},"700",[45,1245,593],{"class":58},[45,1247,1248],{"class":47,"line":428},[45,1249,768],{"emptyLinePlaceholder":767},[45,1251,1252],{"class":47,"line":442},[45,1253,1254],{"class":51},"\u002F* When there's an invalid input: the form border, hint, and button change together *\u002F\n",[45,1256,1257,1260,1262,1264,1267,1270,1273,1276,1278,1280],{"class":47,"line":456},[45,1258,1259],{"class":62},".signup:has",[45,1261,66],{"class":58},[45,1263,146],{"class":145},[45,1265,1266],{"class":58},":",[45,1268,1269],{"class":145},"user-invalid",[45,1271,1272],{"class":58},") { ",[45,1274,1275],{"class":157},"border-color",[45,1277,161],{"class":58},[45,1279,1164],{"class":157},[45,1281,593],{"class":58},[45,1283,1284,1286,1288,1290,1292,1294,1296,1298,1300,1302,1304,1307],{"class":47,"line":465},[45,1285,1259],{"class":62},[45,1287,66],{"class":58},[45,1289,146],{"class":145},[45,1291,1266],{"class":58},[45,1293,1269],{"class":145},[45,1295,80],{"class":58},[45,1297,1138],{"class":62},[45,1299,558],{"class":58},[45,1301,561],{"class":157},[45,1303,161],{"class":58},[45,1305,1306],{"class":157},"block",[45,1308,593],{"class":58},[45,1310,1311,1313,1315,1317,1319,1321,1323,1325,1327,1330,1332,1335,1337,1340,1342,1344],{"class":47,"line":480},[45,1312,1259],{"class":62},[45,1314,66],{"class":58},[45,1316,146],{"class":145},[45,1318,1266],{"class":58},[45,1320,1269],{"class":145},[45,1322,80],{"class":58},[45,1324,983],{"class":145},[45,1326,558],{"class":58},[45,1328,1329],{"class":157},"opacity",[45,1331,161],{"class":58},[45,1333,1334],{"class":157},"0.4",[45,1336,569],{"class":58},[45,1338,1339],{"class":157},"pointer-events",[45,1341,161],{"class":58},[45,1343,1147],{"class":157},[45,1345,593],{"class":58},[15,1347,1348,1349,1352],{},"The state of a single input changes ",[19,1350,1351],{},"the label, the form border, the hint, and the button"," all at once. This used to mean listening for input events, building state, and toggling classes on each element.",[1354,1355,1356],"tip",{},[174,1357,1358],{},[15,1359,1360,1363,1364,1367,1368,1370],{},[24,1361,1362],{},":user-invalid"," is a pseudo-class that only applies after the user has interacted with the field. With ",[24,1365,1366],{},":invalid",", every empty field is marked \"wrong\" the moment the page loads, so ",[24,1369,1362],{}," feels more natural for showing errors.",[266,1372],{},[10,1374,1376],{"id":1375},"example-3-selecting-previous-siblings-a-star-rating","Example 3. Selecting previous siblings: a star rating",[15,1378,1379,1380,1383,1384,1387,1388,1391,1392,1395,1396,1398],{},"CSS's ",[24,1381,1382],{},"~"," and ",[24,1385,1386],{},"+"," combinators can only select ",[19,1389,1390],{},"following"," siblings. That's why it was hard to color \"the hovered star and ",[19,1393,1394],{},"the stars before it","\" in a star rating. With ",[24,1397,127],{},", you can select backwards too. Hover over the stars.",[279,1400,1401,1495],{},[36,1402,1404],{"className":283,"code":1403,"language":285,"meta":41,"style":41},"\u003Cdiv class=\"stars\">\n  \u003Cspan>★\u003C\u002Fspan>\u003Cspan>★\u003C\u002Fspan>\u003Cspan>★\u003C\u002Fspan>\u003Cspan>★\u003C\u002Fspan>\u003Cspan>★\u003C\u002Fspan>\n\u003C\u002Fdiv>\n\u003Cp class=\"caption\">Hover over the stars\u003C\u002Fp>\n",[24,1405,1406,1421,1467,1475],{"__ignoreMap":41},[45,1407,1408,1410,1412,1414,1416,1419],{"class":47,"line":48},[45,1409,292],{"class":58},[45,1411,295],{"class":145},[45,1413,298],{"class":62},[45,1415,301],{"class":58},[45,1417,1418],{"class":69},"\"stars\"",[45,1420,307],{"class":58},[45,1422,1423,1425,1427,1430,1432,1435,1437,1439,1441,1443,1445,1447,1449,1451,1453,1455,1457,1459,1461,1463,1465],{"class":47,"line":55},[45,1424,312],{"class":58},[45,1426,45],{"class":145},[45,1428,1429],{"class":58},">★\u003C\u002F",[45,1431,45],{"class":145},[45,1433,1434],{"class":58},">\u003C",[45,1436,45],{"class":145},[45,1438,1429],{"class":58},[45,1440,45],{"class":145},[45,1442,1434],{"class":58},[45,1444,45],{"class":145},[45,1446,1429],{"class":58},[45,1448,45],{"class":145},[45,1450,1434],{"class":58},[45,1452,45],{"class":145},[45,1454,1429],{"class":58},[45,1456,45],{"class":145},[45,1458,1434],{"class":58},[45,1460,45],{"class":145},[45,1462,1429],{"class":58},[45,1464,45],{"class":145},[45,1466,307],{"class":58},[45,1468,1469,1471,1473],{"class":47,"line":90},[45,1470,541],{"class":58},[45,1472,295],{"class":145},[45,1474,307],{"class":58},[45,1476,1477,1479,1481,1483,1485,1488,1491,1493],{"class":47,"line":118},[45,1478,292],{"class":58},[45,1480,15],{"class":145},[45,1482,298],{"class":62},[45,1484,301],{"class":58},[45,1486,1487],{"class":69},"\"caption\"",[45,1489,1490],{"class":58},">Hover over the stars\u003C\u002F",[45,1492,15],{"class":145},[45,1494,307],{"class":58},[36,1496,1498],{"className":131,"code":1497,"language":133,"meta":41,"style":41},".stars { font-size: 40px; color: #ddd; cursor: pointer; }\n.stars span { transition: color 0.1s; }\n.caption { color: #666; margin: 4px 0 0; }\n\n\u002F* 1) If any star is hovered, first make all of them gold *\u002F\n.stars:has(span:hover) span { color: #f59e0b; }\n\n\u002F* 2) Then turn the stars *after* the hovered one back to gray *\u002F\n.stars span:hover ~ span { color: #ddd; }\n",[24,1499,1500,1535,1556,1585,1589,1594,1620,1624,1629],{"__ignoreMap":41},[45,1501,1502,1505,1507,1509,1511,1514,1516,1518,1520,1522,1525,1527,1529,1531,1533],{"class":47,"line":48},[45,1503,1504],{"class":62},".stars",[45,1506,558],{"class":58},[45,1508,754],{"class":157},[45,1510,161],{"class":58},[45,1512,1513],{"class":157},"40",[45,1515,580],{"class":83},[45,1517,569],{"class":58},[45,1519,744],{"class":157},[45,1521,161],{"class":58},[45,1523,1524],{"class":157},"#ddd",[45,1526,569],{"class":58},[45,1528,670],{"class":157},[45,1530,161],{"class":58},[45,1532,675],{"class":157},[45,1534,593],{"class":58},[45,1536,1537,1539,1541,1543,1545,1547,1549,1552,1554],{"class":47,"line":55},[45,1538,1504],{"class":62},[45,1540,739],{"class":145},[45,1542,558],{"class":58},[45,1544,692],{"class":157},[45,1546,161],{"class":58},[45,1548,744],{"class":157},[45,1550,1551],{"class":157}," 0.1",[45,1553,703],{"class":83},[45,1555,593],{"class":58},[45,1557,1558,1561,1563,1565,1567,1569,1571,1573,1575,1577,1579,1581,1583],{"class":47,"line":90},[45,1559,1560],{"class":62},".caption",[45,1562,558],{"class":58},[45,1564,744],{"class":157},[45,1566,161],{"class":58},[45,1568,749],{"class":157},[45,1570,569],{"class":58},[45,1572,717],{"class":157},[45,1574,161],{"class":58},[45,1576,616],{"class":157},[45,1578,580],{"class":83},[45,1580,725],{"class":157},[45,1582,725],{"class":157},[45,1584,593],{"class":58},[45,1586,1587],{"class":47,"line":118},[45,1588,768],{"emptyLinePlaceholder":767},[45,1590,1591],{"class":47,"line":365},[45,1592,1593],{"class":51},"\u002F* 1) If any star is hovered, first make all of them gold *\u002F\n",[45,1595,1596,1599,1601,1603,1606,1608,1610,1612,1614,1616,1618],{"class":47,"line":379},[45,1597,1598],{"class":62},".stars:has",[45,1600,66],{"class":58},[45,1602,45],{"class":145},[45,1604,1605],{"class":62},":hover",[45,1607,80],{"class":58},[45,1609,45],{"class":145},[45,1611,558],{"class":58},[45,1613,744],{"class":157},[45,1615,161],{"class":58},[45,1617,795],{"class":157},[45,1619,593],{"class":58},[45,1621,1622],{"class":47,"line":389},[45,1623,768],{"emptyLinePlaceholder":767},[45,1625,1626],{"class":47,"line":404},[45,1627,1628],{"class":51},"\u002F* 2) Then turn the stars *after* the hovered one back to gray *\u002F\n",[45,1630,1631,1633,1635,1637,1640,1642,1644,1646,1648,1650],{"class":47,"line":428},[45,1632,1504],{"class":62},[45,1634,739],{"class":145},[45,1636,1605],{"class":62},[45,1638,1639],{"class":83}," ~",[45,1641,739],{"class":145},[45,1643,558],{"class":58},[45,1645,744],{"class":157},[45,1647,161],{"class":58},[45,1649,1524],{"class":157},[45,1651,593],{"class":58},[15,1653,1654],{},"The result: stars fill up to the one you're hovering. You can also express it directly with sibling relationships:",[36,1656,1658],{"className":131,"code":1657,"language":133,"meta":41,"style":41},"\u002F* An element whose very next sibling is hovered = the sibling right before the hovered one *\u002F\nli:has(+ li:hover) {\n  transform: scale(1.1);\n}\n",[24,1659,1660,1665,1684,1700],{"__ignoreMap":41},[45,1661,1662],{"class":47,"line":48},[45,1663,1664],{"class":51},"\u002F* An element whose very next sibling is hovered = the sibling right before the hovered one *\u002F\n",[45,1666,1667,1670,1673,1675,1677,1680,1682],{"class":47,"line":55},[45,1668,1669],{"class":145},"li",[45,1671,1672],{"class":62},":has",[45,1674,66],{"class":58},[45,1676,1386],{"class":83},[45,1678,1679],{"class":145}," li",[45,1681,1605],{"class":62},[45,1683,152],{"class":58},[45,1685,1686,1688,1690,1693,1695,1698],{"class":47,"line":90},[45,1687,814],{"class":157},[45,1689,161],{"class":58},[45,1691,1692],{"class":157},"scale",[45,1694,66],{"class":58},[45,1696,1697],{"class":157},"1.1",[45,1699,829],{"class":58},[45,1701,1702],{"class":47,"line":118},[45,1703,172],{"class":58},[15,1705,1706],{},"That's how you build a macOS Dock-style effect where the icons on either side of the hovered one grow too.",[266,1708],{},[10,1710,1712],{"id":1711},"example-4-changing-layout-based-on-item-count","Example 4. Changing layout based on item count",[15,1714,1715],{},"Conditions like \"two columns once there are four or more items\" are possible in pure CSS. Use the buttons below to add and remove items. (JavaScript only adds and removes items; CSS handles the layout switch.)",[279,1717,1718,1849,2107],{},[36,1719,1721],{"className":283,"code":1720,"language":285,"meta":41,"style":41},"\u003Cdiv class=\"controls\">\n  \u003Cbutton id=\"add\">Add item\u003C\u002Fbutton>\n  \u003Cbutton id=\"remove\">Remove item\u003C\u002Fbutton>\n\u003C\u002Fdiv>\n\u003Cul class=\"list\">\n  \u003Cli>Item 1\u003C\u002Fli>\n  \u003Cli>Item 2\u003C\u002Fli>\n  \u003Cli>Item 3\u003C\u002Fli>\n\u003C\u002Ful>\n",[24,1722,1723,1738,1758,1778,1786,1802,1815,1828,1841],{"__ignoreMap":41},[45,1724,1725,1727,1729,1731,1733,1736],{"class":47,"line":48},[45,1726,292],{"class":58},[45,1728,295],{"class":145},[45,1730,298],{"class":62},[45,1732,301],{"class":58},[45,1734,1735],{"class":69},"\"controls\"",[45,1737,307],{"class":58},[45,1739,1740,1742,1744,1746,1748,1751,1754,1756],{"class":47,"line":55},[45,1741,312],{"class":58},[45,1743,983],{"class":145},[45,1745,925],{"class":62},[45,1747,301],{"class":58},[45,1749,1750],{"class":69},"\"add\"",[45,1752,1753],{"class":58},">Add item\u003C\u002F",[45,1755,983],{"class":145},[45,1757,307],{"class":58},[45,1759,1760,1762,1764,1766,1768,1771,1774,1776],{"class":47,"line":90},[45,1761,312],{"class":58},[45,1763,983],{"class":145},[45,1765,925],{"class":62},[45,1767,301],{"class":58},[45,1769,1770],{"class":69},"\"remove\"",[45,1772,1773],{"class":58},">Remove item\u003C\u002F",[45,1775,983],{"class":145},[45,1777,307],{"class":58},[45,1779,1780,1782,1784],{"class":47,"line":118},[45,1781,541],{"class":58},[45,1783,295],{"class":145},[45,1785,307],{"class":58},[45,1787,1788,1790,1793,1795,1797,1800],{"class":47,"line":365},[45,1789,292],{"class":58},[45,1791,1792],{"class":145},"ul",[45,1794,298],{"class":62},[45,1796,301],{"class":58},[45,1798,1799],{"class":69},"\"list\"",[45,1801,307],{"class":58},[45,1803,1804,1806,1808,1811,1813],{"class":47,"line":379},[45,1805,312],{"class":58},[45,1807,1669],{"class":145},[45,1809,1810],{"class":58},">Item 1\u003C\u002F",[45,1812,1669],{"class":145},[45,1814,307],{"class":58},[45,1816,1817,1819,1821,1824,1826],{"class":47,"line":389},[45,1818,312],{"class":58},[45,1820,1669],{"class":145},[45,1822,1823],{"class":58},">Item 2\u003C\u002F",[45,1825,1669],{"class":145},[45,1827,307],{"class":58},[45,1829,1830,1832,1834,1837,1839],{"class":47,"line":404},[45,1831,312],{"class":58},[45,1833,1669],{"class":145},[45,1835,1836],{"class":58},">Item 3\u003C\u002F",[45,1838,1669],{"class":145},[45,1840,307],{"class":58},[45,1842,1843,1845,1847],{"class":47,"line":428},[45,1844,541],{"class":58},[45,1846,1792],{"class":145},[45,1848,307],{"class":58},[36,1850,1852],{"className":131,"code":1851,"language":133,"meta":41,"style":41},".controls { display: flex; gap: 6px; margin-bottom: 10px; }\nbutton { font: inherit; padding: 4px 10px; }\n.list { list-style: none; padding: 0; margin: 0; display: grid; gap: 6px; }\n.list li { padding: 8px 12px; border-radius: 8px; background: #f4f4f5; }\n\n\u002F* If a 4th item exists = 4 or more items: two columns *\u002F\n.list:has(> li:nth-child(4)) { grid-template-columns: 1fr 1fr; }\n\n\u002F* 7 or more: three columns *\u002F\n.list:has(> li:nth-child(7)) { grid-template-columns: 1fr 1fr 1fr; }\n",[24,1853,1854,1890,1919,1969,2012,2016,2021,2061,2065,2070],{"__ignoreMap":41},[45,1855,1856,1859,1861,1863,1865,1867,1869,1871,1873,1875,1877,1879,1882,1884,1886,1888],{"class":47,"line":48},[45,1857,1858],{"class":62},".controls",[45,1860,558],{"class":58},[45,1862,561],{"class":157},[45,1864,161],{"class":58},[45,1866,566],{"class":157},[45,1868,569],{"class":58},[45,1870,572],{"class":157},[45,1872,161],{"class":58},[45,1874,1124],{"class":157},[45,1876,580],{"class":83},[45,1878,569],{"class":58},[45,1880,1881],{"class":157},"margin-bottom",[45,1883,161],{"class":58},[45,1885,577],{"class":157},[45,1887,580],{"class":83},[45,1889,593],{"class":58},[45,1891,1892,1894,1896,1898,1900,1902,1904,1906,1908,1910,1912,1915,1917],{"class":47,"line":55},[45,1893,983],{"class":145},[45,1895,558],{"class":58},[45,1897,1110],{"class":157},[45,1899,161],{"class":58},[45,1901,1115],{"class":157},[45,1903,569],{"class":58},[45,1905,623],{"class":157},[45,1907,161],{"class":58},[45,1909,616],{"class":157},[45,1911,580],{"class":83},[45,1913,1914],{"class":157}," 10",[45,1916,580],{"class":83},[45,1918,593],{"class":58},[45,1920,1921,1924,1926,1929,1931,1933,1935,1937,1939,1941,1943,1945,1947,1949,1951,1953,1955,1957,1959,1961,1963,1965,1967],{"class":47,"line":90},[45,1922,1923],{"class":62},".list",[45,1925,558],{"class":58},[45,1927,1928],{"class":157},"list-style",[45,1930,161],{"class":58},[45,1932,1147],{"class":157},[45,1934,569],{"class":58},[45,1936,623],{"class":157},[45,1938,161],{"class":58},[45,1940,722],{"class":157},[45,1942,569],{"class":58},[45,1944,717],{"class":157},[45,1946,161],{"class":58},[45,1948,722],{"class":157},[45,1950,569],{"class":58},[45,1952,561],{"class":157},[45,1954,161],{"class":58},[45,1956,607],{"class":157},[45,1958,569],{"class":58},[45,1960,572],{"class":157},[45,1962,161],{"class":58},[45,1964,1124],{"class":157},[45,1966,580],{"class":83},[45,1968,593],{"class":58},[45,1970,1971,1973,1975,1977,1979,1981,1983,1985,1988,1990,1992,1994,1996,1998,2000,2002,2005,2007,2010],{"class":47,"line":118},[45,1972,1923],{"class":62},[45,1974,1679],{"class":145},[45,1976,558],{"class":58},[45,1978,623],{"class":157},[45,1980,161],{"class":58},[45,1982,1025],{"class":157},[45,1984,580],{"class":83},[45,1986,1987],{"class":157}," 12",[45,1989,580],{"class":83},[45,1991,569],{"class":58},[45,1993,658],{"class":157},[45,1995,161],{"class":58},[45,1997,1025],{"class":157},[45,1999,580],{"class":83},[45,2001,569],{"class":58},[45,2003,2004],{"class":157},"background",[45,2006,161],{"class":58},[45,2008,2009],{"class":157},"#f4f4f5",[45,2011,593],{"class":58},[45,2013,2014],{"class":47,"line":365},[45,2015,768],{"emptyLinePlaceholder":767},[45,2017,2018],{"class":47,"line":379},[45,2019,2020],{"class":51},"\u002F* If a 4th item exists = 4 or more items: two columns *\u002F\n",[45,2022,2023,2026,2028,2031,2033,2036,2038,2040,2043,2046,2048,2051,2054,2057,2059],{"class":47,"line":389},[45,2024,2025],{"class":62},".list:has",[45,2027,66],{"class":58},[45,2029,2030],{"class":83},">",[45,2032,1679],{"class":145},[45,2034,2035],{"class":62},":nth-child",[45,2037,66],{"class":58},[45,2039,616],{"class":157},[45,2041,2042],{"class":58},")) { ",[45,2044,2045],{"class":157},"grid-template-columns",[45,2047,161],{"class":58},[45,2049,2050],{"class":157},"1",[45,2052,2053],{"class":83},"fr",[45,2055,2056],{"class":157}," 1",[45,2058,2053],{"class":83},[45,2060,593],{"class":58},[45,2062,2063],{"class":47,"line":404},[45,2064,768],{"emptyLinePlaceholder":767},[45,2066,2067],{"class":47,"line":428},[45,2068,2069],{"class":51},"\u002F* 7 or more: three columns *\u002F\n",[45,2071,2072,2074,2076,2078,2080,2082,2084,2087,2089,2091,2093,2095,2097,2099,2101,2103,2105],{"class":47,"line":442},[45,2073,2025],{"class":62},[45,2075,66],{"class":58},[45,2077,2030],{"class":83},[45,2079,1679],{"class":145},[45,2081,2035],{"class":62},[45,2083,66],{"class":58},[45,2085,2086],{"class":157},"7",[45,2088,2042],{"class":58},[45,2090,2045],{"class":157},[45,2092,161],{"class":58},[45,2094,2050],{"class":157},[45,2096,2053],{"class":83},[45,2098,2056],{"class":157},[45,2100,2053],{"class":83},[45,2102,2056],{"class":157},[45,2104,2053],{"class":83},[45,2106,593],{"class":58},[36,2108,2110],{"className":38,"code":2109,"language":40,"meta":41,"style":41},"const list = document.querySelector(\".list\");\ndocument.querySelector(\"#add\").addEventListener(\"click\", () => {\n  const li = document.createElement(\"li\");\n  li.textContent = `Item ${list.children.length + 1}`;\n  list.append(li);\n});\ndocument.querySelector(\"#remove\").addEventListener(\"click\", () => list.lastElementChild?.remove());\n",[24,2111,2112,2136,2165,2186,2219,2230,2234],{"__ignoreMap":41},[45,2113,2114,2117,2120,2123,2126,2129,2131,2134],{"class":47,"line":48},[45,2115,2116],{"class":83},"const",[45,2118,2119],{"class":157}," list",[45,2121,2122],{"class":83}," =",[45,2124,2125],{"class":58}," document.",[45,2127,2128],{"class":62},"querySelector",[45,2130,66],{"class":58},[45,2132,2133],{"class":69},"\".list\"",[45,2135,829],{"class":58},[45,2137,2138,2141,2143,2145,2148,2151,2153,2155,2158,2161,2163],{"class":47,"line":55},[45,2139,2140],{"class":58},"document.",[45,2142,2128],{"class":62},[45,2144,66],{"class":58},[45,2146,2147],{"class":69},"\"#add\"",[45,2149,2150],{"class":58},").",[45,2152,63],{"class":62},[45,2154,66],{"class":58},[45,2156,2157],{"class":69},"\"click\"",[45,2159,2160],{"class":58},", () ",[45,2162,84],{"class":83},[45,2164,87],{"class":58},[45,2166,2167,2170,2172,2174,2176,2179,2181,2184],{"class":47,"line":90},[45,2168,2169],{"class":83},"  const",[45,2171,1679],{"class":157},[45,2173,2122],{"class":83},[45,2175,2125],{"class":58},[45,2177,2178],{"class":62},"createElement",[45,2180,66],{"class":58},[45,2182,2183],{"class":69},"\"li\"",[45,2185,829],{"class":58},[45,2187,2188,2191,2193,2196,2199,2201,2204,2206,2209,2212,2214,2217],{"class":47,"line":118},[45,2189,2190],{"class":58},"  li.textContent ",[45,2192,301],{"class":83},[45,2194,2195],{"class":69}," `Item ${",[45,2197,2198],{"class":58},"list",[45,2200,846],{"class":69},[45,2202,2203],{"class":58},"children",[45,2205,846],{"class":69},[45,2207,2208],{"class":157},"length",[45,2210,2211],{"class":83}," +",[45,2213,2056],{"class":157},[45,2215,2216],{"class":69},"}`",[45,2218,167],{"class":58},[45,2220,2221,2224,2227],{"class":47,"line":365},[45,2222,2223],{"class":58},"  list.",[45,2225,2226],{"class":62},"append",[45,2228,2229],{"class":58},"(li);\n",[45,2231,2232],{"class":47,"line":379},[45,2233,121],{"class":58},[45,2235,2236,2238,2240,2242,2245,2247,2249,2251,2253,2255,2257,2260,2263],{"class":47,"line":389},[45,2237,2140],{"class":58},[45,2239,2128],{"class":62},[45,2241,66],{"class":58},[45,2243,2244],{"class":69},"\"#remove\"",[45,2246,2150],{"class":58},[45,2248,63],{"class":62},[45,2250,66],{"class":58},[45,2252,2157],{"class":69},[45,2254,2160],{"class":58},[45,2256,84],{"class":83},[45,2258,2259],{"class":58}," list.lastElementChild?.",[45,2261,2262],{"class":62},"remove",[45,2264,2265],{"class":58},"());\n",[15,2267,2268,2269,2271,2272,2275,2276,2279],{},"It uses ",[24,2270,127],{}," to ask whether ",[24,2273,2274],{},"li:nth-child(4)"," ",[19,2277,2278],{},"exists",". This technique is known as a quantity query.",[266,2281],{},[10,2283,2285],{"id":2284},"example-5-changing-page-wide-state","Example 5. Changing page-wide state",[15,2287,2288,2289,2291,2292,2294,2295,2298],{},"Put ",[24,2290,127],{}," on ",[24,2293,285],{}," or ",[24,2296,2297],{},"body"," and any element anywhere on the page can become the condition.",[36,2300,2302],{"className":131,"code":2301,"language":133,"meta":41,"style":41},"\u002F* Lock background scrolling while a modal is open *\u002F\nbody:has(dialog[open]) {\n  overflow: hidden;\n}\n\n\u002F* Switch the whole page's colors when the dark mode checkbox is checked *\u002F\nhtml:has(#dark-mode:checked) {\n  color-scheme: dark;\n  background: #111;\n  color: #eee;\n}\n",[24,2303,2304,2309,2329,2341,2345,2349,2354,2367,2379,2390,2402],{"__ignoreMap":41},[45,2305,2306],{"class":47,"line":48},[45,2307,2308],{"class":51},"\u002F* Lock background scrolling while a modal is open *\u002F\n",[45,2310,2311,2313,2315,2317,2320,2323,2326],{"class":47,"line":55},[45,2312,2297],{"class":145},[45,2314,1672],{"class":62},[45,2316,66],{"class":58},[45,2318,2319],{"class":145},"dialog",[45,2321,2322],{"class":58},"[",[45,2324,2325],{"class":62},"open",[45,2327,2328],{"class":58},"]) {\n",[45,2330,2331,2334,2336,2339],{"class":47,"line":90},[45,2332,2333],{"class":157},"  overflow",[45,2335,161],{"class":58},[45,2337,2338],{"class":157},"hidden",[45,2340,167],{"class":58},[45,2342,2343],{"class":47,"line":118},[45,2344,172],{"class":58},[45,2346,2347],{"class":47,"line":365},[45,2348,768],{"emptyLinePlaceholder":767},[45,2350,2351],{"class":47,"line":379},[45,2352,2353],{"class":51},"\u002F* Switch the whole page's colors when the dark mode checkbox is checked *\u002F\n",[45,2355,2356,2358,2360,2362,2365],{"class":47,"line":389},[45,2357,285],{"class":145},[45,2359,1672],{"class":62},[45,2361,66],{"class":58},[45,2363,2364],{"class":62},"#dark-mode:checked",[45,2366,152],{"class":58},[45,2368,2369,2372,2374,2377],{"class":47,"line":404},[45,2370,2371],{"class":157},"  color-scheme",[45,2373,161],{"class":58},[45,2375,2376],{"class":157},"dark",[45,2378,167],{"class":58},[45,2380,2381,2383,2385,2388],{"class":47,"line":428},[45,2382,802],{"class":157},[45,2384,161],{"class":58},[45,2386,2387],{"class":157},"#111",[45,2389,167],{"class":58},[45,2391,2392,2395,2397,2400],{"class":47,"line":442},[45,2393,2394],{"class":157},"  color",[45,2396,161],{"class":58},[45,2398,2399],{"class":157},"#eee",[45,2401,167],{"class":58},[45,2403,2404],{"class":47,"line":456},[45,2405,172],{"class":58},[15,2407,2408,2409,2412],{},"You can delete the code that sets ",[24,2410,2411],{},"document.body.style.overflow = \"hidden\""," every time a modal opens and resets it when it closes.",[266,2414],{},[10,2416,2418],{"id":2417},"before-you-use-it","Before you use it",[2420,2421,2423],"h3",{"id":2422},"browser-support","Browser support",[15,2425,2426,2428,2429,2432],{},[24,2427,127],{}," is supported from Chrome\u002FEdge 105, Safari 15.4, and Firefox 121, so it's been usable in all major browsers since late 2023. If you need to support older browsers, wrap it in ",[24,2430,2431],{},"@supports"," so it only applies where it works.",[36,2434,2436],{"className":131,"code":2435,"language":133,"meta":41,"style":41},"@supports selector(:has(a)) {\n  .plan:has(input:checked) { border-color: #f59e0b; }\n}\n",[24,2437,2438,2455,2476],{"__ignoreMap":41},[45,2439,2440,2442,2445,2447,2449,2452],{"class":47,"line":48},[45,2441,2431],{"class":83},[45,2443,2444],{"class":58}," selector(",[45,2446,1672],{"class":62},[45,2448,66],{"class":58},[45,2450,2451],{"class":145},"a",[45,2453,2454],{"class":58},")) {\n",[45,2456,2457,2460,2462,2464,2466,2468,2470,2472,2474],{"class":47,"line":55},[45,2458,2459],{"class":62},"  .plan:has",[45,2461,66],{"class":58},[45,2463,146],{"class":145},[45,2465,149],{"class":62},[45,2467,1272],{"class":58},[45,2469,1275],{"class":157},[45,2471,161],{"class":58},[45,2473,795],{"class":157},[45,2475,593],{"class":58},[45,2477,2478],{"class":47,"line":90},[45,2479,172],{"class":58},[2420,2481,2483],{"id":2482},"things-to-watch-out-for","Things to watch out for",[190,2485,2486,2496],{},[193,2487,2488],{},[196,2489,2490,2493],{},[199,2491,2492],{},"Gotcha",[199,2494,2495],{},"Details",[206,2497,2498,2514,2525,2537],{},[196,2499,2500,2508],{},[211,2501,2502,2503,2505,2506],{},"No ",[24,2504,127],{}," inside ",[24,2507,127],{},[211,2509,2510,2513],{},[24,2511,2512],{},".a:has(.b:has(.c))"," is invalid",[196,2515,2516,2519],{},[211,2517,2518],{},"No pseudo-elements inside the parentheses",[211,2520,2521,2524],{},[24,2522,2523],{},":has(::before)"," doesn't work",[196,2526,2527,2530],{},[211,2528,2529],{},"Keep the scope narrow",[211,2531,2532,2533,2536],{},"Selectors like ",[24,2534,2535],{},"body:has(*:hover)"," make the browser keep re-checking the whole page, which costs performance. The narrower, the better",[196,2538,2539,2542],{},[211,2540,2541],{},"One bad selector drops the whole rule",[211,2543,2544,2545,2547],{},"If any selector in the ",[24,2546,127],{}," list is invalid, the entire rule is ignored",[266,2549],{},[10,2551,2553],{"id":2552},"summary-why-this-is-worth-knowing","Summary: why this is worth knowing",[190,2555,2556,2569],{},[193,2557,2558],{},[196,2559,2560,2563],{},[199,2561,2562],{},"What you want",[199,2564,2565,2566,2568],{},"The ",[24,2567,127],{}," answer",[206,2570,2571,2581,2591,2601,2611,2621,2631],{},[196,2572,2573,2576],{},[211,2574,2575],{},"Highlight the card of a checked item",[211,2577,2578],{},[24,2579,2580],{},".card:has(input:checked)",[196,2582,2583,2586],{},[211,2584,2585],{},"Make the whole form react to an error",[211,2587,2588],{},[24,2589,2590],{},"form:has(input:user-invalid)",[196,2592,2593,2596],{},[211,2594,2595],{},"Highlight the label of the focused input",[211,2597,2598],{},[24,2599,2600],{},".field:has(input:focus) label",[196,2602,2603,2606],{},[211,2604,2605],{},"Different layout only for cards with an image",[211,2607,2608],{},[24,2609,2610],{},".card:has(img)",[196,2612,2613,2616],{},[211,2614,2615],{},"Select previous siblings",[211,2617,2618],{},[24,2619,2620],{},"li:has(+ li:hover)",[196,2622,2623,2626],{},[211,2624,2625],{},"Layout based on item count",[211,2627,2628],{},[24,2629,2630],{},".list:has(> li:nth-child(4))",[196,2632,2633,2636],{},[211,2634,2635],{},"Lock scrolling while a modal is open",[211,2637,2638],{},[24,2639,2640],{},"body:has(dialog[open])",[15,2642,2643,2644,2646,2647,2650,2651,2653,2654,2656,2657,2659,2660,2663,2664,2666,2667,2670],{},"The real value of ",[24,2645,127],{}," is that ",[19,2648,2649],{},"it lets you delete JavaScript whose only job is adding and removing classes to reflect state."," The state is already in the HTML: whether something is checked (",[24,2652,149],{},"), whether an input is invalid (",[24,2655,1362],{},"), whether the mouse is over it (",[24,2658,1605],{},"), whether it's open (",[24,2661,2662],{},"[open]","). ",[24,2665,127],{}," lets CSS read that state directly. Next time you reach for ",[24,2668,2669],{},"classList.toggle",", check first whether CSS can do it.",[2672,2673,2674],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}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 .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":41,"searchDepth":55,"depth":55,"links":2676},[2677,2678,2679,2680,2681,2682,2683,2687],{"id":12,"depth":55,"text":13},{"id":270,"depth":55,"text":271},{"id":851,"depth":55,"text":852},{"id":1375,"depth":55,"text":1376},{"id":1711,"depth":55,"text":1712},{"id":2284,"depth":55,"text":2285},{"id":2417,"depth":55,"text":2418,"children":2684},[2685,2686],{"id":2422,"depth":90,"text":2423},{"id":2482,"depth":90,"text":2483},{"id":2552,"depth":55,"text":2553},"Cards that highlight when checked, forms that react as a whole to a bad input, star ratings that fill the stars before the one you hover. Things that used to need JavaScript, done with a single CSS :has() rule, with interactive examples.","md",{"date":2691,"field":2692,"tags":2693},"2026.10.08","frontend",[133],"\u002Fen\u002Fcss-has-selector",{"title":5,"description":2688},{"loc":2694},"en\u002Fcss-has-selector","VAm35EqPO77lK3PqYSy-VHw8FPqqowxtRdPwsZro2vE",1791459767454]