WordPress 7.0 just introduced Custom CSS for individual block instances, and honestly, it’s about time. We’ve been stuck in a “workaround hell” since version 6.2, where styling a single block required a tedious two-step dance of adding a CSS class and then hunting down the Global Styles panel. Furthermore, this update finally bridges the gap between layout flexibility and maintainable code.
In my 14 years of wrestling with WordPress, I’ve seen countless sites bloated with “one-off” CSS classes. Consequently, this new feature doesn’t just make things easier for content editors; it cleans up the stylesheet debt we’ve been carrying for years. Specifically, it allows you to target a single block directly within the block inspector, using the same scoped syntax we’re used to in the Site Editor.
The Problem with the Old Way
Previously, if you wanted a specific Heading block to have a unique hover effect, you had to manually add an “Additional CSS Class” in the Advanced panel. Then, you’d have to go into the Site Editor’s global Custom CSS field to write the actual rules. This was a nightmare for stability and a major bottleneck for editors who didn’t have full admin permissions.
This process was not obvious to most users. Consequently, many ended up installing heavy styling plugins to do what should have been a native feature. You can check out more about how WordPress has been evolving its styling system in my previous post on native block CSS and layout fixes.
How Custom CSS for individual block instances Works
Under the hood, WordPress registers a new customCSS support. When you type your declarations into the new input field, it’s stored as an attribute. Specifically, it lives inside the block’s style attribute under the css key.
<!-- wp:heading {"style":{"css":"&:hover { color: orange; }\n"}} -->
<h2 class="wp-block-heading has-custom-css">Dynamic Heading</h2>
<!-- /wp:heading -->
At render time, WordPress generates a unique hash-based class for that specific instance. This ensures your styles don’t leak into other blocks. Therefore, the frontend output looks something like this:
<style id="wp-block-custom-css">
:root :where(.wp-custom-css-8841bf3c3cc9) {
color: blue;
}
</style>
<h2 class="wp-block-heading has-custom-css wp-custom-css-8841bf3c3cc9">Heading</h2>
The generated stylesheet is registered with a dependency on global-styles. This ensures that your instance-level CSS properly overrides the defaults. It’s similar to how WordPress 7.0 dimensions support simplifies layout controls without external stylesheets.
Opting Out and Custom Blocks
If you’re a block author, you might have blocks where adding a root-level class breaks the rendering (like raw HTML or shortcode wrappers). In those cases, you can opt out in your block.json file.
{
"supports": {
"customCSS": false
}
}
For server-side rendered blocks, WordPress uses the WP_HTML_Tag_Processor to inject the necessary classes. This is a robust way to handle dynamic attributes without messy regex hacks. For further technical details, you should review the PR #73959 or the official Block Supports API reference.
Look, if this Custom CSS for individual block instances stuff is eating up your dev hours, let me handle it. I’ve been wrestling with WordPress since the 4.x days.
The Takeaway
WordPress 7.0 is finally giving us the granularity we need. By utilizing Custom CSS for individual block instances, we can move away from “Additional CSS” workarounds and keep our styles scoped where they belong. Just remember: with great power comes great responsibility—don’t use this as an excuse to stop using proper Global Styles for site-wide consistency. For more context, check the official dev note.