惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
Simon Willison's Weblog
Simon Willison's Weblog
Microsoft Security Blog
Microsoft Security Blog
Y
Y Combinator Blog
The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
F
Fortinet All Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
A
About on SuperTechFans
Last Week in AI
Last Week in AI
月光博客
月光博客
有赞技术团队
有赞技术团队
P
Proofpoint News Feed
MyScale Blog
MyScale Blog
Martin Fowler
Martin Fowler
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
C
Check Point Blog
U
Unit 42
The Register - Security
The Register - Security
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Hugging Face - Blog
Hugging Face - Blog
阮一峰的网络日志
阮一峰的网络日志
V
Visual Studio Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
D
DataBreaches.Net
WordPress大学
WordPress大学
aimingoo的专栏
aimingoo的专栏
H
Hacker News: Front Page
Recent Announcements
Recent Announcements
C
CXSECURITY Database RSS Feed - CXSecurity.com
Latest news
Latest news
小众软件
小众软件
P
Palo Alto Networks Blog
PCI Perspectives
PCI Perspectives
Security Latest
Security Latest
S
Secure Thoughts
Scott Helme
Scott Helme
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Threat Research - Cisco Blogs
P
Proofpoint News Feed
M
MIT News - Artificial intelligence
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google DeepMind News
Google DeepMind News
Recorded Future
Recorded Future
O
OpenAI News
S
Securelist
云风的 BLOG
云风的 BLOG
H
Help Net Security
T
Troy Hunt's Blog

Articles on Smashing Magazine — For Web Designers And Developers

No, People Don’t Want More AI In Their Life — Smashing Magazine From Kickoff To First Concept: How To Turn Brand Strategy Into Visual Direction — Smashing Magazine Designing For Distressed Users: Why Mental Health Apps Shouldn’t Follow Every UI Fashion Meet Kirki: WordPress’s First Visual Builder With An Infinite Canvas — Smashing Magazine Users Don’t Need More Tools: They Need Seamless Integrations — Smashing Magazine Matching AI Modality To User Intent: Designing The Right Interface — Smashing Magazine Why Accessibility Is An Operational Capability, Not A Feature — Smashing Magazine Snapshots Of Summer (July 2026 Wallpapers Edition) — Smashing Magazine Designing With Uncertainty: How AI Supercharges Probabilistic Thinking — Smashing Magazine The Impact Of Humanoid Robots On Humanity — Smashing Magazine The Benefits Of Cognitive Inclusion In UX Research — Smashing Magazine How To Make Your Design System AI-Ready — Smashing Magazine June Is For Exploring (2026 Wallpapers Edition) — Smashing Magazine Algorithmic Theming Engines: Building Self-Correcting Color Systems With contrast-color() — Smashing Magazine Your Prototype Is Not Being Honest With Your Users (And Here’s How To Fix It) — Smashing Magazine Four Levels Of Customer Understanding — Smashing Magazine Advanced Tree Counting: Mathematical Layouts With sibling-index() And sibling-count() — Smashing Magazine Ten Data-Backed Truths Of User Experience ROI — Smashing Magazine Practical Interface Patterns For AI Transparency (Part 2) — Smashing Magazine The Architecture Of Local-First Web Development — Smashing Magazine Rethinking The Experience Of System Tools — Smashing Magazine Designing Stable Interfaces For Streaming Content — Smashing Magazine A Fresh View In May (2026 Wallpapers Edition) — Smashing Magazine The “Bug-Free” Workforce: How AI Efficiency Is Subtly Disrupting The Interactions That Build Strong Teams — Smashing Magazine The UX Designer’s Nightmare: When “Production-Ready” Becomes A Design Deliverable — Smashing Magazine Session Timeouts: The Overlooked Accessibility Barrier In Authentication Design — Smashing Magazine How To Improve UX In Legacy Systems — Smashing Magazine Identifying Necessary Transparency Moments In Agentic AI (Part 1) — Smashing Magazine A Practical Guide To Design Principles — Smashing Magazine The Joy Of A Fresh Beginning (April 2026 Wallpapers Edition) — Smashing Magazine The Site-Search Paradox: Why The Big Box Always Wins — Smashing Magazine Testing Font Scaling For Accessibility With Figma Variables — Smashing Magazine Modal vs. Separate Page: UX Decision Tree — Smashing Magazine Anime vs. Marvel/DC: Designing Digital Products With Emotion In Flow — Smashing Magazine Moving From Moment.js To The JS Temporal API — Smashing Magazine Beyond border-radius: What The CSS corner-shape Property Unlocks For Everyday UI — Smashing Magazine Building Dynamic Forms In React And Next.js — Smashing Magazine Persuasive Design: Ten Years Later — Smashing Magazine Human Strategy In An AI-Accelerated Workflow — Smashing Magazine Now Shipping: Accessible UX Research, A New Smashing Book By Michele Williams — Smashing Magazine Getting Started With The Popover API — Smashing Magazine Fresh Energy In March (2026 Wallpapers Edition) — Smashing Magazine Say Cheese! Meet SmashingConf Amsterdam 🇳🇱 — Smashing Magazine A Designer’s Guide To Eco-Friendly Interfaces — Smashing Magazine Designing A Streak System: The UX And Psychology Of Streaks — Smashing Magazine Building Digital Trust: An Empathy-Centred UX Framework For Mental Health Apps — Smashing Magazine Designing For Agentic AI: Practical UX Patterns For Control, Consent, And Accountability — Smashing Magazine Combobox vs. Multiselect vs. Listbox: How To Choose The Right One — Smashing Magazine Short Month, Big Ideas (February 2026 Wallpapers Edition) — Smashing Magazine Practical Use Of AI Coding Tools For The Responsible Developer — Smashing Magazine Unstacking CSS Stacking Contexts — Smashing Magazine Beyond Generative: The Rise Of Agentic AI And User-Centric Design — Smashing Magazine Rethinking “Pixel Perfect” Web Design — Smashing Magazine Smashing Animations Part 8: Theming Animations Using CSS Relative Colour — Smashing Magazine UX And Product Designer’s Career Paths In 2026 — Smashing Magazine Penpot Is Experimenting With MCP Servers For AI-Powered Design Workflows — Smashing Magazine Pivoting Your Career Without Starting From Scratch — Smashing Magazine Countdown To New Adventures (January 2026 Wallpapers Edition) — Smashing Magazine How To Design For (And With) Deaf People — Smashing Magazine Giving Users A Voice Through Virtual Personas — Smashing Magazine How To Measure The Impact Of Features — Smashing Magazine Smashing Animations Part 7: Recreating Toon Text With CSS And SVG — Smashing Magazine Accessible UX Research, eBook Now Available For Download — Smashing Magazine State, Logic, And Native Power: CSS Wrapped 2025 — Smashing Magazine How UX Professionals Can Lead AI Strategy — Smashing Magazine
CSS @scope: An Alternative To Naming Conventions And Heavy Abstractions — Smashing Magazine
About The Author · 2026-02-05 · via Articles on Smashing Magazine — For Web Designers And Developers

Prescriptive class name conventions are no longer enough to keep CSS maintainable in a world of increasingly complex interfaces. Can the new @scope rule finally give developers the confidence to write CSS that can keep up with modern front ends?

When learning the principles of basic CSS, one is taught to write modular, reusable, and descriptive styles to ensure maintainability. But when developers become involved with real-world applications, it often feels impossible to add UI features without styles leaking into unintended areas.

This issue often snowballs into a self-fulfilling loop; styles that are theoretically scoped to one element or class start showing up where they don’t belong. This forces the developer to create even more specific selectors to override the leaked styles, which then accidentally override global styles, and so on.

Rigid class name conventions, such as BEM, are one theoretical solution to this issue. The BEM (Block, Element, Modifier) methodology is a systematic way of naming CSS classes to ensure reusability and structure within CSS files. Naming conventions like this can reduce cognitive load by leveraging domain language to describe elements and their state, and if implemented correctly, can make styles for large applications easier to maintain.

In the real world, however, it doesn’t always work out like that. Priorities can change, and with change, implementation becomes inconsistent. Small changes to the HTML structure can require many CSS class name revisions. With highly interactive front-end applications, class names following the BEM pattern can become long and unwieldy (e.g., app-user-overview__status--is-authenticating), and not fully adhering to the naming rules breaks the system’s structure, thereby negating its benefits.

Given these challenges, it’s no wonder that developers have turned to frameworks, Tailwind being the most popular CSS framework. Rather than trying to fight what seems like an unwinnable specificity war between styles, it is easier to give up on the CSS Cascade and use tools that guarantee complete isolation.

Developers Lean More On Utilities

How do we know that some developers are keen on avoiding cascaded styles? It’s the rise of “modern” front-end tooling — like CSS-in-JS frameworks — designed specifically for that purpose. Working with isolated styles that are tightly scoped to specific components can seem like a breath of fresh air. It removes the need to name things — still one of the most hated and time-consuming front-end tasks — and allows developers to be productive without fully understanding or leveraging the benefits of CSS inheritance.

But ditching the CSS Cascade comes with its own problems. For instance, composing styles in JavaScript requires heavy build configurations and often leads to styles awkwardly intermingling with component markup or HTML. Instead of carefully considered naming conventions, we allow build tools to autogenerate selectors and identifiers for us (e.g., .jsx-3130221066), requiring developers to keep up with yet another pseudo-language in and of itself. (As if the cognitive load of understanding what all your component’s useEffects do weren’t already enough!)

Further abstracting the job of naming classes to tooling means that basic debugging is often constrained to specific application versions compiled for development, rather than leveraging native browser features that support live debugging, such as Developer Tools.

It’s almost like we need to develop tools to debug the tools we’re using to abstract what the web already provides — all for the sake of running away from the “pain” of writing standard CSS.

Luckily, modern CSS features not only make writing standard CSS more flexible but also give developers like us a great deal more power to manage the cascade and make it work for us. CSS Cascade Layers are a great example, but there’s another feature that gets a surprising lack of attention — although that is changing now that it has recently become Baseline compatible.

The CSS @scope At-Rule

I consider the CSS @scope at-rule to be a potential cure for the sort of style-leak-induced anxiety we’ve covered, one that does not force us to compromise native web advantages for abstractions and extra build tooling.

“The @scope CSS at-rule enables you to select elements in specific DOM subtrees, targeting elements precisely without writing overly-specific selectors that are hard to override, and without coupling your selectors too tightly to the DOM structure.”

MDN

In other words, we can work with isolated styles in specific instances without sacrificing inheritance, cascading, or even the basic separation of concerns that has been a long-running guiding principle of front-end development.

Plus, it has excellent browser coverage. In fact, Firefox 146 added support for @scope in December, making it Baseline compatible for the first time. Here is a simple comparison between a button using the BEM pattern versus the @scope rule:

<!-- BEM --> 
<button class="button button--primary">
  <span class="button__text">Click me</span>
  <span class="button__icon">→</span>
</button>

<style>
  .button .button__text { /* button text styles */ }
  .button .button__icon { /* button icon styles */ }
  .button--primary { primary button styles */ }
</style>
<!-- @scope --> 
<button class="primary-button">
  <span>Click me</span>
  <span>→</span>
</button>

<style>
  @scope (.primary-button) {
    span:first-child { /* button text styles */ }
    span:last-child { /* button icon styles */ }
  }
</style>

The @scope rule allows for precision with less complexity. The developer no longer needs to create boundaries using class names, which, in turn, allows them to write selectors based on native HTML elements, thereby eliminating the need for prescriptive CSS class name patterns. By simply removing the need for class name management, @scope can alleviate the fear associated with CSS in large projects.

Basic Usage

To get started, add the @scope rule to your CSS and insert a root selector to which styles will be scoped:

@scope (<selector>) {
  /* Styles scoped to the <selector> */
}

So, for example, if we were to scope styles to a <nav> element, it may look something like this:

@scope (nav) {
  a { /* Link styles within nav scope */ }

  a:active { /* Active link styles */ }

  a:active::before { /* Active link with pseudo-element for extra styling */ }

  @media (max-width: 768px) {
    a { /* Responsive adjustments */ }
  }
}

This, on its own, is not a groundbreaking feature. However, a second argument can be added to the scope to create a lower boundary, effectively defining the scope’s start and end points.

/* Any `a` element inside `ul` will not have the styles applied */
@scope (nav) to (ul) {
  a {
    font-size: 14px;
  }
}

This practice is called donut scoping, and there are several approaches one could use, including a series of similar, highly specific selectors coupled tightly to the DOM structure, a :not pseudo-selector, or assigning specific class names to <a> elements within the <nav> to handle the differing CSS.

Regardless of those other approaches, the @scope method is much more concise. More importantly, it prevents the risk of broken styles if classnames change or are misused or if the HTML structure were to be modified. Now that @scope is Baseline compatible, we no longer need workarounds!

We can take this idea further with multiple end boundaries to create a “style figure eight”:

/* Any <a> or <p> element inside <aside> or <nav> will not have the styles applied */
@scope (main) to (aside, nav) {
  a {
    font-size: 14px;
  }
  p {
    line-height: 16px;
    color: darkgrey;
  }
}

Compare that to a version handled without the @scope rule, where the developer has to “reset” styles to their defaults:

main a {
  font-size: 14px;
}

main p {
  line-height: 16px;
  color: darkgrey;
}

main aside a,
main nav a {
  font-size: inherit; /* or whatever the default should be */
}

main aside p,
main nav p {
  line-height: inherit; /* or whatever the default should be */
  color: inherit; /* or a specific color */
}

Check out the following example. Do you notice how simple it is to target some nested selectors while exempting others?

See the Pen [@scope example [forked]](https://codepen.io/smashingmag/pen/wBWXggN) by Blake Lundquist.

See the Pen @scope example [forked] by Blake Lundquist.

Consider a scenario where unique styles need to be applied to slotted content within web components. When slotting content into a web component, that content becomes part of the Shadow DOM, but still inherits styles from the parent document. The developer might want to implement different styles depending on which web component the content is slotted into:

<!-- Same <user-card> content, different contexts -->
<product-showcase>
  <user-card slot="reviewer">
    <img src="avatar.jpg" slot="avatar">
    <span slot="name">Jane Doe</span>
  </user-card>
</product-showcase>

<team-roster>
  <user-card slot="member">
    <img src="avatar.jpg" slot="avatar">
    <span slot="name">Jane Doe</span>
  </user-card>
</team-roster>

In this example, the developer might want the <user-card> to have distinct styles only if it is rendered inside <team-roster>:

@scope (team-roster) {
  user-card {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
  }
  
  user-card img {
    border-radius: 50%;
    width: 40px;
    height: 40px;
  }
}

More Benefits

There are additional ways that @scope can remove the need for class management without resorting to utilities or JavaScript-generated class names. For example, @scope opens up the possibility to easily target descendants of any selector, not just class names:

/* Only div elements with a direct child button are included in the root scope */
@scope (div:has(> button)) {
  p {
    font-size: 14px;
  }
}

And they can be nested, creating scopes within scopes:

@scope (main) {
  p {
    font-size: 16px;
    color: black;
  }
  @scope (section) {
    p {
      font-size: 14px;
      color: blue;
    }
    @scope (.highlight) {
      p {
        background-color: yellow;
        font-weight: bold;
      }
    }
  }
}

Plus, the root scope can be easily referenced within the @scope rule:

/* Applies to elements inside direct child `section` elements of `main`, but stops at any direct `aside` that is a direct chiled of those sections */
@scope (main > section) to (:scope > aside) {
  p {
    background-color: lightblue;
    color: blue;
  }
  /* Applies to ul elements that are immediate siblings of root scope  */
  :scope + ul {
    list-style: none;
  }
}

The @scope at-rule also introduces a new proximity dimension to CSS specificity resolution. In traditional CSS, when two selectors match the same element, the selector with the higher specificity wins. With @scope, when two elements have equal specificity, the one whose scope root is closer to the matched element wins. This eliminates the need to override parent styles by manually increasing an element’s specificity, since inner components naturally supersede outer element styles.

<style>
  @scope (.container) {
    .title { color: green; } 
  }
  <!-- The <h2> is closer to .container than to .sidebar so "color: green" wins. -->
  @scope (.sidebar) {
    .title { color: red; }
  }
</style>

<div class="sidebar">
  <div class="container">
    <h2 class="title">Hello</h2>
  </div>
</div>

Conclusion

Utility-first CSS frameworks, such as Tailwind, work well for prototyping and smaller projects. Their benefits quickly diminish, however, when used in larger projects involving more than a couple of developers.

Front-end development has become increasingly overcomplicated in the last few years, and CSS is no exception. While the @scope rule isn’t a cure-all, it can reduce the need for complex tooling. When used in place of, or alongside strategic class naming, @scope can make it easier and more fun to write maintainable CSS.

Further Reading

Smashing Editorial (gg, yk)