Creating native gutenberg dynamic blocks using the block.json schema

Creating native Gutenberg dynamic blocks as of WordPress 5.8 is less laborious and customizable using the block.json schema. Primarily, this file is built to contain all the necessary metadata for a block, such as its name, category, and attributes. It also specifies the files that make up the block, including the JavaScript and CSS that define its behavior and appearance.

The file opens up the oppportunity for one to use of the native features available in WordPress Editor like typography, color schemes as well as include the experimental features if you use the Gutenberg plugin for the latest features.

How does creating custom dynamic blocks look like in WordPress?

If you want to see this in action, check out the video tutorial embeded below or click this link. The tutorial walks one through the process of Creating native gutenberg dynamic blocks using the block.json schema and file from scratch. It will give you a hands-on understanding of how the block.json file fits into the block development workflow, and how you can use it to create your own custom blocks for WordPress. In particular, the tutorial demonstrates how to modify the dynamic “ClassName” and “Alignment” properties with visuals in the file to offer a more seamless development experience.

In this blog article, we will delve deeper into the possibilities of the block.json file. Examining its structure and contents, as well as its place in the overall block development process. By the end of this article, you should have a clear understanding of how to use the block.json file to create custom blocks for the WordPress Gutenberg editor. I encourage you to watch the 10 min video above. With practice, you can use it to create a wide range of custom blocks or extend the core blocks to build better WordPress sites.

WordPress block.json file structure

I have included an example of the various options that can be extended in the block.json file as of December 2022/January 2023. To see all the available options visit – https://schemas.wp.org/trunk/block.json

I have made a collections of the core blocks to create the sample below. Feel free to copy any parts of the JSON object and incorporate them into your own block to see the difference.

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 2,
	"name": "namepsace/nameOfBlock",
	"title": "Name Of Block",
	"category": "widgets",
	"description": "Description of the Block.",
        "keywords": [ "music", "sound", "podcast", "recording" ],
        "usesContext": [ "postType", "postId", "commentId" ],
	"textdomain": "default",
	"attributes": {
		"nameOfAttribute": {
			"type": "boolean",
			"default": false
		},
		"nameOfAttribute1": {
			"type": "string",
			"default": "monthly"
		}
	},
	"supports": {
		"html": false,
		"anchor": true,
		"align": true,
		"alignWide": false,
		"customClassName": false,
		"inserter": false,
		"spacing": {
			"margin": true,
			"padding": true, // [ "horizontal", "vertical" ],
			"__experimentalSkipSerialization": true,
			"__experimentalDefaultControls": {
				"padding": true
			}
		},
                "color": {
			"text": false,
			"background": false,
			"__experimentalDuotone": "img"
		},
		"typography": {
			"fontSize": true,
			"lineHeight": true,
			"__experimentalFontFamily": true,
			"__experimentalFontWeight": true,
			"__experimentalFontStyle": true,
			"__experimentalTextTransform": true,
			"__experimentalTextDecoration": true,
			"__experimentalLetterSpacing": true,
			"__experimentalDefaultControls": {
				"fontSize": true
			}
		}
	},
	"reusable": false,
	"__experimentalBorder": {
		"radius": true,
		"__experimentalSkipSerialization": true,
		"__experimentalDefaultControls": {
			"radius": true
		}
	},
	"__experimentalSelector": ".wp-block-button .wp-block-button__link",
	"editorStyle": "wp-block-archives-editor",
    "styles": [
		{ "name": "fill", "label": "Fill", "isDefault": true },
		{ "name": "outline", "label": "Outline" }
	],
	"__experimentalLayout": {
		"allowSwitching": false,
		"allowInheriting": false,
		"default": {
			"type": "flex"
		}
	},
	"style": "wp-block-audio"
}

However, you can see more options from the different core blocks via https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src.

By comparing the block you are planning to build with a similar core block feature, you can create a more native user experience and reduce your development time in creating custom components. This will also reduce the time you take in maintenance of the developed custom blocks.

Using Theme.json

Similarily, when creating a new block theme, the same experience process has been passed on to the developing custom themes.

Please note that the example below highlights the possibilities in the theme and not in the block creating. However, the theme.json file can override default behaviour and add features to the existing blocks

To see all the available options visit – https://schemas.wp.org/trunk/theme.json

See an example below:

{
  "$schema": "https://schemas.wp.org/trunk/theme.json",
  "version": 2,
  "customTemplates": [
    {
      "name": "blank",
      "postTypes": [
        "page",
        "post"
      ],
      "title": "Blank"
    },
    {
      "name": "blog-alternative",
      "postTypes": [
        "page"
      ],
      "title": "Blog (Alternative)"
    },
    {
      "name": "404",
      "postTypes": [
        "page"
      ],
      "title": "404"
    }
  ],
  "settings": {
    "appearanceTools": true,
    "color": {
      "palette": [
        {
          "color": "#ffffff",
          "name": "Base",
          "slug": "base"
        },
        {
          "color": "#000000",
          "name": "Contrast",
          "slug": "contrast"
        },
        {
          "color": "#9DFF20",
          "name": "Primary",
          "slug": "primary"
        },
        {
          "color": "#345C00",
          "name": "Secondary",
          "slug": "secondary"
        },
        {
          "color": "#F6F6F6",
          "name": "Tertiary",
          "slug": "tertiary"
        }
      ]
    },
    "layout": {
      "contentSize": "650px",
      "wideSize": "1200px"
    },
    "spacing": {
      "spacingScale": {
        "steps": 0
      },
      "spacingSizes": [
        {
          "size": "clamp(1.5rem, 5vw, 2rem)",
          "slug": "30",
          "name": "1"
        },
        {
          "size": "clamp(1.8rem, 1.8rem + ((1vw - 0.48rem) * 2.885), 3rem)",
          "slug": "40",
          "name": "2"
        },
        {
          "size": "clamp(2.5rem, 8vw, 4.5rem)",
          "slug": "50",
          "name": "3"
        },
        {
          "size": "clamp(3.75rem, 10vw, 7rem)",
          "slug": "60",
          "name": "4"
        },
        {
          "size": "clamp(5rem, 5.25rem + ((1vw - 0.48rem) * 9.096), 8rem)",
          "slug": "70",
          "name": "5"
        },
        {
          "size": "clamp(7rem, 14vw, 11rem)",
          "slug": "80",
          "name": "6"
        }
      ],
      "units": [
        "%",
        "px",
        "em",
        "rem",
        "vh",
        "vw"
      ]
    },
    "typography": {
      "dropCap": false,
      "fluid": true,
      "fontFamilies": [
        {
          "fontFace": [
            {
              "fontFamily": "DM Sans",
              "fontStretch": "normal",
              "fontStyle": "normal",
              "fontWeight": "400",
              "src": [
                "file:./assets/fonts/dm-sans/DMSans-Regular.woff2"
              ]
            },
            {
              "fontFamily": "DM Sans",
              "fontStretch": "normal",
              "fontStyle": "italic",
              "fontWeight": "400",
              "src": [
                "file:./assets/fonts/dm-sans/DMSans-Regular-Italic.woff2"
              ]
            },
            {
              "fontFamily": "DM Sans",
              "fontStretch": "normal",
              "fontStyle": "normal",
              "fontWeight": "700",
              "src": [
                "file:./assets/fonts/dm-sans/DMSans-Bold.woff2"
              ]
            },
            {
              "fontFamily": "DM Sans",
              "fontStretch": "normal",
              "fontStyle": "italic",
              "fontWeight": "700",
              "src": [
                "file:./assets/fonts/dm-sans/DMSans-Bold-Italic.woff2"
              ]
            }
          ],
          "fontFamily": "\"DM Sans\", sans-serif",
          "name": "DM Sans",
          "slug": "dm-sans"
        },
        {
          "fontFace": [
            {
              "fontDisplay": "block",
              "fontFamily": "IBM Plex Mono",
              "fontStretch": "normal",
              "fontStyle": "normal",
              "fontWeight": "300",
              "src": [
                "file:./assets/fonts/ibm-plex-mono/IBMPlexMono-Light.woff2"
              ]
            },
            {
              "fontDisplay": "block",
              "fontFamily": "IBM Plex Mono",
              "fontStretch": "normal",
              "fontStyle": "normal",
              "fontWeight": "400",
              "src": [
                "file:./assets/fonts/ibm-plex-mono/IBMPlexMono-Regular.woff2"
              ]
            },
            {
              "fontDisplay": "block",
              "fontFamily": "IBM Plex Mono",
              "fontStretch": "normal",
              "fontStyle": "italic",
              "fontWeight": "400",
              "src": [
                "file:./assets/fonts/ibm-plex-mono/IBMPlexMono-Italic.woff2"
              ]
            },
            {
              "fontDisplay": "block",
              "fontFamily": "IBM Plex Mono",
              "fontStretch": "normal",
              "fontStyle": "normal",
              "fontWeight": "700",
              "src": [
                "file:./assets/fonts/ibm-plex-mono/IBMPlexMono-Bold.woff2"
              ]
            }
          ],
          "fontFamily": "'IBM Plex Mono', monospace",
          "name": "IBM Plex Mono",
          "slug": "ibm-plex-mono"
        },
        {
          "fontFace": [
            {
              "fontFamily": "Inter",
              "fontStretch": "normal",
              "fontStyle": "normal",
              "fontWeight": "200 900",
              "src": [
                "file:./assets/fonts/inter/Inter-VariableFont_slnt,wght.ttf"
              ]
            }
          ],
          "fontFamily": "\"Inter\", sans-serif",
          "name": "Inter",
          "slug": "inter"
        },
        {
          "fontFamily": "-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,Oxygen-Sans,Ubuntu,Cantarell,\"Helvetica Neue\",sans-serif",
          "name": "System Font",
          "slug": "system-font"
        },
        {
          "fontFace": [
            {
              "fontFamily": "Source Serif Pro",
              "fontStretch": "normal",
              "fontStyle": "normal",
              "fontWeight": "200 900",
              "src": [
                "file:./assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2"
              ]
            },
            {
              "fontFamily": "Source Serif Pro",
              "fontStretch": "normal",
              "fontStyle": "italic",
              "fontWeight": "200 900",
              "src": [
                "file:./assets/fonts/source-serif-pro/SourceSerif4Variable-Italic.ttf.woff2"
              ]
            }
          ],
          "fontFamily": "\"Source Serif Pro\", serif",
          "name": "Source Serif Pro",
          "slug": "source-serif-pro"
        }
      ],
      "fontSizes": [
        {
          "fluid": {
            "min": "0.875rem",
            "max": "1rem"
          },
          "size": "1rem",
          "slug": "small"
        },
        {
          "fluid": {
            "min": "1rem",
            "max": "1.125rem"
          },
          "size": "1.125rem",
          "slug": "medium"
        },
        {
          "fluid": {
            "min": "1.75rem",
            "max": "1.875rem"
          },
          "size": "1.75rem",
          "slug": "large"
        },
        {
          "fluid": false,
          "size": "2.25rem",
          "slug": "x-large"
        },
        {
          "fluid": {
            "min": "4rem",
            "max": "10rem"
          },
          "size": "10rem",
          "slug": "xx-large"
        }
      ]
    },
    "useRootPaddingAwareAlignments": true
  },
  "styles": {
    "blocks": {
      "core/navigation": {
        "elements": {
          "link": {
            ":hover": {
              "typography": {
                "textDecoration": "underline"
              }
            },
            ":focus": {
              "typography": {
                "textDecoration": "underline dashed"
              }
            },
            ":active": {
              "typography": {
                "textDecoration": "none"
              }
            },
            "typography": {
              "textDecoration": "none"
            }
          }
        },
        "typography": {
          "fontSize": "var(--wp--preset--font-size--small)"
        }
      },
      "core/post-author": {
        "typography": {
          "fontSize": "var(--wp--preset--font-size--small)"
        }
      },
      "core/post-content": {
        "elements": {
          "link": {
            "color": {
              "text": "var(--wp--preset--color--secondary)"
            }
          }
        }
      },
      "core/post-excerpt": {
        "typography": {
          "fontSize": "var(--wp--preset--font-size--medium)"
        }
      },
      "core/post-date": {
        "typography": {
          "fontSize": "var(--wp--preset--font-size--small)",
          "fontWeight": "400"
        },
        "elements": {
          "link": {
            "typography": {
              "textDecoration": "none"
            },
            ":hover": {
              "typography": {
                "textDecoration": "underline"
              }
            }
          }
        }
      },
      "core/post-terms": {
        "typography": {
          "fontSize": "var(--wp--preset--font-size--small)"
        }
      },
      "core/post-title": {
        "spacing": {
          "margin": {
            "bottom": "1.25rem",
            "top": "1.25rem"
          }
        },
        "typography": {
          "fontWeight": "400"
        },
        "elements": {
          "link": {
            ":hover": {
              "typography": {
                "textDecoration": "underline"
              }
            },
            ":focus": {
              "typography": {
                "textDecoration": "underline dashed"
              }
            },
            ":active": {
              "color": {
                "text": "var(--wp--preset--color--secondary)"
              },
              "typography": {
                "textDecoration": "none"
              }
            },
            "typography": {
              "textDecoration": "none"
            }
          }
        }
      },
      "core/comments-title": {
        "typography": {
          "fontSize": "var(--wp--preset--font-size--large)"
        },
        "spacing": {
          "margin": {
            "bottom": "var(--wp--preset--spacing--40)"
          }
        }
      },
      "core/comment-author-name": {
        "elements": {
          "link": {
            ":hover": {
              "typography": {
                "textDecoration": "underline"
              }
            },
            ":focus": {
              "typography": {
                "textDecoration": "underline dashed"
              }
            },
            ":active": {
              "color": {
                "text": "var(--wp--preset--color--secondary)"
              },
              "typography": {
                "textDecoration": "none"
              }
            },
            "typography": {
              "textDecoration": "none"
            }
          }
        }
      },
      "core/comment-date": {
        "typography": {
          "fontSize": "var(--wp--preset--font-size--small)"
        },
        "elements": {
          "link": {
            ":hover": {
              "typography": {
                "textDecoration": "underline"
              }
            },
            ":focus": {
              "typography": {
                "textDecoration": "underline dashed"
              }
            },
            ":active": {
              "color": {
                "text": "var(--wp--preset--color--secondary)"
              },
              "typography": {
                "textDecoration": "none"
              }
            },
            "typography": {
              "textDecoration": "none"
            }
          }
        }
      },
      "core/comment-edit-link": {
        "typography": {
          "fontSize": "var(--wp--preset--font-size--small)"
        }
      },
      "core/comment-reply-link": {
        "typography": {
          "fontSize": "var(--wp--preset--font-size--small)"
        }
      },
      "core/comments-pagination": {
        "spacing": {
          "margin": {
            "top": "var(--wp--preset--spacing--40)"
          }
        },
        "elements": {
          "link": {
            "typography": {
              "textDecoration": "none"
            }
          }
        }
      },
      "core/pullquote": {
        "border": {
          "style": "solid",
          "width": "1px 0"
        },
        "elements": {
          "cite": {
            "typography": {
              "fontSize": "var(--wp--preset--font-size--small)",
              "fontStyle": "normal",
              "textTransform": "none"
            }
          }
        },
        "typography": {
          "lineHeight": "1.3"
        },
        "spacing": {
          "margin": {
            "bottom": "var(--wp--preset--spacing--40) !important",
            "top": "var(--wp--preset--spacing--40) !important"
          }
        }
      },
      "core/query": {
        "elements": {
          "h2": {
            "typography": {
              "fontSize": "var(--wp--preset--font-size--x-large)"
            }
          }
        }
      },
      "core/query-pagination": {
        "typography": {
          "fontSize": "var(--wp--preset--font-size--small)",
          "fontWeight": "400"
        },
        "elements": {
          "link": {
            "typography": {
              "textDecoration": "none"
            },
            ":hover": {
              "typography": {
                "textDecoration": "underline"
              }
            }
          }
        }
      },
      "core/quote": {
        "border": {
          "width": "1px"
        },
        "elements": {
          "cite": {
            "typography": {
              "fontSize": "var(--wp--preset--font-size--small)",
              "fontStyle": "normal"
            }
          }
        },
        "spacing": {
          "padding": {
            "left": "var(--wp--preset--spacing--30)",
            "right": "var(--wp--preset--spacing--30)"
          }
        }
      },
      "core/site-title": {
        "elements": {
          "link": {
            ":hover": {
              "typography": {
                "textDecoration": "underline"
              }
            },
            ":focus": {
              "typography": {
                "textDecoration": "underline dashed"
              }
            },
            ":active": {
              "color": {
                "text": "var(--wp--preset--color--secondary)"
              },
              "typography": {
                "textDecoration": "none"
              }
            },
            "typography": {
              "textDecoration": "none"
            }
          }
        },
        "typography": {
          "fontSize": "var(--wp--preset--font-size--medium)",
          "fontWeight": "normal",
          "lineHeight": "1.4"
        }
      }
    },
    "color": {
      "background": "var(--wp--preset--color--base)",
      "text": "var(--wp--preset--color--contrast)"
    },
    "elements": {
      "button": {
        "border": {
          "radius": "0"
        },
        "color": {
          "background": "var(--wp--preset--color--primary)",
          "text": "var(--wp--preset--color--contrast)"
        },
        ":hover": {
          "color": {
            "background": "var(--wp--preset--color--contrast)",
            "text": "var(--wp--preset--color--base)"
          }
        },
        ":focus": {
          "color": {
            "background": "var(--wp--preset--color--contrast)",
            "text": "var(--wp--preset--color--base)"
          }
        },
        ":active": {
          "color": {
            "background": "var(--wp--preset--color--secondary)",
            "text": "var(--wp--preset--color--base)"
          }
        },
        ":visited": {
          "color": {
            "text": "var(--wp--preset--color--contrast)"
          }
        }
      },
      "h1": {
        "typography": {
          "fontSize": "3.625rem",
          "lineHeight": "1.2"
        }
      },
      "h2": {
        "typography": {
          "fontSize": "clamp(2.625rem, calc(2.625rem + ((1vw - 0.48rem) * 8.4135)), 3.25rem)",
          "lineHeight": "1.2"
        }
      },
      "h3": {
        "typography": {
          "fontSize": "var(--wp--preset--font-size--x-large)"
        }
      },
      "h4": {
        "typography": {
          "fontSize": "var(--wp--preset--font-size--large)"
        }
      },
      "h5": {
        "typography": {
          "fontSize": "var(--wp--preset--font-size--medium)",
          "fontWeight": "700",
          "textTransform": "uppercase"
        }
      },
      "h6": {
        "typography": {
          "fontSize": "var(--wp--preset--font-size--medium)",
          "textTransform": "uppercase"
        }
      },
      "heading": {
        "typography": {
          "fontWeight": "400",
          "lineHeight": "1.4"
        }
      },
      "link": {
        "color": {
          "text": "var(--wp--preset--color--contrast)"
        },
        ":hover": {
          "typography": {
            "textDecoration": "none"
          }
        },
        ":focus": {
          "typography": {
            "textDecoration": "underline dashed"
          }
        },
        ":active": {
          "color": {
            "text": "var(--wp--preset--color--secondary)"
          },
          "typography": {
            "textDecoration": "none"
          }
        },
        "typography": {
          "textDecoration": "underline"
        }
      }
    },
    "spacing": {
      "blockGap": "1.5rem",
      "padding": {
        "top": "var(--wp--preset--spacing--40)",
        "right": "var(--wp--preset--spacing--30)",
        "bottom": "var(--wp--preset--spacing--40)",
        "left": "var(--wp--preset--spacing--30)"
      }
    },
    "typography": {
      "fontFamily": "var(--wp--preset--font-family--system-font)",
      "fontSize": "var(--wp--preset--font-size--medium)",
      "lineHeight": "1.6"
    }
  },
  "templateParts": [
    {
      "area": "header",
      "name": "header",
      "title": "Header"
    },
    {
      "area": "footer",
      "name": "footer",
      "title": "Footer"
    },
    {
      "area": "uncategorized",
      "name": "comments",
      "title": "Comments"
    },
    {
      "area": "uncategorized",
      "name": "post-meta",
      "title": "Post Meta"
    }
  ]
}

You can visualize each component of a similar schema using the following link: https://jsonhero.io/j/0cjFNJnefgqE

For custom block developers, having this in mind with reduce the development time and technical debt in times to come. It enables for a unique experience for the users and WordPress continues to iterate over this with the goal to make full site editing possible.

Has this article been helpful? How can it be improved to make it more usable? Let me know in the comments below.


Comments

Leave a Reply

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