[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"verticals":3,"article-has-selector-condition-evaluator":32,"code:css:true:1qe728o":192,"code:js:true:181pjcy":193,"code:css:true:euq3vj":194,"code:css:true:10bdyjc":195,"code:css:true:mknxf0":196,"code:css:true:asc7kd":197},[4,20],{"id":5,"slug":6,"name":7,"tagline":8,"description":9,"accentFrom":10,"accentTo":11,"icon":12,"defaultLocale":13,"locales":14,"features":16,"position":19},"019fe637-3d33-714b-b57f-23e163ffca0c","dev","Web Development","Build. Learn. Ship.","Practical courses, engineering-grade articles and open-source tools for people who ship.","violet-500","cyan-400","◇","en",[13,15],"fa",{"courses":17,"paths":17,"articles":17,"exams":18,"flashcards":18,"packages":17,"community":17,"certificates":17,"teams":17,"commerce":17},true,false,0,{"id":21,"slug":22,"name":23,"tagline":24,"description":25,"accentFrom":26,"accentTo":10,"icon":27,"defaultLocale":13,"locales":28,"features":30,"position":31},"019fe637-3dc2-754c-8657-0f175bfee7c6","lang","Languages","Learn a language the way you learn a codebase.","Structured paths, listening drills and spaced repetition that actually sticks.","amber-400","⌘",[13,15,29],"es",{"courses":17,"paths":17,"articles":18,"exams":18,"flashcards":18,"packages":18,"community":17,"certificates":18,"teams":18,"commerce":17},2,{"id":33,"slug":34,"title":35,"subtitle":36,"excerpt":37,"coverUrl":38,"locale":13,"readingMinutes":39,"publishedAt":40,"viewCount":39,"likeCount":19,"commentCount":19,"author":41,"vertical":46,"topic":47,"tags":50,"_count":62,"playground":36,"body":63,"bodyMd":182,"seo":183,"translationGroupId":186,"thread":187,"assessments":189,"translations":190,"quiz":36},"019fe65f-d19a-709a-855e-54178d886feb","has-selector-condition-evaluator",":has() isn't a parent selector. It deletes JavaScript.",null,"Everyone calls :has() the parent selector. That framing is too small — it's a condition evaluator that obsoletes a whole category of class-toggling JS, and it's in every browser today.","\u002Fmedia\u002Fcovers\u002Fhas-selector-condition-evaluator.png",4,"2026-07-02T07:18:03.500Z",{"id":42,"name":43,"username":44,"avatarUrl":36,"headline":45},"019fe637-3c25-7088-9034-39c9f15dc3c8","Parsa Jiravand","parsa","Frontend engineer · building bestpractic",{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":48,"name":49},"css","CSS",[51,53,56,59],{"slug":48,"name":52,"color":36},"Css",{"slug":54,"name":55,"color":36},"webdev","Webdev",{"slug":57,"name":58,"color":36},"frontend","Frontend",{"slug":60,"name":61,"color":36},"javascript","Javascript",{"assessments":19},{"blocks":64,"version":181},[65,69,72,75,80,83,88,91,94,97,102,105,109,112,115,118,122,125,128,132,135,138,142,145,148,151,154,157,160,163,166,169,172],{"id":66,"html":67,"type":68},"b1","\u003Cp>Open your codebase and search for \u003Ccode>classList.toggle\u003C\u002Fcode>. Go ahead, I&#39;ll wait.\u003C\u002Fp>","paragraph",{"id":70,"html":71,"type":68},"b2","\u003Cp>I&#39;d bet a real chunk of those hits are the same little chore: the user checks a box, focuses a field, or makes a selection, and you respond by toggling a class on some \u003Cem>parent\u003C\u002Fem> element so its styling can react. A listener, a class, matching CSS for that class. You&#39;ve written that dance dozens of times.\u003C\u002Fp>",{"id":73,"html":74,"type":68},"b3","\u003Cp>Most of it can be deleted. Not refactored — deleted. The reason it survives is that everyone learned \u003Ccode>:has()\u003C\u002Fcode> as &quot;the parent selector,&quot; and that label quietly hides what it actually is. Stick with me and you&#39;ll never write that class-toggle the same way again.\u003C\u002Fp>",{"id":76,"html":77,"text":78,"type":79,"level":31},"b4","Why &quot;parent selector&quot; is the wrong name","Why \"parent selector\" is the wrong name","heading",{"id":81,"html":82,"type":68},"b5","\u003Cp>Yes, \u003Ccode>:has()\u003C\u002Fcode> can style a parent based on a child. But pin it to that one trick and you&#39;ll miss the whole feature. \u003Ccode>:has()\u003C\u002Fcode> tests a \u003Cem>condition\u003C\u002Fem> — any selector you&#39;d normally write, evaluated against an element&#39;s contents instead of the element itself. The thing making it true can be a descendant, a sibling, a count, or the \u003Cem>absence\u003C\u002Fem> of something.\u003C\u002Fp>",{"id":84,"code":85,"type":86,"language":48,"highlight":87},"b6","\u002F* a parent based on a child — the famous case *\u002F\n.card:has(img) { ... }\n\n\u002F* focus state buried deep in the subtree *\u002F\n.form-group:has(:focus-visible) { ... }\n\n\u002F* checked state *\u002F\n.option-row:has(input:checked) { background: var(--selected-bg); }\n\n\u002F* absence — the logical complement *\u002F\n.card:not(:has(img)) { ... }\n\n\u002F* count — restyle a grid by how many children it holds *\u002F\n.grid:has(> :nth-child(4)) { grid-template-columns: repeat(4, 1fr); }","code",[],{"id":89,"html":90,"type":68},"b7","\u003Cp>Stare at that last one. You&#39;re changing a grid&#39;s layout \u003Cem>based on how many items it contains\u003C\u002Fem> — in pure CSS, no JavaScript, no server-rendered class. That&#39;s not &quot;selecting a parent.&quot; That&#39;s a conditional reading live DOM state. Different mental model entirely.\u003C\u002Fp>",{"id":92,"html":93,"text":93,"type":79,"level":31},"b8","The class of JavaScript that just disappears",{"id":95,"html":96,"type":68},"b9","\u003Cp>Here&#39;s the pattern \u003Ccode>:has()\u003C\u002Fcode> retires. You&#39;ve written this:\u003C\u002Fp>",{"id":98,"code":99,"type":86,"language":100,"highlight":101},"b10","\u002F\u002F The old bridge: JS exists only to move a class up the tree\ncheckbox.addEventListener(\"change\", () => {\n  row.classList.toggle(\"is-checked\", checkbox.checked);\n});","js",[],{"id":103,"html":104,"type":68},"b11","\u003Cp>Why does this code exist at all? Because CSS selectors only ever flowed \u003Cem>down\u003C\u002Fem> — a parent could style its children, but a child could never trigger a style on its ancestor. So we hired JavaScript as a messenger. \u003Ccode>:has()\u003C\u002Fcode> makes the messenger redundant:\u003C\u002Fp>",{"id":106,"code":107,"type":86,"language":48,"highlight":108},"b12","\u002F* The whole listener, gone *\u002F\n.option-row:has(input[type=\"checkbox\"]:checked) {\n  background: var(--selected-bg);\n  font-weight: 600;\n}",[],{"id":110,"html":111,"type":68},"b13","\u003Cp>The listener is gone. The class is gone. And — this is the part that&#39;s easy to undervalue — the style is now \u003Cem>true whenever the DOM is in that state\u003C\u002Fem>. On first render. After a back-navigation. When state is restored from a URL. There&#39;s no window where the DOM has updated but the class hasn&#39;t caught up yet, because there&#39;s no class to catch up.\u003C\u002Fp>",{"id":113,"html":114,"text":114,"type":79,"level":31},"b14","Three you can paste in today",{"id":116,"html":117,"type":68},"b15","\u003Cp>\u003Cstrong>Field-group validation.\u003C\u002Fstrong> Light up the whole group — label, input, hint — when it holds an input the user touched and left invalid:\u003C\u002Fp>",{"id":119,"code":120,"type":86,"language":48,"highlight":121},"b16",".field-group:has(input:invalid:not(:placeholder-shown)) {\n  border-color: var(--color-error);\n}\n.field-group:has(input:invalid:not(:placeholder-shown)) label {\n  color: var(--color-error);\n}",[],{"id":123,"html":124,"type":68},"b17","\u003Cp>That used to be a \u003Ccode>blur\u003C\u002Fcode> listener, a wrapper class, and matching CSS. Now: two rules.\u003C\u002Fp>",{"id":126,"html":127,"type":68},"b18","\u003Cp>\u003Cstrong>Empty state.\u003C\u002Fstrong> Show a placeholder when a list has no items:\u003C\u002Fp>",{"id":129,"code":130,"type":86,"language":48,"highlight":131},"b19",".todo-list:not(:has(li)) + .empty-state { display: block; }",[],{"id":133,"html":134,"type":68},"b20","\u003Cp>No JS tracking item counts. The empty state appears the moment the last \u003Ccode>li\u003C\u002Fcode> leaves.\u003C\u002Fp>",{"id":136,"html":137,"type":68},"b21","\u003Cp>\u003Cstrong>Checkbox-driven panel.\u003C\u002Fstrong> A toggle reveals its settings panel:\u003C\u002Fp>",{"id":139,"code":140,"type":86,"language":48,"highlight":141},"b22",".settings-section:has(input[type=\"checkbox\"]:checked) .settings-panel {\n  display: grid;\n}",[],{"id":143,"html":144,"type":68},"b23","\u003Cp>The browser&#39;s own form state is the source of truth, and CSS reads it directly. No syncing.\u003C\u002Fp>",{"id":146,"html":147,"text":147,"type":79,"level":31},"b24","The one place to slow down",{"id":149,"html":150,"type":68},"b25","\u003Cp>\u003Ccode>:has()\u003C\u002Fcode> isn&#39;t free. Matching a class is the browser reading an attribute; matching \u003Ccode>:has()\u003C\u002Fcode> means evaluating the inner selector against descendants. For static content and low-frequency state — validation, toggles, checked state — the cost is imperceptible. Ship it.\u003C\u002Fp>",{"id":152,"html":153,"type":68},"b26","\u003Cp>Where to be deliberate: high-frequency, continuously-changing inputs. \u003Ccode>:has()\u003C\u002Fcode> keyed off scroll position, or nested inside \u003Ccode>:hover\u003C\u002Fcode> on a list of thousands of rows. The rule of thumb: anywhere you&#39;d have reached for a \u003Ccode>debounce\u003C\u002Fcode> on the JS side, give the \u003Ccode>:has()\u003C\u002Fcode> version a second look and profile it.\u003C\u002Fp>",{"id":155,"html":156,"text":156,"type":79,"level":31},"b27","So which JS is still pretending to be CSS?",{"id":158,"html":159,"type":68},"b28","\u003Cp>Back to that \u003Ccode>classList.toggle\u003C\u002Fcode> search you ran. The framing that unlocks the cleanup isn&#39;t &quot;where can I select a parent&quot; — it&#39;s this: \u003Cstrong>whenever you catch yourself toggling a class purely to drive styling off some child&#39;s state, stop and ask whether \u003Ccode>:has()\u003C\u002Fcode> expresses that condition directly.\u003C\u002Fstrong> More often than you&#39;d guess, it does. When it does, the CSS shrinks, the JS evaporates, and the styling is correct from the very first paint because it&#39;s \u003Cem>reading\u003C\u002Fem> state instead of \u003Cem>reacting\u003C\u002Fem> to it.\u003C\u002Fp>",{"id":161,"html":162,"type":68},"b29","\u003Cp>\u003Ccode>:has()\u003C\u002Fcode> is in Chrome, Firefox, Safari, and Edge — no flag, no polyfill, no waiting. It&#39;s not a parent selector. It&#39;s a stylesheet that can finally read its own document.\u003C\u002Fp>",{"id":164,"html":165,"type":68},"b30","\u003Cp>So go run the search. How many of your \u003Ccode>classList.toggle\u003C\u002Fcode> calls are really a \u003Ccode>:has()\u003C\u002Fcode> rule in a trench coat? Drop the gnarliest one in the comments and let&#39;s rewrite it.\u003C\u002Fp>",{"id":167,"type":168},"b31","divider",{"id":170,"html":171,"type":68},"b32","\u003Cp>\u003Cem>Thanks for reading! Let&#39;s stay connected:\u003C\u002Fem>\u003C\u002Fp>",{"id":173,"type":174,"items":175,"ordered":18},"b33","list",[176,177,178,179,180],"⭐ \u003Cstrong>GitHub\u003C\u002Fstrong> — follow me and star the projects: \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fparsajiravand\">github.com\u002Fparsajiravand\u003C\u002Fa>","💬 \u003Cstrong>Discord\u003C\u002Fstrong> — join the frontend best-practices community: \u003Ca href=\"https:\u002F\u002Fdiscord.gg\u002Fd9KRhuAwQ\">discord.gg\u002Fd9KRhuAwQ\u003C\u002Fa>","📸 \u003Cstrong>Instagram\u003C\u002Fstrong> — frontend best practices, daily: \u003Ca href=\"https:\u002F\u002Fwww.instagram.com\u002Fbestpractice___\u002F\">@bestpractice___\u003C\u002Fa>","💼 \u003Cstrong>LinkedIn\u003C\u002Fstrong> — \u003Ca href=\"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fparsa-jiravand\u002F\">linkedin.com\u002Fin\u002Fparsa-jiravand\u003C\u002Fa>","✉️ \u003Cstrong>Email\u003C\u002Fstrong> (work &amp; contract inquiries): \u003Ca href=\"mailto:bestpractice2026@gmail.com\">bestpractice2026@gmail.com\u003C\u002Fa>",1,"Open your codebase and search for `classList.toggle`. Go ahead, I'll wait.\n\nI'd bet a real chunk of those hits are the same little chore: the user checks a box, focuses a field, or makes a selection, and you respond by toggling a class on some *parent* element so its styling can react. A listener, a class, matching CSS for that class. You've written that dance dozens of times.\n\nMost of it can be deleted. Not refactored — deleted. The reason it survives is that everyone learned `:has()` as \"the parent selector,\" and that label quietly hides what it actually is. Stick with me and you'll never write that class-toggle the same way again.\n\n## Why \"parent selector\" is the wrong name\n\nYes, `:has()` can style a parent based on a child. But pin it to that one trick and you'll miss the whole feature. `:has()` tests a *condition* — any selector you'd normally write, evaluated against an element's contents instead of the element itself. The thing making it true can be a descendant, a sibling, a count, or the *absence* of something.\n\n```css\n\u002F* a parent based on a child — the famous case *\u002F\n.card:has(img) { ... }\n\n\u002F* focus state buried deep in the subtree *\u002F\n.form-group:has(:focus-visible) { ... }\n\n\u002F* checked state *\u002F\n.option-row:has(input:checked) { background: var(--selected-bg); }\n\n\u002F* absence — the logical complement *\u002F\n.card:not(:has(img)) { ... }\n\n\u002F* count — restyle a grid by how many children it holds *\u002F\n.grid:has(> :nth-child(4)) { grid-template-columns: repeat(4, 1fr); }\n```\n\nStare at that last one. You're changing a grid's layout *based on how many items it contains* — in pure CSS, no JavaScript, no server-rendered class. That's not \"selecting a parent.\" That's a conditional reading live DOM state. Different mental model entirely.\n\n## The class of JavaScript that just disappears\n\nHere's the pattern `:has()` retires. You've written this:\n\n```js\n\u002F\u002F The old bridge: JS exists only to move a class up the tree\ncheckbox.addEventListener(\"change\", () => {\n  row.classList.toggle(\"is-checked\", checkbox.checked);\n});\n```\n\nWhy does this code exist at all? Because CSS selectors only ever flowed *down* — a parent could style its children, but a child could never trigger a style on its ancestor. So we hired JavaScript as a messenger. `:has()` makes the messenger redundant:\n\n```css\n\u002F* The whole listener, gone *\u002F\n.option-row:has(input[type=\"checkbox\"]:checked) {\n  background: var(--selected-bg);\n  font-weight: 600;\n}\n```\n\nThe listener is gone. The class is gone. And — this is the part that's easy to undervalue — the style is now *true whenever the DOM is in that state*. On first render. After a back-navigation. When state is restored from a URL. There's no window where the DOM has updated but the class hasn't caught up yet, because there's no class to catch up.\n\n## Three you can paste in today\n\n**Field-group validation.** Light up the whole group — label, input, hint — when it holds an input the user touched and left invalid:\n\n```css\n.field-group:has(input:invalid:not(:placeholder-shown)) {\n  border-color: var(--color-error);\n}\n.field-group:has(input:invalid:not(:placeholder-shown)) label {\n  color: var(--color-error);\n}\n```\n\nThat used to be a `blur` listener, a wrapper class, and matching CSS. Now: two rules.\n\n**Empty state.** Show a placeholder when a list has no items:\n\n```css\n.todo-list:not(:has(li)) + .empty-state { display: block; }\n```\n\nNo JS tracking item counts. The empty state appears the moment the last `li` leaves.\n\n**Checkbox-driven panel.** A toggle reveals its settings panel:\n\n```css\n.settings-section:has(input[type=\"checkbox\"]:checked) .settings-panel {\n  display: grid;\n}\n```\n\nThe browser's own form state is the source of truth, and CSS reads it directly. No syncing.\n\n## The one place to slow down\n\n`:has()` isn't free. Matching a class is the browser reading an attribute; matching `:has()` means evaluating the inner selector against descendants. For static content and low-frequency state — validation, toggles, checked state — the cost is imperceptible. Ship it.\n\nWhere to be deliberate: high-frequency, continuously-changing inputs. `:has()` keyed off scroll position, or nested inside `:hover` on a list of thousands of rows. The rule of thumb: anywhere you'd have reached for a `debounce` on the JS side, give the `:has()` version a second look and profile it.\n\n## So which JS is still pretending to be CSS?\n\nBack to that `classList.toggle` search you ran. The framing that unlocks the cleanup isn't \"where can I select a parent\" — it's this: **whenever you catch yourself toggling a class purely to drive styling off some child's state, stop and ask whether `:has()` expresses that condition directly.** More often than you'd guess, it does. When it does, the CSS shrinks, the JS evaporates, and the styling is correct from the very first paint because it's *reading* state instead of *reacting* to it.\n\n`:has()` is in Chrome, Firefox, Safari, and Edge — no flag, no polyfill, no waiting. It's not a parent selector. It's a stylesheet that can finally read its own document.\n\nSo go run the search. How many of your `classList.toggle` calls are really a `:has()` rule in a trench coat? Drop the gnarliest one in the comments and let's rewrite it.\n\n---\n\n*Thanks for reading! Let's stay connected:*\n\n- ⭐ **GitHub** — follow me and star the projects: [github.com\u002Fparsajiravand](https:\u002F\u002Fgithub.com\u002Fparsajiravand)\n- 💬 **Discord** — join the frontend best-practices community: [discord.gg\u002Fd9KRhuAwQ](https:\u002F\u002Fdiscord.gg\u002Fd9KRhuAwQ)\n- 📸 **Instagram** — frontend best practices, daily: [@bestpractice___](https:\u002F\u002Fwww.instagram.com\u002Fbestpractice___\u002F)\n- 💼 **LinkedIn** — [linkedin.com\u002Fin\u002Fparsa-jiravand](https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fparsa-jiravand\u002F)\n- ✉️ **Email** (work & contract inquiries): [bestpractice2026@gmail.com](mailto:bestpractice2026@gmail.com)",{"title":35,"canonical":184,"description":185},"https:\u002F\u002Fbestpractic.org\u002Fblog\u002Fhas-selector-condition-evaluator","Everyone calls :has() the parent selector. That framing is too small — it's a condition evaluator that obsoletes a whole category of class-toggling JS, and it's in every browser to","019fe65f-d19a-709a-855e-5a2f4385b130",{"id":188,"locked":18},"019fe65f-d850-70bd-99e0-30fff589f769",[],[191],{"locale":13,"slug":34},"\u003Cdiv class=\"shj shj-lang-css shj-multiline\" data-lang=\"css\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003Cdiv>9\u003C\u002Fdiv>\u003Cdiv>10\u003C\u002Fdiv>\u003Cdiv>11\u003C\u002Fdiv>\u003Cdiv>12\u003C\u002Fdiv>\u003Cdiv>13\u003C\u002Fdiv>\u003Cdiv>14\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-cmnt\">\u002F* a parent based on a child — the famous case *\u002F\u003C\u002Fspan>\n\u003Cspan class=\"shj-var\">.card\u003C\u002Fspan>\u003Cspan class=\"shj-var\">:has\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">img\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> ... \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\n\u003Cspan class=\"shj-cmnt\">\u002F* focus state buried deep in the subtree *\u002F\u003C\u002Fspan>\n\u003Cspan class=\"shj-var\">.form-group\u003C\u002Fspan>\u003Cspan class=\"shj-var\">:has\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-var\">:focus-visible\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> ... \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\n\u003Cspan class=\"shj-cmnt\">\u002F* checked state *\u002F\u003C\u002Fspan>\n\u003Cspan class=\"shj-var\">.option-row\u003C\u002Fspan>\u003Cspan class=\"shj-var\">:has\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">input\u003C\u002Fspan>\u003Cspan class=\"shj-var\">:checked\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> \u003Cspan class=\"shj-var\">background\u003C\u002Fspan>: \u003Cspan class=\"shj-func\">var\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>--\u003Cspan class=\"shj-num\">selected-bg\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\n\u003Cspan class=\"shj-cmnt\">\u002F* absence — the logical complement *\u002F\u003C\u002Fspan>\n\u003Cspan class=\"shj-var\">.card\u003C\u002Fspan>\u003Cspan class=\"shj-var\">:not\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-var\">:has\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">img\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> ... \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\n\u003Cspan class=\"shj-cmnt\">\u002F* count — restyle a grid by how many children it holds *\u002F\u003C\u002Fspan>\n\u003Cspan class=\"shj-var\">.grid\u003C\u002Fspan>\u003Cspan class=\"shj-var\">:has\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>&gt; \u003Cspan class=\"shj-var\">:nth-child\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">4\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> \u003Cspan class=\"shj-var\">grid-template-columns\u003C\u002Fspan>: \u003Cspan class=\"shj-func\">repeat\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">4\u003C\u002Fspan>, \u003Cspan class=\"shj-num\">1\u003C\u002Fspan>fr\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-cmnt\">\u002F\u002F The old bridge: JS exists only to move a class up the tree\n\u003C\u002Fspan>checkbox\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">addEventListener\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"change\"\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  row\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>classList\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">toggle\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"is-checked\"\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> checkbox\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>checked\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-css shj-multiline\" data-lang=\"css\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-cmnt\">\u002F* The whole listener, gone *\u002F\u003C\u002Fspan>\n\u003Cspan class=\"shj-var\">.option-row\u003C\u002Fspan>\u003Cspan class=\"shj-var\">:has\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">input\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">type\u003C\u002Fspan>=\u003Cspan class=\"shj-str\">\"checkbox\"\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-var\">:checked\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-var\">background\u003C\u002Fspan>: \u003Cspan class=\"shj-func\">var\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>--\u003Cspan class=\"shj-num\">selected-bg\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-var\">font-weight\u003C\u002Fspan>: \u003Cspan class=\"shj-num\">600\u003C\u002Fspan>;\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-css shj-multiline\" data-lang=\"css\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-var\">.field-group\u003C\u002Fspan>\u003Cspan class=\"shj-var\">:has\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">input\u003C\u002Fspan>\u003Cspan class=\"shj-var\">:invalid\u003C\u002Fspan>\u003Cspan class=\"shj-var\">:not\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-var\">:placeholder-shown\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-var\">border-color\u003C\u002Fspan>: \u003Cspan class=\"shj-func\">var\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>--\u003Cspan class=\"shj-num\">color-error\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\u003Cspan class=\"shj-var\">.field-group\u003C\u002Fspan>\u003Cspan class=\"shj-var\">:has\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">input\u003C\u002Fspan>\u003Cspan class=\"shj-var\">:invalid\u003C\u002Fspan>\u003Cspan class=\"shj-var\">:not\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-var\">:placeholder-shown\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">label\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-var\">color\u003C\u002Fspan>: \u003Cspan class=\"shj-func\">var\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>--\u003Cspan class=\"shj-num\">color-error\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-css shj-oneline\" data-lang=\"css\">\u003Cspan class=\"shj-var\">.todo-list\u003C\u002Fspan>\u003Cspan class=\"shj-var\">:not\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-var\">:has\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">li\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> + \u003Cspan class=\"shj-var\">.empty-state\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> \u003Cspan class=\"shj-var\">display\u003C\u002Fspan>: \u003Cspan class=\"shj-num\">block\u003C\u002Fspan>; \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-css shj-multiline\" data-lang=\"css\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-var\">.settings-section\u003C\u002Fspan>\u003Cspan class=\"shj-var\">:has\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">input\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">type\u003C\u002Fspan>=\u003Cspan class=\"shj-str\">\"checkbox\"\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-var\">:checked\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-var\">.settings-panel\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-var\">display\u003C\u002Fspan>: \u003Cspan class=\"shj-num\">grid\u003C\u002Fspan>;\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>"]