Extensibility is one of WordPress features that I love the most. From custom filters to actions, now they are applying the same thing with the new Gutenberg Editor.
It’s pretty great but aside from the WordPress handbook, there are only few tutorials available for Gutenberg development as of the moment. This is the main reason I’ve decided to pitch in and help out with creating tutorials starting from custom attributes and controls. These tutorials are the ones I’ve learned by actively participating on Gutenberg development on Github. I also used these methods on CoBlocks and EditorsKit plugins.
Let’s dig in. 😎
Adding Custom Attributes to Core Gutenberg Blocks
First, let’s add our custom attributes. In this tutorial, we will be using visibleOnMobile
custom attributes to add custom CSS mobile-hidden
class when it’s set to false.
By using blocks.registerBlockType
filter we can extend each block setting, which includes the attributes.
Here’s how you can easily add our custom attribute. 👇
/** | |
* WordPress Dependencies | |
*/ | |
const { addFilter } = wp.hooks; | |
/** | |
* Add custom attribute for mobile visibility. | |
* | |
* @param {Object} settings Settings for the block. | |
* | |
* @return {Object} settings Modified settings. | |
*/ | |
function addAttributes( settings ) { | |
//check if object exists for old Gutenberg version compatibility | |
if( typeof settings.attributes !== 'undefined' ){ | |
settings.attributes = Object.assign( settings.attributes, { | |
visibleOnMobile:{ | |
type: 'boolean', | |
default: true, | |
} | |
}); | |
} | |
return settings; | |
} | |
addFilter( | |
'blocks.registerBlockType', | |
'editorskit/custom-attributes', | |
addAttributes | |
); |
Adding Custom Attributes to Core Gutenberg Blocks
Tweet
Create Custom Controls on Advanced Block Panel
Now that we have registered our custom attributes, we need custom control to handle/change the value. I’ll be using ToggleControl component to easily switch our control on or off.

Using editor.BlockEdit
filter, we can modify block’s edit component. It receives the original block via BlockEdit
component and returns the new component. Then InspectorAdvancedControls component will help us target the Advanced Block Panel. It’s easier to show than tell. Check my codes below.
/** | |
* WordPress Dependencies | |
*/ | |
const { __ } = wp.i18n; | |
const { addFilter } = wp.hooks; | |
const { Fragment } = wp.element; | |
const { InspectorAdvancedControls } = wp.editor; | |
const { createHigherOrderComponent } = wp.compose; | |
const { ToggleControl } = wp.components; | |
/** | |
* Add mobile visibility controls on Advanced Block Panel. | |
* | |
* @param {function} BlockEdit Block edit component. | |
* | |
* @return {function} BlockEdit Modified block edit component. | |
*/ | |
const withAdvancedControls = createHigherOrderComponent( ( BlockEdit ) => { | |
return ( props ) => { | |
const { | |
attributes, | |
setAttributes, | |
isSelected, | |
} = props; | |
const { | |
visibleOnMobile, | |
} = attributes; | |
return ( | |
<Fragment> | |
<BlockEdit {…props} /> | |
{ isSelected && | |
<InspectorAdvancedControls> | |
<ToggleControl | |
label={ __( 'Mobile Devices Visibity' ) } | |
checked={ !! visibleOnMobile } | |
onChange={ () => setAttributes( { visibleOnMobile: ! visibleOnMobile } ) } | |
help={ !! visibleOnMobile ? __( 'Showing on mobile devices.' ) : __( 'Hidden on mobile devices.' ) } | |
/> | |
</InspectorAdvancedControls> | |
} | |
</Fragment> | |
); | |
}; | |
}, 'withAdvancedControls'); | |
addFilter( | |
'editor.BlockEdit', | |
'editorskit/custom-advanced-control', | |
withAdvancedControls | |
); |
Apply Custom Element Class to Gutenberg Blocks
Almost done! All I need to do now is apply our mobile-hidden
to the block. I just need to make sure that it will only be added when toggle is off.
blocks.getSaveContent.extraProps
filter applies to all blocks returning the element in the save()
function. This filter has extraProps
attribute that we can use to add custom classNames.
/** | |
* External Dependencies | |
*/ | |
import classnames from 'classnames'; | |
/** | |
* Add custom element class in save element. | |
* | |
* @param {Object} extraProps Block element. | |
* @param {Object} blockType Blocks object. | |
* @param {Object} attributes Blocks attributes. | |
* | |
* @return {Object} extraProps Modified block element. | |
*/ | |
function applyExtraClass( extraProps, blockType, attributes ) { | |
const { visibleOnMobile } = attributes; | |
//check if attribute exists for old Gutenberg version compatibility | |
//add class only when visibleOnMobile = false | |
if ( typeof visibleOnMobile !== 'undefined' && !visibleOnMobile ) { | |
extraProps.className = classnames( extraProps.className, 'mobile-hidden' ); | |
} | |
return extraProps; | |
} | |
addFilter( | |
'blocks.getSaveContent.extraProps', | |
'editorskit/applyExtraClass', | |
applyExtraClass | |
); |
That’s it! I made sure that it’s pretty easy to follow — I hope I achieved that. Now you can just add .mobile-hidden{ display: none }
on your frontend css.
Below is the full code with dependencies and filters altogether. I’ve also added allowedBlocks
variable so you can check how to apply the custom attributes and control to specific blocks only.
/** | |
* External Dependencies | |
*/ | |
import classnames from 'classnames'; | |
/** | |
* WordPress Dependencies | |
*/ | |
const { __ } = wp.i18n; | |
const { addFilter } = wp.hooks; | |
const { Fragment } = wp.element; | |
const { InspectorAdvancedControls } = wp.editor; | |
const { createHigherOrderComponent } = wp.compose; | |
const { ToggleControl } = wp.components; | |
//restrict to specific block names | |
const allowedBlocks = [ 'core/paragraph', 'core/heading' ]; | |
/** | |
* Add custom attribute for mobile visibility. | |
* | |
* @param {Object} settings Settings for the block. | |
* | |
* @return {Object} settings Modified settings. | |
*/ | |
function addAttributes( settings ) { | |
//check if object exists for old Gutenberg version compatibility | |
//add allowedBlocks restriction | |
if( typeof settings.attributes !== 'undefined' && allowedBlocks.includes( settings.name ) ){ | |
settings.attributes = Object.assign( settings.attributes, { | |
visibleOnMobile:{ | |
type: 'boolean', | |
default: true, | |
} | |
}); | |
} | |
return settings; | |
} | |
/** | |
* Add mobile visibility controls on Advanced Block Panel. | |
* | |
* @param {function} BlockEdit Block edit component. | |
* | |
* @return {function} BlockEdit Modified block edit component. | |
*/ | |
const withAdvancedControls = createHigherOrderComponent( ( BlockEdit ) => { | |
return ( props ) => { | |
const { | |
name, | |
attributes, | |
setAttributes, | |
isSelected, | |
} = props; | |
const { | |
visibleOnMobile, | |
} = attributes; | |
return ( | |
<Fragment> | |
<BlockEdit {…props} /> | |
//add allowedBlocks restriction | |
{ isSelected && allowedBlocks.includes( name ) && | |
<InspectorAdvancedControls> | |
<ToggleControl | |
label={ __( 'Mobile Devices Visibity' ) } | |
checked={ !! visibleOnMobile } | |
onChange={ () => setAttributes( { visibleOnMobile: ! visibleOnMobile } ) } | |
help={ !! visibleOnMobile ? __( 'Showing on mobile devices.' ) : __( 'Hidden on mobile devices.' ) } | |
/> | |
</InspectorAdvancedControls> | |
} | |
</Fragment> | |
); | |
}; | |
}, 'withAdvancedControls'); | |
/** | |
* Add custom element class in save element. | |
* | |
* @param {Object} extraProps Block element. | |
* @param {Object} blockType Blocks object. | |
* @param {Object} attributes Blocks attributes. | |
* | |
* @return {Object} extraProps Modified block element. | |
*/ | |
function applyExtraClass( extraProps, blockType, attributes ) { | |
const { visibleOnMobile } = attributes; | |
//check if attribute exists for old Gutenberg version compatibility | |
//add class only when visibleOnMobile = false | |
//add allowedBlocks restriction | |
if ( typeof visibleOnMobile !== 'undefined' && !visibleOnMobile && allowedBlocks.includes( blockType.name ) ) { | |
extraProps.className = classnames( extraProps.className, 'mobile-hidden' ); | |
} | |
return extraProps; | |
} | |
//add filters | |
addFilter( | |
'blocks.registerBlockType', | |
'editorskit/custom-attributes', | |
addAttributes | |
); | |
addFilter( | |
'editor.BlockEdit', | |
'editorskit/custom-advanced-control', | |
withAdvancedControls | |
); | |
addFilter( | |
'blocks.getSaveContent.extraProps', | |
'editorskit/applyExtraClass', | |
applyExtraClass | |
); |
Closing
As you can see, this will open up a lot of possibilities to extend existing Gutenberg blocks. I highly suggest you explore the Gutenberg Handbook for more filters available. I urge you to subscribe to my newsletter too to get notified for new tutorials and news. With that being said, please share the love and do not hesitate to say hi on the comment section.
Leave a Reply