Instead of having one big chunk of content, as it was until Gutenberg had been introduced in WordPress 5.0, the web page is now segmented into smaller parts, called blocks. The editor provides a wide variety of blocks that you can use across your pages and posts, but since this is WordPress, there’s always room for more custom functionality.

In this tutorial, you will learn how to create a custom block for displaying different types of notices. It will look like this in the editor:

PHP file

We will create a custom notice block in the form of a plugin, by making a new folder (‘o4t-notice-block’ for example)  in the ‘wp-content/plugins’ directory with an ‘o4t-notice-block.php’ file in it (can be given a more relevant name).

<?php
/**
 * Plugin Name: Open4Tech Custom Notice Block
 * Author:  Open4Tech
 * Version: 1.0.0
 */
 
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
        	exit;
}
 
// Load assets for wp-admin when editor is active
function o4t_notice_block_admin() {
   wp_enqueue_script(
      'o4t-notice-block-editor',
      plugins_url( 'block.js', __FILE__ ),
      array( 'wp-blocks', 'wp-element' )
   );
 
   wp_enqueue_style(
      'o4t-notice-block-editor',
      plugins_url( 'block.css', __FILE__ ),
      array()
   );
}
 
add_action( 'enqueue_block_editor_assets', 'o4t_notice_block_admin' );
 
// Load assets for frontend
function o4t_notice_block_frontend() {
 
   wp_enqueue_style(
      'o4t-notice-block-editor',
      plugins_url( 'block.css', __FILE__ ),
      array()
   );
}
 
add_action( 'wp_enqueue_scripts', 'o4t_notice_block_frontend' );

The plugin is initialised by loading the necessary JS and CSS files (block.js and block.css). The block script ‘block.js’ (which doesn’t exist yet) is enqueued and has two script dependencies included – ‘wp-blocks’ and ‘wp-editor’. The first one handles block registration among other functionality, whereas ‘wp-editor’ includes several basic components you might need, such as Rich Text. It is followed by the ‘wp_enqueue_style’ function which registers the stylesheet ‘block.css’.

Since the main JavaScript for creating blocks is only needed in the admin editor we’ll use ‘enqueue_block_editor_assets’ to include it. Then we enqueue the stylesheet for the frontend by using the same ‘block.css’ file for the sake of simplicity. You can use a different file if you wish. The ‘wp_enqueue_scripts’ hook is used when enqueuing scripts and styles that are meant to appear on the front end.

CSS file

The style.css file contains the formatting for the different attributes (described in the JS file below) included in the block:

div.notice-box h4 {
   font-size: 18px;
   margin:0 0 10px 0;
}
 
div.notice-box p {
   font-size: 16px;
   line-height: 24px;
   margin:0;
}

div.notice-box {
    padding: 15px;
    background-color: #fafafa;
    border-left: 6px solid #7f7f84;
    margin-bottom: 10px;
    -webkit-box-shadow: 0 5px 8px -6px rgba(0,0,0,.2);
       -moz-box-shadow: 0 5px 8px -6px rgba(0,0,0,.2);
            box-shadow: 0 5px 8px -6px rgba(0,0,0,.2);
	padding: 35px;
    font-size: large;
}


div.notice-box.notice-success {
    border-color: #80D651;
}

div.notice-box.notice-default {
    border-color: #45ABCD;
}

div.notice-box.notice-warning {
    border-color: #FEAF20;
}

div.notice-box.notice-error {
    border-color: #d73814;
}

JS file

Next, we will create a file called block.js in the custom plugin folder, which will hold the entire logic of the custom block type for the admin-side and frontend. It’s important to note that most components of Gutenberg blocks are written in JavaScript.

var el = wp.element.createElement;
 
wp.blocks.registerBlockType('o4t/notice-block', {
 
   title: 'Notice', // The display title for your block
 
   icon: 'megaphone', // Toolbar icon can be either using WP Dashicons or custom SVG
 
   category: 'common', // Under which category the block would appear
 
   attributes: { // The data this block will be storing
 
      type: { type: 'string', default: 'default' }, // Notice box type for loading the appropriate CSS class. Default class is 'default'.
 
      title: { type: 'string' }, // Notice box title in h4 tag
 
      content: { type: 'array', source: 'children', selector: 'p' } /// Notice box content in p tag
 
   },
 
  edit: function(props) {
   // How our block renders in the editor in edit mode
 
   function updateTitle( event ) {
      props.setAttributes( { title: event.target.value } );
   }
 
   function updateContent( newdata ) {
      props.setAttributes( { content: newdata } );
   }
 
   function updateType( event ) {
      props.setAttributes( { type: event.target.value } );
   }
 
   return el( 'div',
      {
         className: 'notice-box notice-' + props.attributes.type
      },
      el(
         'select',
         {
            onChange: updateType,
            value: props.attributes.type,
         },
         el("option", {value: "default" }, "Default"),
         el("option", {value: "success" }, "Success"),
         el("option", {value: "warning" }, "Warning"),
         el("option", {value: "error" }, "Error")
      ),
      el(
         'input',
         {
            type: 'text',
            placeholder: 'Enter title here...',
            value: props.attributes.title,
            onChange: updateTitle,
            style: { width: '100%' }
         }
      ),
      el(
         wp.editor.RichText,
         {
            tagName: 'p',
            onChange: updateContent,
            value: props.attributes.content,
            placeholder: 'Enter description here...'
         }
      )
   ); // End return
 
},  // End edit()
 
save: function(props) {
   // How our block renders on the frontend
 
   return el( 'div',
      {
         className: 'notice-box notice-' + props.attributes.type
      },
      el(
         'h4',
         null,
         props.attributes.title
      ),
      el( wp.editor.RichText.Content, {
         tagName: 'p',
         value: props.attributes.content
      })
 
   ); // End return
 
} // End save()
 
});
 

We register a new block type with the registerBlockType function. The name for a block must be unique and has to be structured as ‘namespace/block-name’, where the namespace is the name of your plugin or theme. The ‘title’ and ‘category’ properties are mandatory for the successful registration, while the rest are optional.

In our code, we create a block named ‘Notice’, with a ‘megaphone’ dashicon, listed under ‘common’ category. The core provided categories are: common, formatting, layout, widgets and embed. But also a custom block categories are supported.

The attributes specified in our block are ‘type’, ‘title’ and ‘content’.

Then, we create a function where we will edit and/or update them. The ‘title’ and ‘content’ in our code are just updated with the new data, while there are given four options for the ‘type’ which change the class name and respectively formatting, which is written in the ‘style.css’ file.

Lastly, the ‘save’ function describes how our block renders in the front end. It will return the ‘title’ as h4 heading and ‘content’ as a paragraph in different coloured boxes depending on the notice type and whether it is for default notice, success, warning or error.

This is the output generated by the notice block in the frontend:

Creating custom blocks gives flexibility for content customisation. You can make any piece of content imaginable and add it to a blog post or page through the block-based editor.

Was this article helpful?