Skip to main content

WordPress Gutenberg and Block Editor CSS

The WordPress block editor (Gutenberg) generates specific HTML class names and uses theme.json for design tokens. This guide covers how to style Gutenberg blocks in your child theme and integrate your CSS design system with the block editor.

1. How Gutenberg HTML is Structured

Every Gutenberg block generates a wp-block-[name] class. The HTML output is predictable:

<!-- Paragraph -->
<p class="wp-block-paragraph">Content</p>

<!-- Heading -->
<h2 class="wp-block-heading">Title</h2>

<!-- Image -->
<figure class="wp-block-image size-large">
<img src="...">
</figure>

<!-- Columns -->
<div class="wp-block-columns">
<div class="wp-block-column">...</div>
</div>

<!-- Button -->
<div class="wp-block-buttons">
<div class="wp-block-button">
<a class="wp-block-button__link wp-element-button">Click Me</a>
</div>
</div>

<!-- Group -->
<div class="wp-block-group">
<div class="wp-block-group__inner-container">...</div>
</div>

<!-- Cover -->
<div class="wp-block-cover">
<div class="wp-block-cover__inner-container">...</div>
</div>

2. Essential Block CSS Overrides

/* ── Core Content Width ── */
.wp-block-post-content > * {
max-width: 72ch; /* Optimal reading width */
margin-left: auto;
margin-right: auto;
}

/* Full-width blocks break out of content width */
.wp-block-post-content > .alignfull {
max-width: 100%;
margin-left: calc(-1 * var(--wp--style--global--content-size));
margin-right: calc(-1 * var(--wp--style--global--content-size));
}

/* ── Headings ── */
.wp-block-heading,
.wp-block-post-title {
font-family: var(--font-heading);
line-height: 1.2;
color: var(--color-text);
}

/* ── Paragraphs ── */
.wp-block-paragraph {
color: var(--color-text);
line-height: 1.7;
}
.wp-block-paragraph.has-large-font-size {
font-size: var(--text-xl);
}

/* ── Buttons ── */
.wp-block-button__link,
.wp-element-button {
background: var(--color-primary) !important;
border-radius: var(--radius-full) !important;
padding: 0.75rem 2rem !important;
font-weight: 600 !important;
transition: background var(--ease);
}
.wp-block-button__link:hover, .wp-element-button:hover {
background: var(--color-primary-dark) !important;
}

/* ── Images ── */
.wp-block-image img {
border-radius: var(--radius-md);
max-width: 100%;
height: auto;
}
.wp-block-image.alignfull img { border-radius: 0; }

/* ── Columns ── */
.wp-block-columns { gap: 2rem; }
.wp-block-column { min-width: 0; } /* Prevent overflow */

/* ── Separator ── */
.wp-block-separator {
border-color: var(--color-border);
opacity: 1;
margin: var(--space-8) auto;
}

/* ── Quote ── */
.wp-block-quote {
border-left: 4px solid var(--color-primary);
padding-left: 1.5rem;
font-size: 1.125rem;
font-style: italic;
color: var(--color-text-muted);
}
.wp-block-quote cite { font-style: normal; font-size: 0.875rem; }

/* ── Code ── */
.wp-block-code,
.wp-block-preformatted {
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
font-family: var(--font-mono);
font-size: 0.875rem;
padding: 1.5rem;
overflow-x: auto;
}

3. theme.json — The Design Token Bridge

theme.json defines the block editor's color palette, font sizes, spacing scale and exposes them as CSS variables to both the editor (backend) and the frontend. This is the bridge between your CSS token system and Gutenberg.

Location: /wp-content/themes/your-child-theme/theme.json

{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 2,
"settings": {
"color": {
"defaultPalette": false,
"palette": [
{ "slug": "primary", "color": "#6c63ff", "name": "Primary" },
{ "slug": "surface", "color": "#1a1a1a", "name": "Surface" },
{ "slug": "text", "color": "#f0f0f0", "name": "Text" },
{ "slug": "muted", "color": "#888888", "name": "Muted" },
{ "slug": "danger", "color": "#e53e3e", "name": "Danger" },
{ "slug": "success", "color": "#38a169", "name": "Success" }
]
},
"typography": {
"defaultFontSizes": false,
"fontSizes": [
{ "slug": "sm", "size": "0.875rem", "name": "Small" },
{ "slug": "base", "size": "clamp(1rem, 0.9rem + 0.5vw, 1.125rem)", "name": "Base" },
{ "slug": "lg", "size": "clamp(1.25rem, 1rem + 1vw, 1.75rem)", "name": "Large" },
{ "slug": "xl", "size": "clamp(1.5rem, 1.2rem + 1.5vw, 2.5rem)", "name": "XL" },
{ "slug": "hero", "size": "clamp(2.5rem, 5vw + 1rem, 5rem)", "name": "Hero" }
]
},
"spacing": {
"spacingSizes": [
{ "slug": "sm", "size": "1rem", "name": "Small" },
{ "slug": "md", "size": "2rem", "name": "Medium" },
{ "slug": "lg", "size": "4rem", "name": "Large" },
{ "slug": "xl", "size": "6rem", "name": "XL" }
]
}
},
"styles": {
"color": {
"background": "#0f0f0f",
"text": "#f0f0f0"
},
"typography": {
"fontFamily": "var(--font-body, system-ui)",
"fontSize": "var(--text-base, 1rem)",
"lineHeight": "1.6"
}
}
}

CSS Variables Generated by theme.json

WordPress converts theme.json entries into CSS custom properties:

/* From theme.json colors */
--wp--preset--color--primary: #6c63ff;
--wp--preset--color--surface: #1a1a1a;
--wp--preset--color--text: #f0f0f0;

/* From theme.json font sizes */
--wp--preset--font-size--sm: 0.875rem;
--wp--preset--font-size--base: clamp(1rem, ...);

/* From theme.json spacing */
--wp--preset--spacing--sm: 1rem;
--wp--preset--spacing--md: 2rem;

4. Custom Block Styles

Register custom style variations for blocks using PHP:

// functions.php
function mytheme_register_block_styles() {
// Custom card style for the Group block
register_block_style('core/group', [
'name' => 'card',
'label' => 'Card',
]);

// Featured quote style
register_block_style('core/quote', [
'name' => 'featured',
'label' => 'Featured Quote',
]);

// Outline button variant
register_block_style('core/button', [
'name' => 'outline',
'label' => 'Outline',
]);
}
add_action('init', 'mytheme_register_block_styles');

Then style with the generated class:

/* Group block with 'card' style applied */
.wp-block-group.is-style-card {
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius-lg);
padding: var(--space-6);
box-shadow: var(--shadow-md);
}

/* Featured quote */
.wp-block-quote.is-style-featured {
border-left: none;
background: var(--color-surface);
padding: 2rem;
border-radius: var(--radius-md);
text-align: center;
}

/* Outline button */
.wp-block-button.is-style-outline .wp-block-button__link {
background: transparent !important;
border: 2px solid var(--color-primary) !important;
color: var(--color-primary) !important;
}

5. Editor-Only vs Frontend Styles

To apply styles only in the block editor (not on the frontend):

// functions.php
function mytheme_editor_styles() {
add_editor_style('assets/css/editor.css'); // Only loads in editor
}
add_action('after_setup_theme', 'mytheme_editor_styles');
/* editor.css — editor-only overrides */
.editor-styles-wrapper {
background: var(--color-bg);
color: var(--color-text);
font-family: var(--font-body);
padding: 2rem !important;
}
.editor-styles-wrapper h1,
.editor-styles-wrapper h2 {
font-family: var(--font-heading);
}