{"id":10360,"date":"2026-07-09T10:30:37","date_gmt":"2026-07-09T15:30:37","guid":{"rendered":"https:\/\/master.dev\/blog\/?p=10360"},"modified":"2026-07-09T10:30:38","modified_gmt":"2026-07-09T15:30:38","slug":"thinking-horizontally-in-css-layer","status":"publish","type":"post","link":"https:\/\/master.dev\/blog\/thinking-horizontally-in-css-layer\/","title":{"rendered":"Thinking Horizontally in CSS @layer"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">I joked the other day:<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-rich is-provider-bluesky-social wp-block-embed-bluesky-social\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"bluesky-embed\" data-bluesky-uri=\"at:\/\/did:plc:xhhcrzsilpamjmz4dvrpt7df\/app.bsky.feed.post\/3mp62ulrzac2w\" data-bluesky-cid=\"bafyreicpdje5zw6akwdnvy54xn3pz6cupjmm6t7fgzse26scmhe3dplwpu\"><p lang=\"en\">wait is @layer like z-index but for CSS itself<\/p>&mdash; <a href=\"https:\/\/bsky.app\/profile\/did:plc:xhhcrzsilpamjmz4dvrpt7df?ref_src=embed\">Chris Coyier (@chriscoyier.net)<\/a> <a href=\"https:\/\/bsky.app\/profile\/did:plc:xhhcrzsilpamjmz4dvrpt7df\/post\/3mp62ulrzac2w?ref_src=embed\">2026-06-26T04:04:38.605Z<\/a><\/blockquote><script async src=\"https:\/\/embed.bsky.app\/static\/embed.js\" charset=\"utf-8\"><\/script>\n<\/div><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">I know what CSS <code>@layer<\/code> is, and maybe you do too. This won&#8217;t be a reiteration of the rhyme and reason of the feature itself. For that, you probably can&#8217;t do better than <a href=\"https:\/\/css-tricks.com\/css-cascade-layers\/\">Miriam&#8217;s guide<\/a>. Rather, this will be about a different way of thinking about layers that might be useful to you.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The point of my lame observational joke is that we tend to think of CSS <code>@layer<\/code> as a vertical concern. This is true of so many other CSS concepts. Like inline styles are above styles applied in a stylesheet. Your user-authored styles are above the user-agent styles that browsers ship and apply to all pages. But the main thing we think about is specificity. IDs are stronger than classes are stronger than elements, and all that.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Along comes <code>@layer<\/code> and it can make us think even <em>more<\/em> vertically. Now, we essentially &#8220;stack&#8221; layers. Styles in a higher layer are more powerful <em>(regardless of specificity)<\/em> than styles in a lower layer. So our code can literally be structured like this, which is also a vertical stack. <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"597\" height=\"1024\" src=\"https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/stack-of-layers.png?resize=597%2C1024&#038;ssl=1\" alt=\"@layers named and structured like in a CSS file, emphasizing a vertical stack.\" class=\"wp-image-10361\" style=\"width:295px;height:auto\" srcset=\"https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/stack-of-layers.png?resize=597%2C1024&amp;ssl=1 597w, https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/stack-of-layers.png?resize=175%2C300&amp;ssl=1 175w, https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/stack-of-layers.png?resize=768%2C1317&amp;ssl=1 768w, https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/stack-of-layers.png?w=800&amp;ssl=1 800w\" sizes=\"auto, (max-width: 597px) 100vw, 597px\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">You can also be specific about layering them.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@layer<\/span> reset, defaults, patterns, components, utilities, overrides;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">I like that, myself, as it freaks me out a little bit that otherwise each <code>@layer<\/code> is stacked through source order alone. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">There is another little bit of syntax that I find interesting: sub-layers. You use a dot\/period for this, like:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@layer<\/span> components.button {\n\n}\n<span class=\"hljs-keyword\">@layer<\/span> components.card {\n\n}\n<span class=\"hljs-keyword\">@layer<\/span> components.grid {\n\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">So now all these layers are still slotted into the power hierarchy, where the <code>components<\/code> is, but then have their own sub-heirarchy, which would be source-order, unless we force it ourselves like:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@layer<\/span> \n  reset,\n  defaults,\n  components,\n    components.button,\n    components.card,\n    components.grid,\n  patterns,\n  ...;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">The Thing About Components: There Are Many<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Maybe you have like 50? 100? 374? <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And if you&#8217;re like me (and a lot of front-end architectures!), you like the one-CSS-file-per-component setup (sometimes <a href=\"https:\/\/frontendmasters.com\/blog\/architecture-through-component-colocation\/\">like this<\/a>). <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">With this many components and many CSS files, the point is: who cares about the vertical ordering of the layers? It just doesn&#8217;t matter which component&#8217;s styles beat another component&#8217;s styles.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So you can either just not name them:<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\"><pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\">\/\/ <span class=\"hljs-selector-tag\">components<\/span>\/<span class=\"hljs-selector-tag\">button<\/span>\/<span class=\"hljs-selector-tag\">button<\/span><span class=\"hljs-selector-class\">.css<\/span>\n<span class=\"hljs-keyword\">@layer<\/span> components {\n  <span class=\"hljs-selector-class\">.button<\/span> {\n     <span class=\"hljs-comment\">\/* button styles *\/<\/span>\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre><\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\"><pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\">\/\/ <span class=\"hljs-selector-tag\">components<\/span>\/<span class=\"hljs-selector-tag\">card<\/span>\/<span class=\"hljs-selector-tag\">card<\/span><span class=\"hljs-selector-class\">.css<\/span>\n<span class=\"hljs-keyword\">@layer<\/span> components {\n  <span class=\"hljs-selector-class\">.card<\/span> {\n     <span class=\"hljs-comment\">\/* card styles *\/<\/span>\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre><\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Or\u00a0do\u00a0name them (just &#8220;in case&#8221;), but don&#8217;t even bother to order them specifically,\u00a0because it <em>probably <\/em>doesn&#8217;t matter.<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\"><pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\">\/\/ <span class=\"hljs-selector-tag\">components<\/span>\/<span class=\"hljs-selector-tag\">button<\/span>\/<span class=\"hljs-selector-tag\">button<\/span><span class=\"hljs-selector-class\">.css<\/span>\n<span class=\"hljs-keyword\">@layer<\/span> components.button {\n  <span class=\"hljs-selector-class\">.button<\/span> {\n     <span class=\"hljs-comment\">\/* button styles *\/<\/span>\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre><\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\"><pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\">\/\/ <span class=\"hljs-selector-tag\">components<\/span>\/<span class=\"hljs-selector-tag\">card<\/span>\/<span class=\"hljs-selector-tag\">card<\/span><span class=\"hljs-selector-class\">.css<\/span>\n<span class=\"hljs-keyword\">@layer<\/span> components.card {\n  <span class=\"hljs-selector-class\">.card<\/span> {\n     <span class=\"hljs-comment\">\/* card styles *\/<\/span>\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre><\/div>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">A Component Might Have Layered and Unlayered Styles<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You can already get some level of CSS scoping to a component, even without any fancy tools. Say you have a <code>Card<\/code> component (as we&#8217;ve been using an example), it could just have that class of Card, and you nest everything beneath that, and that&#8217;s that.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-class\">.card<\/span> {\n  .title {\n  }\n  <span class=\"hljs-selector-class\">.meta<\/span> {\n  }\n  <span class=\"hljs-comment\">\/* etc. *\/<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Or perhaps you have some naming convention like BEM or whatever.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Maybe you get even fancier and use <code>@scope<\/code> like:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@scope<\/span> (.card) {\n\n}\n\n<span class=\"hljs-comment\">\/* or you have a custom element *\/<\/span>\n<span class=\"hljs-keyword\">@scope<\/span> (design-system-card) {\n\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">You could even use <a href=\"https:\/\/frontendmasters.com\/blog\/name-only-containers-the-scoping-we-needed\/\">a name-only container query<\/a>, which I find kind of satisfying for some reason.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-comment\">\/* Name a container *\/<\/span>\n<span class=\"hljs-selector-class\">.card<\/span> {\n  <span class=\"hljs-attribute\">container-name<\/span>: ds-card;\n  <span class=\"hljs-attribute\">container-type<\/span>: inline-size;\n}\n\n<span class=\"hljs-comment\">\/* Write styles with that name only, no conditions *\/<\/span>\n<span class=\"hljs-keyword\">@container<\/span> ds-card {\n  <span class=\"hljs-selector-class\">.title<\/span> {\n    <span class=\"hljs-comment\">\/* classes like me won't \"leak out\" *\/<\/span>\n  }\n  <span class=\"hljs-selector-class\">.meta<\/span> {\n  }\n  <span class=\"hljs-comment\">\/* etc. *\/<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Literally any of that will work with what I&#8217;m about to show. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The idea is that you layer the tokens the component uses, and you <em>don&#8217;t<\/em> layer scoped stuff.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@layer<\/span> components.card {\n  <span class=\"hljs-comment\">\/* intentionally weakened so any other selector can override values *\/<\/span>\n  <span class=\"hljs-selector-class\">.card<\/span> {\n    <span class=\"hljs-attribute\">--card-bg<\/span>: black;\n    <span class=\"hljs-attribute\">--card-color<\/span>: white;\n    <span class=\"hljs-comment\">\/* etc. *\/<\/span>\n  }\n}\n\n<span class=\"hljs-comment\">\/* Scope for protection while retaining some strength *\/<\/span>\n<span class=\"hljs-keyword\">@scope<\/span> (.card) {\n  <span class=\"hljs-selector-tag\">background<\/span>: <span class=\"hljs-selector-tag\">var<\/span>(<span class=\"hljs-selector-tag\">--card-bg<\/span>);\n  <span class=\"hljs-selector-tag\">color<\/span>: <span class=\"hljs-selector-tag\">var<\/span>(<span class=\"hljs-selector-tag\">--card-color<\/span>);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">The Point is Intentionally Weak Tokens<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">I don&#8217;t want to have to fight to override tokens. That should be really easy. I don&#8217;t want to think about source order or if the selector I&#8217;m using is strong enough to do the job. In the code block above, because I&#8217;ve used <code>@layer<\/code> to wrap where I&#8217;m setting the tokens, any higher layer, <strong>and definitely unlayered CSS, <\/strong>can target the card and override the variables. No fighting.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Now We&#8217;re in Horizontal-Town<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Imagine you do this on all your components. You&#8217;ve basically got two-layer components, but a ton of them. It&#8217;s now much less about the vertical ordering. It&#8217;s a short, fat, horizontal setup.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"287\" src=\"https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/horizontal.png?resize=1024%2C287&#038;ssl=1\" alt=\"\" class=\"wp-image-10366\" srcset=\"https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/horizontal-scaled.png?resize=1024%2C287&amp;ssl=1 1024w, https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/horizontal-scaled.png?resize=300%2C84&amp;ssl=1 300w, https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/horizontal-scaled.png?resize=768%2C215&amp;ssl=1 768w, https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/horizontal-scaled.png?resize=1536%2C431&amp;ssl=1 1536w, https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/horizontal-scaled.png?resize=2048%2C575&amp;ssl=1 2048w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Maybe calling it &#8220;horizontal&#8221; is a stretch or a weird way to think about it. But it&#8217;s useful to me! I think it&#8217;s a bit overwhelming to consider the vertical stacking order of potentially hundreds of items. But you don&#8217;t have to care. You don&#8217;t have to think of it that way. You can think of it horizontally, where each component is essentially just a two-stacker.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Here&#8217;s a Real-World Example of it Being Very Useful<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This is literally what we do with components at CodePen. Here&#8217;s a screenshot with a couple of random component CSS files open side by side. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"416\" src=\"https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/Screenshot-2026-07-08-at-4.42.38-PM.png?resize=1024%2C416&#038;ssl=1\" alt=\"\" class=\"wp-image-10367\" srcset=\"https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/Screenshot-2026-07-08-at-4.42.38-PM-scaled.png?resize=1024%2C416&amp;ssl=1 1024w, https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/Screenshot-2026-07-08-at-4.42.38-PM-scaled.png?resize=300%2C122&amp;ssl=1 300w, https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/Screenshot-2026-07-08-at-4.42.38-PM-scaled.png?resize=768%2C312&amp;ssl=1 768w, https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/Screenshot-2026-07-08-at-4.42.38-PM-scaled.png?resize=1536%2C624&amp;ssl=1 1536w, https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/Screenshot-2026-07-08-at-4.42.38-PM-scaled.png?resize=2048%2C832&amp;ssl=1 2048w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Notice we use <code>.module.scss<\/code> files. Both Sass and CSS modules. That&#8217;s neither here nor there for the point of this post, but it works great for us. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We also have &#8220;library&#8221; components, which are &#8220;dumb,&#8221; meaning they can&#8217;t do things like query for data and don&#8217;t have other custom components as children. Those are vertically layered underneath just &#8220;components&#8221;, which are more compositional.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Generally, the root node of a component has the class &#8220;root&#8221; as a convention for us, and to avoid having to name it explicitly. It literally doesn&#8217;t matter what it&#8217;s named because of the scoping.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The important bit to this article is how we are <code>@layer<\/code>ing all the custom properties that each component uses. This makes it very easy for us to override them whenever needed, which is good, actually, and why they are there in the first place. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I really dislike it when we find ourselves using like <code>.root.root<\/code> style class names just to increase specificity to make a custom property win somewhere. Putting custom properties into a layer at all makes them so &#8220;weak&#8221; that pretty much anything can override them, even when targeting the element with a very weak (yet unlayered) style.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Demo<\/h2>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_019f3a92-0f00-7f23-9ba8-417d6c0f02c4\" src=\"\/\/codepen.io\/editor\/anon\/embed\/019f3a92-0f00-7f23-9ba8-417d6c0f02c4?height=650&amp;theme-id=1&amp;slug-hash=019f3a92-0f00-7f23-9ba8-417d6c0f02c4&amp;default-tab=result\" height=\"650\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed 019f3a92-0f00-7f23-9ba8-417d6c0f02c4\" title=\"CodePen Embed 019f3a92-0f00-7f23-9ba8-417d6c0f02c4\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Now I could take a weak-but-meaningfully-specific selector to the cards and override a custom property (token):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">ui-card<\/span> {\n  <span class=\"hljs-attribute\">--card-font<\/span>: fantasy;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">And bask in typographic glory:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"567\" src=\"https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/Screenshot-2026-07-09-at-8.20.21-AM.png?resize=1024%2C567&#038;ssl=1\" alt=\"\" class=\"wp-image-10374\" srcset=\"https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/Screenshot-2026-07-09-at-8.20.21-AM.png?resize=1024%2C567&amp;ssl=1 1024w, https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/Screenshot-2026-07-09-at-8.20.21-AM.png?resize=300%2C166&amp;ssl=1 300w, https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/Screenshot-2026-07-09-at-8.20.21-AM.png?resize=768%2C426&amp;ssl=1 768w, https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/Screenshot-2026-07-09-at-8.20.21-AM.png?resize=1536%2C851&amp;ssl=1 1536w, https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/Screenshot-2026-07-09-at-8.20.21-AM.png?w=1754&amp;ssl=1 1754w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>If you put your custom properties (tokens) for every component in an @layer, then overriding them is never a fight.<\/p>\n","protected":false},"author":1,"featured_media":10376,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[1],"tags":[511,512,7,180,24],"class_list":["post-10360","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","tag-layer","tag-components","tag-css","tag-custom-properties","tag-design"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/07\/horizontally.jpg?fit=2000%2C1200&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/master.dev\/blog\/wp-json\/wp\/v2\/posts\/10360","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/master.dev\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/master.dev\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/master.dev\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/master.dev\/blog\/wp-json\/wp\/v2\/comments?post=10360"}],"version-history":[{"count":10,"href":"https:\/\/master.dev\/blog\/wp-json\/wp\/v2\/posts\/10360\/revisions"}],"predecessor-version":[{"id":10378,"href":"https:\/\/master.dev\/blog\/wp-json\/wp\/v2\/posts\/10360\/revisions\/10378"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/master.dev\/blog\/wp-json\/wp\/v2\/media\/10376"}],"wp:attachment":[{"href":"https:\/\/master.dev\/blog\/wp-json\/wp\/v2\/media?parent=10360"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/master.dev\/blog\/wp-json\/wp\/v2\/categories?post=10360"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/master.dev\/blog\/wp-json\/wp\/v2\/tags?post=10360"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}