Right, let's talk about feature detection. For years, we've had a bit of a blind spot in our CSS architecture: we could detect properties, but we couldn't reliably detect the rules that contain them. If you wanted to check if a browser supported @layer or @scope, you were often stuck using 'proxy properties' or, worse, heavy JavaScript libraries.
That's finally changed. The introduction of the at-rule() function inside @supports gives us a native, declarative way to gate modern CSS features. It's a game-changer for those of us building large-scale design systems who want to ship cutting-edge features without breaking the experience for users on older engines.
The Problem with Traditional Feature Queries
Standard @supports queries are great for checking property-value pairs. You've likely used @supports (display: grid) a thousand times. But these queries only check if a declaration is valid; they don't tell you if the browser understands the structural at-rule surrounding it.
In the past, if you wanted to detect @layer, you might have looked for a property that shipped at the same time. It was a bit like guessing if a house has a kitchen by checking if there's a toaster in the driveway. It works, but it's hardly robust.
Enter the at-rule() Function
The at-rule() function allows the browser to explicitly confirm if it recognises a specific at-rule in any context. As Bramus Van Damme noted, this function simply checks for recognition, making it the perfect gatekeeper for modern layout logic.
/* The new standard for at-rule detection */
@supports at-rule(@layer) {
@layer base, components, utilities;
@layer base {
body {
font-family: system-ui;
}
}
}
I've found this particularly useful when migrating design systems to Cascade Layers. Instead of a 'big bang' release, you can safely wrap your layered architecture in a supports block, ensuring that older browsers still receive a flat, functional stylesheet.
The Meta-Detection Pattern
Because at-rule() is itself a new feature, we need to be careful. You can't just start using it and assume the browser knows what to do. The most robust pattern involves a 'meta-check' to see if the browser supports the at-rule() function itself within @supports.
/* First: detect support for the detection function itself */
@supports at-rule(@supports) {
/* Now detect specific modern features */
@supports at-rule(@container) {
.card-layout {
display: grid;
grid-template-columns: 1fr 1fr;
}
}
@supports at-rule(@scope) {
@scope (.card) {
:scope {
border: 1px solid var(--border-color);
}
}
}
}
Design System Implementation Strategy
When I'm architecting a design system, I treat these queries as native feature flags. It allows us to move away from JavaScript-heavy solutions like Modernizr. Here's how I suggest structuring your tokens and components:
- Base Styles: Keep these outside of any complex at-rules to ensure 100% reach.
- Enhancements: Use
at-rule(@container)orat-rule(@view-transition)to wrap advanced motion or layout logic. - Architecture: Use
at-rule(@layer)to organise the cascade for browsers that support it, while providing a fallback bundle for those that don't.
One common misconception I see is developers thinking @supports is a guarantee that a feature is bug-free. It's not. It only tells you the browser claims to support it. You still need to test, but at least now you have a reliable way to start the conversation with the engine.
Wrapping Up
- Stop using proxy properties; use
at-rule()to detect@layer,@scope, and@containerdirectly. - Always use the meta-check
@supports at-rule(@supports)to gate the use of the detection function itself. - Treat CSS feature queries as native flags to reduce your dependency on JavaScript for styling logic.
I'd encourage you to try nesting your next experimental feature inside one of these blocks. It feels much cleaner than managing class names via JS just to get a container query working safely.
If you want to go deeper and learn how to build real, production-ready CSS design systems step by step, check out my full course here: CSS Design Systems Course
The long version with support labels and runnable demos is in Modern CSS 2026 on Amazon Kindle.
Feel free to reach out if you've found any interesting edge cases with this. You can find me on Twitter or LinkedIn.