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 that you will be using in the HTML files.

Estimated reading time: 6 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 and self-closing or a wrapper for actual HTML content.
Let’s look at these two examples: The search block and the paragraph block.

<!-- 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 -->
</div>
<!-- /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 this 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:

{"style":{"color":{"background":"#88bbdd"}}}
class="wp-block-columns has-background"
style="background-color:#88bbdd"

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 -->
{"backgroundColor":"pink"}
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

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 editor.js file using basic components like the toggle control:

<ToggleControl
	label={ __( 'Autoplay' ) }
	onChange={ toggleAttribute( 'autoplay' ) }
	checked={ autoplay }
	help={ getAutoplayHelp }
/>
<ToggleControl
	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="http://example.com/wp-content/uploads/2008/06/originaldixielandjazzbandwithalbernard-stlouisblues.mp3" 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="http://example.com/wp-content/uploads/2008/06/originaldixielandjazzbandwithalbernard-stlouisblues.mp3"></audio></figure>
<!-- /wp:audio -->

Supports

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

To learn if a block supports a specific feature or uses an attribute, you can go directly to the source and read the block.json files:

WordPress core source files, if you are not using Gutenberg
Gutenberg source files

Or you can use the block reference on this site. I try to keep it up to date with the latest Gutenberg version.

Let’s look at some more examples.
The paragraph block registers supports for link color, text color, and background color, but not for gradients (June 2022):

"supports": {
		"anchor": true,
		"className": false,
		"color": {
			"link": true,
			"__experimentalDefaultControls": {
				"background": true,
				"text": true
			}
		},
		... (truncated code)
	},

In your markup, you can still add gradients to the paragraph 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, but only 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:paragraph {"className":"has-pale-ocean-gradient-background has-background"} -->
<p class="has-pale-ocean-gradient-background has-background">paragraph</p>
<!-- /wp:paragraph -->

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:paragraph {"style":{"color":{"gradient":"linear-gradient(135deg,rgb(74,224,241) 43%,rgb(0,255,21) 100%)"}}} -->
<p class="wp-block-group has-background" style="background:linear-gradient(135deg,rgb(74,224,241) 43%,rgb(0,255,21) 100%)"paragraph</p>
<!-- /wp:paragraph -->

Adding a font family

The group block supports several typography settings but only displays the font size control (To access the font appearance and text transform tools, you first need to open the menu in the Typography panel).

"typography": {
	"fontSize": true,
	"lineHeight": true,
	"__experimentalFontStyle": true,
	"__experimentalFontWeight": true,
	"__experimentalLetterSpacing": true,
	"__experimentalTextTransform": true,
	"__experimentalDefaultControls": {
		"fontSize": true
	}
},

The block does not have support for the font family (June 2022). It is easy to believe that you could add a font family through markup the following way:

<!-- wp:group {"fontFamily":"source-serif-pro"} -->
<div class="wp-block-group has-source-serif-pro-font-family"><!-- wp:paragraph -->
<p>text</p>
<!-- /wp:paragraph --></div>
<!-- /wp:group -->

If you try to apply the fontFamily block support this way, the editor will remove it.
But because you have included the class names on the div, WordPress adds the className attribute in its place:

<!-- wp:group {"className":"has-source-serif-pro-font-family"} -->
<div class="wp-block-group has-source-serif-pro-font-family"><!-- wp:paragraph -->
<p>text</p>
<!-- /wp:paragraph --></div>
<!-- /wp:group -->

– And with the help of the classname, the blocks that you place inside the group uses the chosen font family.

Alignments

The two types of alignments are 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.