How to set default block styles in a block theme

By Ian Svoboda on March 25, 2026

In this post I’ll walk you through how to style blocks using the Site Editor’s Global Styles interface, how to use “Additional CSS” for more advanced customizations (like hover states and targeting descendant elements), and how to persist everything back to your theme files using Create Block Theme.

The site editor UI has many options for styling global elements, but you can also style specific blocks too. While you can absolutely do this with stylesheets, being able to make these changes in the editor and have immediate real-time feedback is really valuable for speed.

This makes it really easy to iterate quickly on your designs without having to leave the editor at all and lets you do things fast. All while still supporting version control, which is very commonly used on bigger client projects or internal projects at companies where that sort of thing matters.

There are global styles for typography and color that can apply to one or more elements, but those are not block-specific. I’m going to show you how to set block-specific global styles that apply to all instances of the block by default.

What are Global Styles for blocks?

When you open the Site Editor and click on the Styles panel (the half-filled circle icon in the top right), you’ll see options for Typography, Colors, Background, Shadows, and Layout. These are your global styles that apply to the entire site.

But at the bottom of that panel, you’ll also see a “Blocks” section. This is where things get really interesting.

Screenshot of the global styles UI in the site editor with the Blocks button outlined in blue.

Clicking on “Blocks” gives you a list of every registered block type. From there, you can select any block and customize its default appearance across your site. For example, you could change the default font size for all Paragraph blocks, set a background color for all Group blocks, or adjust the border radius on all Image blocks.

The key thing to understand here is that these are defaults. Users can still override them on individual block instances. But by setting sensible defaults at the theme level, you can ensure consistency across your site without having to style each block one at a time.

Styling a block: the basics

Let’s start with a simple example. Say you want to customize the appearance of the Button block across your site.

  1. Open the Site Editor (Appearance > Editor)
  2. Click the Styles icon (half-filled circle) in the top right
  3. Scroll down and click “Blocks”
  4. Search for or select “Button”

From here, you’ll see the same familiar style controls you’d see when editing an individual block: typography, colors, spacing, borders, and so on. Any changes you make here will apply to all Button blocks on your site as the default style.

Screenshot of the default block styles selection UI in the site editor
Screenshot of the default styles edit UI for the button block

For example, you could set a specific background color, adjust the padding, add a border radius, or change the font weight. These are the same design tools you’re used to from the block editor, just applied globally instead of to a single instance.

Going further with Additional CSS

The built-in style controls cover a lot of ground, but there are situations where you need more control than the UI provides. That’s where “Additional CSS” comes in.

If you scroll down in a block’s style panel and expand the “Advanced” section, you’ll find a text area labeled “Additional CSS.” This lets you write raw CSS that applies to all instances of that block type.

Screenshot of the additional CSS tab for default block styles

By default, you won’t need to add a CSS selector. WordPress automatically scopes your CSS to the correct block. So if you’re adding styles to the Button block, you just write the properties and values directly.

For instance, if you wanted to add a subtle transition to all buttons:

CSS
transition: all 0.2s ease;

That’s it. WordPress handles the selector for you. This CSS gets applied to both the editor and the front end of your site, so what you see is what you get.

Adding hover styles with the & selector

One of the most common things people want to do is add hover styles to buttons. The Site Editor does have a hover color option for links (since WordPress 6.3), but buttons don’t have a dedicated hover UI in the style controls (as of WordPress 6.9).

This is where the & selector becomes incredibly useful. Inside the Additional CSS field, you can use & to reference the current block’s selector and append pseudo-classes or target descendant elements.

For a Button block, you could add a hover effect like this:

CSS
transition: background-color 0.2s ease;

&:hover { 
  background-color: var(--wp--preset--color--secondary);  
}

The & here represents the block’s own selector, so &:hover compiles to something like .wp-block-button__link:hover in the final output. The button block’s additional CSS targets the inner a tag, instead of the wrapping div element.

HTML
<div class="wp-block-button">
  <a class="wp-block-button__link wp-element-button">Button 1</a>
</div>

You may notice I used a CSS variable here. If you’re working with colors, you should be using the colors from your palette as much as possible. All colors you add into the settings.colors.palette array (in theme.json or via Global Styles) will have a CSS variable generated for them based on the color’s slug (ex: secondary).

You can use this same approach for :focus, :active, :focus-visible, and any other pseudo-class you need:

CSS
&:focus-visible { 
  outline: 3px solid var(--wp--preset--color--primary); 
  outline-offset: 2px; 
}

You can also combine the & with :not(), :has(), and other pseudo-selectors to get really specific:

CSS
&:not(.is-style-plain) { 
  list-style-type: "circle"; 
}

Targeting descendant elements with &

The & selector isn’t just for pseudo-classes. You can also use it to target child or descendant elements inside a block. This is especially useful for blocks that contain nested HTML elements.

One example applies to the List and List Item blocks. List item blocks represent an <li> tag that goes inside a list. So those could be styled individually just like a list could. But what if you want to get even numbered list items or target the first list item in a nested list? You’d need to target those list items based on their parent container.

Thankfully the ampersand (&) can allow you to select child elements as well as the block itself.

CSS
/* Remove the margin from the first list item in a nested list only */
& ul > li:first-child {
  margin-block: 0;
}

The & ul > li:first-child compiles to something like .wp-block-list ul > li:first-child in the final CSS output.

Saving your styles to theme.json with Create Block Theme

So you’ve customized your blocks in the Site Editor, added some Additional CSS, and everything looks great. But here’s the thing: those changes are stored in the database as “user” styles. They’re not part of your theme files. If you export your theme or set it up on another site, those customizations won’t come along for the ride.

This is where the Create Block Theme plugin comes in. If you’re not familiar with it, Create Block Theme is a plugin from the WordPress project itself that lets you save changes made in the Site Editor back to your theme’s files.

Here’s how to save your block style customizations:

  1. Install and activate the Create Block Theme plugin
  2. Make your style changes in the Site Editor as described above
  3. Go to edit any template, then click the Create Block Theme icon (the wrench icon) next to the Save button at the top of the editor
  4. Select “Save Changes to Theme”
  5. Check “Save Style Changes”
  6. Click “Save Changes”

Note:
Carefully consider which options are enabled in Create Block Theme. You should read and understand each one you enable and if you’re not sure what you need, just check the boxes you’re sure about (such as Save Styles Changes, in this case).

That’s it. The plugin will write your customizations into the theme’s theme.json file. If you open theme.json after saving, you’ll see your block styles reflected in the styles.blocks section.

What it looks like in theme.json

Let’s say you styled the Button block with a custom border radius and added some Additional CSS for hover styles. After saving with Create Block Theme, your theme.json might look something like this:

JSON
{
  "$schema": "https://schemas.wp.org/trunk/theme.json",
  "version": 3,
  "styles": {
    "blocks": {
      "core/button": {
        "border": {
          "radius": "4px"
        },
        "css": "transition: background-color 300ms ease-out;\n\n&:hover {\n  background-color: var(--wp--preset--color--secondary);\n}"
      }
    }
  }
}

The standard block properties (like border.radius) get saved as structured JSON, while the Additional CSS gets saved in the css property as a string. WordPress knows how to process both and generate the correct CSS output.

And for the List block example with the descendant selector:

JSON
{
  "styles": {
    "blocks": {
      "core/list": {
        "css": "& ul > li:first-child {\n  margin-block: 0;\n}"
      }
    }
  }
}

Hover and focus styles without Additional CSS

It’s worth mentioning that for links and buttons as elements (not the Button block specifically), theme.json has built-in support for pseudo-class styles without needing to use the css property at all. You can define :hover, :focus, :active, :visited, and (as of WordPress 6.8) :focus-visible states directly in the structured JSON.

Here’s an example that sets hover styles for all links across the site:

JSON
{
  "version": 3,
  "styles": {
    "elements": {
      "link": {
        "color": {
          "text": "var(--wp--preset--color--primary)"
        },
        "typography": {
          "textDecoration": "underline"
        },
        ":hover": {
          "color": {
            "text": "var(--wp--preset--color--contrast)"
          },
          "typography": {
            "textDecoration": "none"
          }
        }
      }
    }
  }
}

And you can scope these to specific blocks too. For example, adding hover styles only to links inside the Navigation block:

JSON
{
  "version": 3,
  "styles": {
    "blocks": {
      "core/navigation": {
        "elements": {
          "link": {
            "typography": {
              "textDecoration": "none"
            },
            ":hover": {
              "typography": {
                "textDecoration": "underline"
              }
            }
          }
        }
      }
    }
  }
}

This is the preferred approach when the structured JSON supports what you need. Reserve the css property for things that the UI and structured JSON can’t handle (like transitions, transforms, descendant selectors, and other CSS properties that theme.json doesn’t have dedicated support for).

Choosing the right approach

So when should you use each option? Here’s a quick rundown:

Use the Site Editor style controls for anything the UI supports natively: colors, typography, spacing, borders, shadows. This is the easiest path and keeps everything manageable through the visual interface.

Use Additional CSS (the css property) when you need CSS properties that aren’t available in the UI, like transitions, transforms, custom pseudo-class styles for blocks, or descendant element targeting. It’s great for small, targeted additions.

Use a separate stylesheet when you need to use any at-rules like @media, @supports, @container, @keyframes, etc. or if you have a large amount of custom CSS that would be unwieldy as a single-line JSON string.

The beauty of this system is that the Site Editor, theme.json, and Create Block Theme all work together. You can start visually, save to code, and then fine-tune in your editor. Or you can write everything in theme.json directly if that’s more your speed. Either way, the styles integrate into the WordPress cascade correctly, and users can still override them through the Site Editor if they need to.

Happy coding!



Leave a Reply

Your email address will not be published. Required fields are marked *