Block grammar, attributes, and supports

Level: ,

As I mentioned in the first lesson, What is full site editing? theme developers will use HTML templates instead of PHP files and HTML comments and block markup instead of PHP functions.

In this lesson, I will not discuss building custom blocks with JavaScript but rather the HTML code or the so-called block grammar you will use in the HTML files.

Estimated reading time: 4 minutes

Last updated

Block grammar basics

A basic block uses an HTML comment that WordPress parses and renders as HTML on the front:

<!--            /-->

All block comments start with a prefix and the block name: wp:blockname.

The comment can be a single line, self-closing, or wrapper for HTML content.
Let’s look at these two examples: The search and paragraph blocks.

<!-- wp:search /-->

<!-- wp:paragraph -->
<p>Welcome to the world of blocks.</p>
<!-- /wp:paragraph -->

We know that the search block outputs a form on the front. But the comment is self-closing because it doesn’t have any content.

The paragraph block prints the text content and uses the HTML comment as a wrapper. It tells us where the paragraph starts and where it ends.

Our third example, the columns block, has a comment wrapper and inner blocks based on divs:

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

How to find the block markup

So how do you know what block markup you need to use?
The easiest way to get the HTML code for a block is to add the block in the editor and copy the code. You can copy the code from the code editor mode (Ctrl+Shift+Alt+M) or the block toolbar:

The block toolbar has an option to copy the block markup under the ellipsis menu.

Using block metadata in markup

When you change block settings, WordPress stores the settings as a JSON object inside the block comment. As an example, I have added a custom background color to the columns block:

<!-- wp:columns {"style":{"color":{"background":"#88bbdd"}}} -->
<div class="wp-block-columns has-background" style="background-color:#88bbdd">
<!-- wp:column -->
<div class="wp-block-column"></div>
<!-- /wp:column -->

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

The block repeats the JSON data from the HTML comment as a CSS class and inline style:

class="wp-block-columns has-background"

If you pick a predefined color from the palette, the block uses a class name instead:

<!-- wp:columns {"backgroundColor":"pink"} -->
<div class="wp-block-columns has-pink-background-color has-background">
<!-- wp:column -->
<div class="wp-block-column"></div>
<!-- /wp:column -->

<!-- wp:column -->
<div class="wp-block-column"></div>
<!-- /wp:column --></div>
<!-- /wp:columns -->
class="wp-block-columns has-pink-background-color has-background"

This duplication is essential when you start customizing blocks in your HTML files.

The JSON data includes more than block attributes

Calling it block attributes is a simplification: When WordPress registers a block, it can add both attributes and block supports.


Attributes are often unique to the block. For example, the audio HTML element has built-in controls for autoplay and loop. The audio block registers autoplay and loop as block attributes.
Settings for the attributes are created in the block’s edit.js file using basic components like the toggle control:

	label={ __( 'Autoplay' ) }
	onChange={ toggleAttribute( 'autoplay' ) }
	checked={ autoplay }
	help={ getAutoplayHelp }
	label={ __( 'Loop' ) }
	onChange={ toggleAttribute( 'loop' ) }
	checked={ loop }

The controls are output with the block markup:

<!-- wp:audio {"id":821} -->
<figure class="wp-block-audio"><audio controls src="" autoplay loop></audio></figure>
<!-- /wp:audio -->

And if you wanted to remove these controls manually in your template markup, you would remove the keywords:

<!-- wp:audio {"id":821} -->
<figure class="wp-block-audio"><audio controls src=""></audio></figure>
<!-- /wp:audio -->


In comparison, block supports are settings that are reused by many blocks. The blocks can register if they want full or partial support and if the control should be visible by default in the editors.

To learn if a block supports a specific feature, you can use the block reference on this site.

Even if a block does not register support, there are ways to add default values to the block markup. The calendar block registers support for link color, text color, and background color but not for gradients (February 2023):

"color": {
	"link": true,
	"__experimentalSkipSerialization": [ "text", "background" ],
	"__experimentalDefaultControls": {
		"background": true,
		"text": true
	"__experimentalSelector": "table, th"

In your markup, you can still add gradients to the block in the following ways:

Using a predefined gradient with a class name

This example is the equivalent of adding the CSS classes in the “Additional CSS class(es)” field in the Advanced panel in the block settings sidebar. The user can remove the background in the editor by removing the class names from the input field. They can not change the color using the block’s color settings because the gradient takes precedence.

<!-- wp:calendar {"className":"has-pale-ocean-gradient-background has-background"} /-->

Using a custom gradient

Like the first example, this block markup works in the editor and front without any block validation errors. But since you are using inline styles instead of the class name, there is no way for the user to change the background color without editing the code or deleting the block.

<!-- wp:calendar {"style":{"color":{"gradient":"linear-gradient(135deg,rgb(74,224,241) 43%,rgb(0,255,21) 100%)"}}} /-->


There are two types of alignments, divided between supports and attributes:

  • Block alignments like wide and full width are registered as block supports
  • Text alignment is a block attribute

Blocks that do not have wide/full-width block alignments use “align” to align text. See this paragraph for an example:

<!-- wp:paragraph {"align":"center"} -->
<p class="has-text-align-center">Paragraph</p>
<!-- /wp:paragraph -->

Some blocks have both wide/full-width block alignments and text alignments.
These blocks use "textAlign" to align text and “align” to align the block:

<!-- wp:heading {"textAlign":"center","align":"full"} -->
<h2 class="alignfull has-text-align-center">Heading</h2>
<!-- /wp:heading --

When you align text, both textAlign and align is combined with the CSS class “has-text-align-{name-of-alignment}” on the HTML element.