[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"quiz-css-style-queries-react-to-custom-properties":3,"verticals":25,"quiz-article-css-style-queries-react-to-custom-properties":48},{"id":4,"slug":5,"kind":6,"title":7,"description":8,"config":9,"verticalId":17,"vertical":18,"course":11,"_count":21,"access":22,"attempts":24,"questionCount":10},"019fe776-c054-771f-aef5-65f6f34940d9","css-style-queries-react-to-custom-properties","PRACTICE_QUIZ","CSS Container Style Queries","Style queries extend @container to check CSS custom property values on a container ancestor, not just its size. These questions cover how style queries differ from size queries, what container declaration is required, what happens when queries compose, how custom properties flow to make them work, and the browser baseline.",{"questionCount":10,"timeLimitSec":11,"shuffleQuestions":12,"shuffleOptions":13,"negativeMarking":14,"passScorePct":15,"maxAttempts":11,"revealAnswers":16,"allowFlagging":12,"allowBacktracking":13},9,null,false,true,0,70,"AFTER_SUBMIT","019fe637-3d33-714b-b57f-23e163ffca0c",{"slug":19,"name":20},"dev","Web Development",{"questions":10},{"allowed":13,"reason":23},"FREE",[],[26,36],{"id":17,"slug":19,"name":20,"tagline":27,"description":28,"accentFrom":29,"accentTo":30,"icon":31,"defaultLocale":32,"locales":33,"features":35,"position":14},"Build. Learn. Ship.","Practical courses, engineering-grade articles and open-source tools for people who ship.","violet-500","cyan-400","◇","en",[32,34],"fa",{"courses":13,"paths":13,"articles":13,"exams":12,"flashcards":12,"packages":13,"community":13,"certificates":13,"teams":13,"commerce":13},{"id":37,"slug":38,"name":39,"tagline":40,"description":41,"accentFrom":42,"accentTo":29,"icon":43,"defaultLocale":32,"locales":44,"features":46,"position":47},"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","⌘",[32,34,45],"es",{"courses":13,"paths":13,"articles":12,"exams":12,"flashcards":12,"packages":12,"community":13,"certificates":12,"teams":12,"commerce":13},2,{"id":49,"slug":5,"title":50,"subtitle":11,"excerpt":51,"coverUrl":52,"locale":32,"readingMinutes":53,"publishedAt":54,"viewCount":55,"likeCount":14,"commentCount":14,"author":56,"vertical":61,"topic":62,"tags":65,"_count":77,"playground":79,"body":81,"bodyMd":218,"seo":219,"translationGroupId":223,"thread":224,"assessments":226,"translations":229,"quiz":231},"019fe660-e5d0-756a-9ae2-20c6ff4c2f48","Container queries can check more than size — style queries let components read custom property values","Size queries react to container width. Style queries react to CSS custom property values on a container ancestor — enabling component-level theming and variant switching in pure CSS, no JavaScript involved.","\u002Fmedia\u002Fcovers\u002Fcss-style-queries-react-to-custom-properties.png",4,"2026-08-06T08:44:20.136Z",12,{"id":57,"name":58,"username":59,"avatarUrl":11,"headline":60},"019fe637-3c25-7088-9034-39c9f15dc3c8","Parsa Jiravand","parsa","Frontend engineer · building bestpractic",{"slug":19,"name":20,"accentFrom":29,"accentTo":30},{"slug":63,"name":64},"css","CSS",[66,68,71,74],{"slug":63,"name":67,"color":11},"Css",{"slug":69,"name":70,"color":11},"webdev","Webdev",{"slug":72,"name":73,"color":11},"frontend","Frontend",{"slug":75,"name":76,"color":11},"components","Components",{"assessments":78},1,{"slug":5,"title":80},"CSS Style Queries — interactive playground",{"blocks":82,"version":78},[83,87,91,94,99,102,105,109,112,115,118,122,125,128,131,135,138,141,144,148,151,154,157,161,164,167,170,173,176,179,182,185,188,191,194,197,200,203,206,209],{"id":84,"html":85,"type":86},"b1","\u003Cp>When a component needs to know its context — is it inside a dark sidebar? a compact layout? a danger banner? — the usual answer is JavaScript. You pass a prop, toggle a class, and the styles follow. But the context you&#39;re checking is often already sitting in a CSS custom property on some ancestor element. Style queries let the component read it directly, with no JavaScript in the middle.\u003C\u002Fp>","paragraph",{"id":88,"html":89,"text":89,"type":90,"level":47},"b2","The size queries you already know","heading",{"id":92,"html":93,"type":86},"b3","\u003Cp>If you&#39;ve used container queries, you know the size query pattern:\u003C\u002Fp>",{"id":95,"code":96,"type":97,"language":63,"highlight":98},"b4",".card { container-type: inline-size; }\n\n@container (min-width: 400px) {\n  .card-body { display: grid; grid-template-columns: 1fr 1fr; }\n}","code",[],{"id":100,"html":101,"type":86},"b5","\u003Cp>The child adapts when the container crosses a width threshold. Style queries use the same \u003Ccode>@container\u003C\u002Fcode> syntax, but check a CSS custom property value instead of a size.\u003C\u002Fp>",{"id":103,"html":104,"text":104,"type":90,"level":47},"b6","What a style query looks like",{"id":106,"code":107,"type":97,"language":63,"highlight":108},"b7",".sidebar {\n  container-type: inline-size;\n  --theme: dark;\n}\n\n@container style(--theme: dark) {\n  .button {\n    background: #1e293b;\n    color: #f8fafc;\n  }\n}",[],{"id":110,"html":111,"type":86},"b8","\u003Cp>The \u003Ccode>.button\u003C\u002Fcode> inside \u003Ccode>.sidebar\u003C\u002Fcode> asks: does my nearest container ancestor have \u003Ccode>--theme\u003C\u002Fcode> set to \u003Ccode>dark\u003C\u002Fcode>? If yes, apply these styles. No JavaScript. No extra class on the button. The context lives in the custom property; the component reads it.\u003C\u002Fp>",{"id":113,"html":114,"text":114,"type":90,"level":47},"b9","The mental model: CSS custom properties already flow down",{"id":116,"html":117,"type":86},"b10","\u003Cp>Custom properties cascade from parent to child — you&#39;ve always been able to \u003Cem>use\u003C\u002Fem> \u003Ccode>--theme\u003C\u002Fcode> inside a descendant. What you couldn&#39;t do was \u003Cem>branch on its value\u003C\u002Fem> in CSS alone. A style query adds that branch.\u003C\u002Fp>",{"id":119,"code":120,"type":97,"language":63,"highlight":121},"b11","\u002F* Intent set once on the layout root *\u002F\n.layout[data-mode=\"compact\"]  { --density: compact; }\n.layout[data-mode=\"spacious\"] { --density: spacious; }\n\n.panel { container-type: inline-size; }\n\n\u002F* Any descendant component reads the inherited context *\u002F\n@container style(--density: compact) {\n  .list-item { padding: 4px 8px; font-size: 0.875rem; }\n}\n\n@container style(--density: spacious) {\n  .list-item { padding: 12px 16px; font-size: 1rem; }\n}",[],{"id":123,"html":124,"type":86},"b12","\u003Cp>The data attribute on \u003Ccode>.layout\u003C\u002Fcode> sets the intent once. The custom property carries it down the tree. The style query acts on it wherever the component appears — the component itself needs no extra class, no prop, no knowledge of where it&#39;s placed.\u003C\u002Fp>",{"id":126,"html":127,"text":127,"type":90,"level":47},"b13","A real-world use case: variant-aware alerts",{"id":129,"html":130,"type":86},"b14","\u003Cp>Component variant systems are a natural fit. A severity-aware alert where every sub-element adapts:\u003C\u002Fp>",{"id":132,"code":133,"type":97,"language":63,"highlight":134},"b15",".alert {\n  container-type: inline-size;\n  --alert-severity: neutral;\n}\n\n.alert[data-severity=\"error\"]   { --alert-severity: error; }\n.alert[data-severity=\"warning\"] { --alert-severity: warning; }\n.alert[data-severity=\"success\"] { --alert-severity: success; }\n\n@container style(--alert-severity: error) {\n  .alert-icon { color: var(--red-600); }\n  .alert-bar  { background: var(--red-100); border-color: var(--red-600); }\n}\n\n@container style(--alert-severity: warning) {\n  .alert-icon { color: var(--amber-600); }\n  .alert-bar  { background: var(--amber-100); border-color: var(--amber-600); }\n}\n\n@container style(--alert-severity: success) {\n  .alert-icon { color: var(--green-600); }\n  .alert-bar  { background: var(--green-100); border-color: var(--green-600); }\n}",[],{"id":136,"html":137,"type":86},"b16","\u003Cp>The severity is declared once on \u003Ccode>.alert\u003C\u002Fcode> via a data attribute. Every nested element — the icon, the border bar, a close button you add later — reads it through the style query. Adding a new sub-element means one new \u003Ccode>@container style(...)\u003C\u002Fcode> rule; nothing else changes.\u003C\u002Fp>",{"id":139,"html":140,"text":140,"type":90,"level":47},"b17","Combining size and style in one block",{"id":142,"html":143,"type":86},"b18","\u003Cp>Style and size queries compose. A single \u003Ccode>@container\u003C\u002Fcode> block can check both:\u003C\u002Fp>",{"id":145,"code":146,"type":97,"language":63,"highlight":147},"b19","@container card (max-width: 300px) and style(--theme: dark) {\n  .card-label {\n    font-size: 0.75rem;\n    color: var(--dark-muted);\n  }\n}",[],{"id":149,"html":150,"type":86},"b20","\u003Cp>This applies only when the container named \u003Ccode>card\u003C\u002Fcode> is narrow \u003Cem>and\u003C\u002Fem> has \u003Ccode>--theme: dark\u003C\u002Fcode>. The combination lets you encode conditional behavior in CSS that would otherwise require a computed class name or inline style injection.\u003C\u002Fp>",{"id":152,"html":153,"text":153,"type":90,"level":47},"b21","One thing to remember about the container",{"id":155,"html":156,"type":86},"b22","\u003Cp>The \u003Ccode>container-type\u003C\u002Fcode> declaration is still needed on the ancestor for style queries to work — it establishes the containment context that \u003Ccode>@container style(...)\u003C\u002Fcode> queries against. If you only need style queries and not size queries, you can use \u003Ccode>container-type: normal\u003C\u002Fcode> (or just set \u003Ccode>container-name\u003C\u002Fcode> without a type). Without any container declaration on the ancestor, the style query has nothing to inspect and applies nothing.\u003C\u002Fp>",{"id":158,"code":159,"type":97,"language":63,"highlight":160},"b23","\u002F* Size + style queries: use inline-size or size *\u002F\n.card { container-type: inline-size; }\n\n\u002F* Style queries only — no size containment needed *\u002F\n.theme-root { container-name: themed; }\n\n@container themed style(--theme: dark) { ... }",[],{"id":162,"html":163,"text":163,"type":90,"level":47},"b24","Browser support",{"id":165,"html":166,"type":86},"b25","\u003Cp>Style queries are \u003Cstrong>Baseline 2024\u003C\u002Fstrong>: Chrome 111 (March 2023), Firefox 110 (February 2023), Safari 17.2 (December 2023). All three major engines shipped within the same year. If your project already uses container size queries, style queries are available in the same browsers.\u003C\u002Fp>",{"id":168,"html":169,"type":86},"b26","\u003C!-- playground:start -->",{"id":171,"html":172,"text":172,"type":90,"level":47},"b27","🎮 Try it yourself",{"id":174,"html":175,"type":86},"b28","\u003Cp>\u003Cstrong>\u003Ca href=\"https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fposts\u002F2026-08-06-css-style-queries-react-to-custom-properties\u002Fplayground\u002F\">▶️ Open the interactive playground →\u003C\u002Fa>\u003C\u002Fstrong>\u003C\u002Fp>",{"id":177,"html":178,"type":86},"b29","\u003Cp>\u003Cem>Runs right in your browser — poke at it and watch the concept react live.\u003C\u002Fem>\u003C\u002Fp>",{"id":180,"html":181,"type":86},"b30","\u003C!-- playground:end -->",{"id":183,"html":184,"type":86},"b31","\u003C!-- quiz:start -->",{"id":186,"html":187,"text":187,"type":90,"level":47},"b32","🧠 Test yourself",{"id":189,"html":190,"type":86},"b33","\u003Cp>Think it clicked? \u003Cstrong>\u003Ca href=\"https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fquiz\u002Ftake.html?post=2026-08-06-css-style-queries-react-to-custom-properties\">Take the 9-question quiz →\u003C\u002Fa>\u003C\u002Fstrong>\u003C\u002Fp>",{"id":192,"html":193,"type":86},"b34","\u003Cp>\u003Cem>Instant feedback, a hint on every question, and an explanation for each answer — right or wrong.\u003C\u002Fem>\u003C\u002Fp>",{"id":195,"html":196,"type":86},"b35","\u003C!-- quiz:end -->",{"id":198,"html":199,"text":199,"type":90,"level":47},"b36","The takeaway",{"id":201,"html":202,"type":86},"b37","\u003Cp>Scan your codebase for places where JavaScript reads a state value and then toggles a CSS class to change a component&#39;s appearance. If that state is already encoded as a CSS custom property on an ancestor element, a style query can replace the JavaScript bridge entirely. The property carries the context down the tree; \u003Ccode>@container style(...)\u003C\u002Fcode> branches on it wherever the component appears. The component stays self-contained — it reads its environment rather than getting configuration pushed in from outside.\u003C\u002Fp>",{"id":204,"type":205},"b38","divider",{"id":207,"html":208,"type":86},"b39","\u003Cp>\u003Cem>Thanks for reading! Let&#39;s stay connected:\u003C\u002Fem>\u003C\u002Fp>",{"id":210,"type":211,"items":212,"ordered":12},"b40","list",[213,214,215,216,217],"⭐ \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>","When a component needs to know its context — is it inside a dark sidebar? a compact layout? a danger banner? — the usual answer is JavaScript. You pass a prop, toggle a class, and the styles follow. But the context you're checking is often already sitting in a CSS custom property on some ancestor element. Style queries let the component read it directly, with no JavaScript in the middle.\n\n## The size queries you already know\n\nIf you've used container queries, you know the size query pattern:\n\n```css\n.card { container-type: inline-size; }\n\n@container (min-width: 400px) {\n  .card-body { display: grid; grid-template-columns: 1fr 1fr; }\n}\n```\n\nThe child adapts when the container crosses a width threshold. Style queries use the same `@container` syntax, but check a CSS custom property value instead of a size.\n\n## What a style query looks like\n\n```css\n.sidebar {\n  container-type: inline-size;\n  --theme: dark;\n}\n\n@container style(--theme: dark) {\n  .button {\n    background: #1e293b;\n    color: #f8fafc;\n  }\n}\n```\n\nThe `.button` inside `.sidebar` asks: does my nearest container ancestor have `--theme` set to `dark`? If yes, apply these styles. No JavaScript. No extra class on the button. The context lives in the custom property; the component reads it.\n\n## The mental model: CSS custom properties already flow down\n\nCustom properties cascade from parent to child — you've always been able to *use* `--theme` inside a descendant. What you couldn't do was *branch on its value* in CSS alone. A style query adds that branch.\n\n```css\n\u002F* Intent set once on the layout root *\u002F\n.layout[data-mode=\"compact\"]  { --density: compact; }\n.layout[data-mode=\"spacious\"] { --density: spacious; }\n\n.panel { container-type: inline-size; }\n\n\u002F* Any descendant component reads the inherited context *\u002F\n@container style(--density: compact) {\n  .list-item { padding: 4px 8px; font-size: 0.875rem; }\n}\n\n@container style(--density: spacious) {\n  .list-item { padding: 12px 16px; font-size: 1rem; }\n}\n```\n\nThe data attribute on `.layout` sets the intent once. The custom property carries it down the tree. The style query acts on it wherever the component appears — the component itself needs no extra class, no prop, no knowledge of where it's placed.\n\n## A real-world use case: variant-aware alerts\n\nComponent variant systems are a natural fit. A severity-aware alert where every sub-element adapts:\n\n```css\n.alert {\n  container-type: inline-size;\n  --alert-severity: neutral;\n}\n\n.alert[data-severity=\"error\"]   { --alert-severity: error; }\n.alert[data-severity=\"warning\"] { --alert-severity: warning; }\n.alert[data-severity=\"success\"] { --alert-severity: success; }\n\n@container style(--alert-severity: error) {\n  .alert-icon { color: var(--red-600); }\n  .alert-bar  { background: var(--red-100); border-color: var(--red-600); }\n}\n\n@container style(--alert-severity: warning) {\n  .alert-icon { color: var(--amber-600); }\n  .alert-bar  { background: var(--amber-100); border-color: var(--amber-600); }\n}\n\n@container style(--alert-severity: success) {\n  .alert-icon { color: var(--green-600); }\n  .alert-bar  { background: var(--green-100); border-color: var(--green-600); }\n}\n```\n\nThe severity is declared once on `.alert` via a data attribute. Every nested element — the icon, the border bar, a close button you add later — reads it through the style query. Adding a new sub-element means one new `@container style(...)` rule; nothing else changes.\n\n## Combining size and style in one block\n\nStyle and size queries compose. A single `@container` block can check both:\n\n```css\n@container card (max-width: 300px) and style(--theme: dark) {\n  .card-label {\n    font-size: 0.75rem;\n    color: var(--dark-muted);\n  }\n}\n```\n\nThis applies only when the container named `card` is narrow *and* has `--theme: dark`. The combination lets you encode conditional behavior in CSS that would otherwise require a computed class name or inline style injection.\n\n## One thing to remember about the container\n\nThe `container-type` declaration is still needed on the ancestor for style queries to work — it establishes the containment context that `@container style(...)` queries against. If you only need style queries and not size queries, you can use `container-type: normal` (or just set `container-name` without a type). Without any container declaration on the ancestor, the style query has nothing to inspect and applies nothing.\n\n```css\n\u002F* Size + style queries: use inline-size or size *\u002F\n.card { container-type: inline-size; }\n\n\u002F* Style queries only — no size containment needed *\u002F\n.theme-root { container-name: themed; }\n\n@container themed style(--theme: dark) { ... }\n```\n\n## Browser support\n\nStyle queries are **Baseline 2024**: Chrome 111 (March 2023), Firefox 110 (February 2023), Safari 17.2 (December 2023). All three major engines shipped within the same year. If your project already uses container size queries, style queries are available in the same browsers.\n\n\n\u003C!-- playground:start -->\n\n## 🎮 Try it yourself\n\n**[▶️ Open the interactive playground →](https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fposts\u002F2026-08-06-css-style-queries-react-to-custom-properties\u002Fplayground\u002F)**\n\n_Runs right in your browser — poke at it and watch the concept react live._\n\n\u003C!-- playground:end -->\n\n\u003C!-- quiz:start -->\n\n## 🧠 Test yourself\n\nThink it clicked? **[Take the 9-question quiz →](https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fquiz\u002Ftake.html?post=2026-08-06-css-style-queries-react-to-custom-properties)**\n\n_Instant feedback, a hint on every question, and an explanation for each answer — right or wrong._\n\n\u003C!-- quiz:end -->\n## The takeaway\n\nScan your codebase for places where JavaScript reads a state value and then toggles a CSS class to change a component's appearance. If that state is already encoded as a CSS custom property on an ancestor element, a style query can replace the JavaScript bridge entirely. The property carries the context down the tree; `@container style(...)` branches on it wherever the component appears. The component stays self-contained — it reads its environment rather than getting configuration pushed in from outside.\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":220,"canonical":221,"description":222},"Container queries can check more than size — style queries let compone","https:\u002F\u002Fbestpractic.org\u002Fblog\u002Fcss-style-queries-react-to-custom-properties","Size queries react to container width. Style queries react to CSS custom property values on a container ancestor — enabling component-level theming and variant switching in pure CS","019fe660-e5d0-756a-9ae2-270ea0958fa6",{"id":225,"locked":12},"019fe660-ed29-74cb-9f86-b7a1ca454350",[227],{"id":4,"slug":5,"title":7,"_count":228},{"questions":10},[230],{"locale":32,"slug":5},{"id":4,"slug":5,"title":7,"_count":232,"questionCount":10},{"questions":10}]