Theme.json elements

In this lesson

Estimated reading time: 4 minutes

Last updated

What are theme.json elements?

Sometimes you want to style a part of a complex block, and you want more control than the block styles offer. Let’s take these examples:

  • When you style the heading block using styles.blocks.heading, the styles are applied to all heading blocks, but not to other type of headings like the site title or post title.
  • If you style the button block using styles.blocks.button, WordPress does not apply the styles to custom HTML buttons like submit buttons.

This is problematic because to create a consistent site design, you would have to style the extra headings and buttons separately. The theme.json elements category solves this by styling elements on the website and inside blocks.

It is important to know that theme.json elements are not strictly HTML elements. WordPress only supports a few selected elements, and applies some styles to a CSS class rather than the HTML tag itself. Block developers can add these custom class names to their blocks to ensure that they can be styled.

Which elements can I use with theme.json?

ElementCSS selectorSupported by
linkaWordPress 6.0
h1 to h6 Individual h1, h2, h3, h4, h5, h6WordPress 6.0
headingAll headings at once: h1, h2, h3, h4, h5, h6WordPress 6.1
button.wp-element-button and .wp-block-button__linkWordPress 6.1
caption.wp-element-caption,
.wp-block-audio figcaption,
.wp-block-embed figcaption,

.wp-block-gallery figcaption,
.wp-block-image figcaption,
.wp-block-table figcaption,

.wp-block-video figcaption
WordPress 6.1
citeciteWordPress 6.1
form elementsPlanning stages
pPlanning stages

Examples

Elements are used in the styles section of theme.json and in styles.blocks.blockname.

Headings

Here is how you would add a default font weight to all headings, set some sizes, and add a font family to all H2 headings, regardless of if they are a heading block or not. The last part of the code example applies a style to the H3 heading inside the post comments form:

{
	"version": 3,
	"styles": {
		"elements": {
			"heading": {
				"typography": {
					"fontWeight": "700"
				}
			},
			"h1": {
				"typography": {
					"fontSize": "var(--wp--preset--font-size--huge)"
				}
			},
			"h2": {
				"typography": {
					"fontSize": "var(--wp--preset--font-size--xxl)"
					"fontFamily": "var(--wp--preset--font-family--source-serif-pro)"
				}
			},
			"h3": {
				"typography": {
					"fontSize": "var(--wp--preset--font-size--extra-large)"
				}
			},
			"h4": {
				"typography": {
					"fontSize": "var(--wp--preset--font-size--large)"
				}
			}
		},
		"blocks": {
			"core/post-comments-form": {
				"elements": {
					"h3": {
						"typography": {
							"textTransform": "uppercase"
						}
					}
				}
			}
		}
	}
}

💡A mistake that theme developers often make is setting a default font size on styles.elements.headings. I want to clarify that setting a size on headings will apply the size to all heading levels. Set different sizes on different heading levels instead, by using styles.elements.h2, styles.elements.h3 etc.

A common scenario is to set all H1’s to a large size using styles.elements.H1 and then add exceptions to some blocks. But elements.heading and elements.hX does not work inside blocks that are headings. The following example would attempt to apply a font size to an H1 heading inside another heading, which does not work:

{
	"version": 3,
	"styles": {
		"elements": {
			"h1": {
				"typography": {
					"fontSize": "60px"
				}
			}
		},
		"blocks": {
			"core/query-title: {
				"elements": {
					"h1": {
						"typography": {
							"fontSize": "44px"
						}
					}
				}
			}
		}
	}
}

Instead, you can use custom CSS to add the exceptions:

{
	"version": 3,
	"styles": {
		"elements": {
			"h1": {
				"typography": {
					"fontSize": "60px"
				}
			}
		},
		"blocks": {
			"core/query-title: {
				"css": "&:is(h1){font-size: 44px;}"
			}
		}
	}
}

Read the lesson about how to add custom CSS using theme.json.

Another frequently asked question is why the site title block has the wrong styles: The site title can be changed to a paragraph, and then it is no longer affected by the heading styles. In this case you want to double check the level setting on the block.

Button

You can use styles.elements.button to add the same design to most buttons.
The exception is the navigation block buttons: If you want to style these buttons, you need to use custom CSS.

The styles from styles.elements.button are applied to the CSS class wp-element-button, and these blocks use the class: Button, file, search, and post comments form.

In the following theme.json example I am adding default styles for all buttons, and then reducing the font size for the button inside the file block:

{
	"version": 3,
	"styles": {
		"elements": {
			"button": {
				"typography": {
					"fontWeight": "700",
					"fontSize": "1.2rem"
				},
				"color": {
					"background": "#fafafa",
					"text": "#111111"
				},
				"border": {
					"radius": "0",
					"width": "2px",
					"style": "solid"
				}
			}
		},
		"blocks": {
			"core/file": {
				"elements": {
					"button": {
						"typography": {
							"fontSize": ".8rem"
						}
					}
				}
			}
		}
	}
}

The link is possibly the element that I see theme developers struggle most with.
You can use styles.elements.link to set a site wide style to all links. Please see this lesson to learn how to add hover and focus styles.

{
	"version": 3,
	"styles": {
		"elements": {
			"link": {
				"color": {
					"text": "#111111"
				}
			}
		}
	}
}

You can also use it to style links inside blocks: Like the post title which is a heading element with an <a> element inside if the link option is enabled:

{
	"version": 3,
	"styles": {
		"blocks": {
			"core/post-title": {
				"elements": {
					"link": {
						"color": {
							"text": "#111111"
						}
					}
				}
			}
		}
	}
}

A problem that theme developers can run into is that you can’t style blocks that are links this way. Most blocks that are links also have a wrapper (a div), but there are exceptions. This example with the read more block will have no effect:

{
	"version": 3,
	"styles": {
		"blocks": {
			"core/read-more": {
				"elements": {
					"link": {
						"color": {
							"text": "#111111"
						}
					}
				}
			}
		}
	}
}

To style this block you would use the text color:

{
	"version": 3,
	"styles": {
		"blocks": {
			"core/read-more": {
				"color": {
					"text": "red"
				}
			},
		}
	}
}

Caption

You can use styles.elements.caption to style the fig caption inside the figure element in the following blocks: Galleries, images, table, video, audio, and embeds.

{
	"version": 3,
	"styles": {
		"elements": {
			"caption": {
				"color": {
					"text": "#111111"
				},
				"typography": {
					"fontSize": "0.8rem",
					"lineHeight": ".7",
					"textTransform": "uppercase"
				}
			}
		}
	}
}

Cite

With styles.elements.cite you can add default styles to the citation in the quote block:

{
	"version": 3,
	"styles": {
		"elements": {
			"cite": {
				"color": {
					"text": "#333"
				},
				"typography": {
					"fontSize": "0.8rem",
					"lineHeight": ".7"
				}
			}
		}
	}	
}

Resources