Styling the WordPress 6.9 Accordion block properly

A client reached out last week. They were rebuilding their FAQ page and wanted a branded accordion to match the rest of the site. That seemed simple until we dropped the new Accordion block from WordPress 6.9 onto the page. It worked fine as an accordion, but it looked plain, nothing like the styling they had in mind. Plenty of people are running into this now, or will soon. The Accordion block is a useful addition, but out of the box it comes unstyled. To make it match your theme, you need a consistent way to style WordPress Accordion blocks rather than patching them one at a time. My first instinct was to throw custom CSS at it. A border-radius here, a background-color there, an !important to force something stubborn into line. It held up for about a minute. Then the client asked for a different look in another section, and I ended up with a tangle of CSS that was miserable to maintain. That does not scale, and it is not really the right way to work with modern WordPress. You will regret it later. The better approach is to start with theme.json and then use targeted CSS only for the fine details. The Accordion block in WordPress 6.9 is not a single block; it is a nested set: core/accordion, core/accordion-item, core/accordion-heading, and core/accordion-panel. Each one gives you a place to hook your styles.

Styling WordPress Accordion blocks with theme.json

Start by setting your base styles in theme.json. That is where you define the global and block-specific styles the rest builds on. Here is a simplified example for core/accordion-item, the wrapper around each question and answer pair.
{
	"styles": {
		"blocks": {
			"core/accordion-item": {
				"border": {
					"color": "#d5dae2",
					"style": "solid",
					"width": "1px",
					"radius": "12px"
				},
				"color": {
					"background": "#f6f7f9",
					"text": "#343b46"
				},
				"shadow": "0 10px 15px -3px #80000080, 0 4px 6px -4px #80000080",
				"spacing": {
					"blockGap": "0"
				}
			}
		}
	}
}
That sets the borders, background, text color, and a shadow straight from the JSON. In a real project you would reference presets here rather than hard-coded values, but this keeps the example short. Next come core/accordion-heading and core/accordion-panel. The heading renders as an <h3> element, so your existing heading styles already apply to it, and you may want to reset or adjust them.
{
	"styles": {
		"blocks": {
			"core/accordion-heading": {
				"css": "&__toggle { padding: var(--wp--preset--spacing--40) var(--wp--style--block-gap); }",
				"typography": {
					"fontFamily": "inherit",
					"fontSize": "inherit",
					"fontStyle": "inherit",
					"fontWeight": "500",
					"lineHeight": "inherit",
					"textTransform": "inherit"
				}
			},
			"core/accordion-panel": {
				"spacing": {
					"padding": {
						"top": "var(--wp--style--block-gap)",
						"bottom": "var(--wp--style--block-gap)",
						"left": "var(--wp--style--block-gap)",
						"right": "var(--wp--style--block-gap)"
					}
				}
			}
		}
	}
}
The css property in theme.json is handy for the nested elements you cannot target directly, like the __toggle button inside the heading, and it keeps those styles in one place. The original article on developer.wordpress.org goes into more detail and has fuller examples.

Fine-tuning with custom block stylesheets

theme.json gets you most of the way, but some dynamic styling, like hover states or the open and closed appearance, is better handled in a dedicated block stylesheet. Create block-accordion.css in your theme’s assets and enqueue it with wp_enqueue_block_style(). That gives you precise control without bloating theme.json.
/* Add toggle button background on open/hover/focus. */
.wp-block-accordion-item.is-open .wp-block-accordion-heading__toggle,
.wp-block-accordion-heading__toggle:hover,
.wp-block-accordion-heading__toggle:focus {
	background: #eceff2; /* Use a preset here. */
}
Placed in block-accordion.css, this snippet changes the background when an item is open or hovered. It is a tidy way to handle those interactive cues. You can also add block style variations, such as a “Minimal” style, through separate JSON files and extra CSS, which gives editors more design options without leaving the editor. Splitting things up this way makes the styles easier to extend and maintain.

So, what’s the point?

The Accordion block is genuinely useful, but with any new feature, the payoff comes from knowing how to style and integrate it well. Avoid the quick-fix CSS trap. Set your base styles in theme.json and use block stylesheets for the interactive parts. Done that way, your accordion styling holds up whether it is a simple FAQ or a busier interactive section. The point is to work with WordPress rather than against it. This stuff gets complicated fast. If you are tired of debugging someone else’s mess and just want your site to work, drop my team a line. We have probably seen it before.
author avatar
Ahmad Wael
I'm a WordPress and WooCommerce developer with 15+ years of experience building custom e-commerce solutions and plugins. I specialize in PHP development, following WordPress coding standards to deliver clean, maintainable code. Currently, I'm exploring AI and e-commerce by building multi-agent systems and SaaS products that integrate technologies like Google Gemini API with WordPress platforms, approaching every project with a commitment to performance, security, and exceptional user experience.