STEPS
If you’ve used Visual Composer in developing of themes probably you’ve thought at least one time to create your custom block.Well, this tutorial will explain how to do it, but before to start I strongly suggest you read the basic tutorial to integrate Visual Composer in your themeadvised
1. Where to include your code
As I wrote in other similar tutorials, the code position is a personal choice. Most tutorials on the net recommend to place any function in the functions.php file in the theme folder.
I believe instead that it’s better to create a separate file for the Visual Composer setup in which to place all features.
In this tutorial I’ll share my way to include an element on Visual Composer. I think it’s a really clean way.
So you have to create a folder in your theme’s root folder. I decided to create a
Inside
The file you just created is still not in WP so we’re going to require it.
If you followed the related tutorial that I reported on the heading you’ll know how to add actions to the hook
Add the following code in
In this tutorial I’ll share my way to include an element on Visual Composer. I think it’s a really clean way.
So you have to create a folder in your theme’s root folder. I decided to create a
vc-elements
folder in my theme’s root. Inside
vc-elements
folder you can create a php file that will contain your new element. I created for example my-first-custom-element.php
The file you just created is still not in WP so we’re going to require it.
If you followed the related tutorial that I reported on the heading you’ll know how to add actions to the hook
vc_before_init
, but let me show you the code once again. Add the following code in
function.php
in your theme. It’s called BEFORE the Visual Composer initialization:
// Before VC Init add_action( 'vc_before_init', 'vc_before_init_actions' ); function vc_before_init_actions() { //.. Code from other Tutorials ..// // Require new custom Element require_once( get_template_directory().'/vc-elements/my-first-custom-element.php' ); }
Code explanation
- row 02: I added an action to the
vc_before_init
VC hook, so my function will be called before VC init - row 09: I required the file we just created
my-first-custom-element.php
and to find its absolute path I usedget_template_directory()
Note: if you want to edit or customize a Visual Composer default block please follow the tutorial How-To: customize default elements in Visual Composer advised
2. Initialize your new Element
Before to show you the element code I have to say that there are many ways to build it, I will show you my way. I commonly create a php Class to extend the
My Class consists of 3 parts:
WPBakeryShortCode
Class so I can include all the code in the same place and it allows to do a clean work.My Class consists of 3 parts:
- Shortcode Init
- Shortcode Map (parameters)
- Shortcode HTML
/* Element Description: VC Info Box */ // Element Class class vcInfoBox extends WPBakeryShortCode { // Element Init function __construct() { add_action( 'init', array( $this, 'vc_infobox_mapping' ) ); add_shortcode( 'vc_infobox', array( $this, 'vc_infobox_html' ) ); } // Element Mapping public function vc_infobox_mapping() { //.. the Code is in the next steps ..// } // Element HTML public function vc_infobox_html( $atts ) { //.. the Code is in the next steps ..// } } // End Element Class // Element Class Init new vcInfoBox();
Code explanation
- row 02: I advise to put a description about the element you are developing
- row 06: I extended the
WPBakeryShortCode
class with new element classvcInfoBox
- row 09: I added a
__construct()
function to initialize the functions in the class - row 10: I added an action to initialize the element’s mapping function
vc_infobox_mapping()
(row: 15) - row 11: I used
add_shortcode()
function to create the new shortcode for the element. In the first parameter I passed the slug for the shortcodevc_infobox
and in the second parameter I passed an array to call the element’s HTML functionvc_infobox_html()
(row: 23) - row 15:
vc_infobox_mapping()
function (explained in the next steps) - row 23:
vc_infobox_html()
function (explained in the next steps) - row 32: After the end of the Class,so outside the class, you have to initialize it so Visual Composer will be able to include your element in the list
3. Mapping the Element
It’s time to use the famous
So we can edit our
vc_map()
function, that allows to add new elements inside Visual Composer and to assign them custom params/attributes. So we can edit our
vc_infobox_mapping()
function:
// Element Mapping public function vc_infobox_mapping() { // Stop all if VC is not enabled if ( !defined( 'WPB_VC_VERSION' ) ) { return; } // Map the block with vc_map() vc_map( array( 'name' => __('VC Infobox', 'text-domain'), 'base' => 'vc_infobox', 'description' => __('Another simple VC box', 'text-domain'), 'category' => __('My Custom Elements', 'text-domain'), 'icon' => get_template_directory_uri().'/assets/img/vc-icon.png', 'params' => array( array( 'type' => 'textfield', 'holder' => 'h3', 'class' => 'title-class', 'heading' => __( 'Title', 'text-domain' ), 'param_name' => 'title', 'value' => __( 'Default value', 'text-domain' ), 'description' => __( 'Box Title', 'text-domain' ), 'admin_label' => false, 'weight' => 0, 'group' => 'Custom Group', ), array( 'type' => 'textarea', 'holder' => 'div', 'class' => 'text-class', 'heading' => __( 'Text', 'text-domain' ), 'param_name' => 'text', 'value' => __( 'Default value', 'text-domain' ), 'description' => __( 'Box Text', 'text-domain' ), 'admin_label' => false, 'weight' => 0, 'group' => 'Custom Group', ) ) ) ); }
Code explanation
- row 05-07: If Visual Composer is not enabled the function stops, avoiding the Fatal Error.
- row 10: I called the function vc_map() passing an Array of options and params
- row 10: A human friendly name for the element. It will be displayed in the list of elements in VC.
- row 14: This must be extactly the shortcode slug you defined in previous step on the row 11.
- row 15: A human friendly description for the element. It will be displayed in the list of elements in VC.
- row 16: Using the
category
attribute is allowing you to create a custom tab for your personal elements in the VC list of elements. If you don’t add this attribute, your element will be placed in the “All” tab. - row 17: The
icon
attribute allows to add a custom icon for the element. I created and uploaded my icon in the img folder in my theme and I usedget_template_directory_uri()
function to reach it. - row 18:
params
attribute is the heart of the Mapping. You can pass here an array of arrays adding unlimited params to your custom element. - row 21: The field type. In our example it’s a simple textfield (input type text).
- row 22: HTML tag name where Visual Composer will store attribute value in Visual Composer edit mode. Default: hidden input.
- row 23: Class name that will be added to the “holder” HTML tag. Useful if you want to target some CSS rules to specific items in the backend edit interface.
- row 24: Human friendly title of your param. Will be visible in shortcode’s edit screen.
- row 25: Will be the “name” attribute for your field. Use only
_
for multiple words and try to add unique names because it will be used to save the data. - row 26: Default value
- row 27: Human friendly description of your param. Will be visible in shortcode’s edit screen.
- row 28: Show/Hide value of param in Visual Composer editor.
- row 29: Params with greater weight will be rendered first respect the other params.
- row 30: Use it to divide your params within groups/tabs (the position of the tab is influenced by the previous option).
- row 33-44: I added another param (a textarea to add some text). You can add any else arrays/params here.
4. Element HTML
We are finally ready to work on the frontend layout, so let’s edit our
vc_infobox_html()
function:
// Element HTML public function vc_infobox_html( $atts ) { // Params extraction extract( shortcode_atts( array( 'title' => '', 'text' => '', ), $atts ) ); // Fill $html var with data $html = ' <div class="vc-infobox-wrap"> <h2 class="vc-infobox-title">' . $title . '</h2> <div class="vc-infobox-text">' . $text . '</div> </div>'; return $html; }
Code explanation
- row 02: I start saying that we have to set a variable (
$atts
) in the function in order to contain our attribute values. - row 05: This function is extracting all the values from the DB and is putting them in some variables.
- row 08: I extract the
title
param. It must be exactly the same name you used in the params mapping (previous step, row 25). You can also pass a default value in case of empty value. I don’t need to add a default value so I leave it blank.
Note: the function will create a var$title
and the name is exactly the param name you passed. - row 09: I extract the
text
param. It must be exactly the same name you used in the params mapping (previous step, row 38). You can also pass a default value in case of empty value. I don’t need to add a default value so I leave it blank.
Note: the function will create a var$text
and the name is exactly the param name you passed. - row 11: I pass to the function the
$atts
variable where the data is saved (as described for the row 02) - row 16-23: I fill a
$html
variable with the HTML code adding also my 2 attributes$title
and$text
- row 25: I finally
return
the$html
variable rendering my custom element in frontend.
5. Result and Complete Code
This is our backend result:

And this is our frontend result:
If you need the complete code paste in your

And this is our frontend result:

If you need the complete code paste in your
function.php
file this function:
// Before VC Init add_action( 'vc_before_init', 'vc_before_init_actions' ); function vc_before_init_actions() { //.. Code from other Tutorials ..// // Require new custom Element require_once( get_template_directory().'/vc-elements/my-first-custom-element.php' ); }And paste in your
my-first-custom-element.php
file this class:
/* Element Description: VC Info Box */ // Element Class class vcInfoBox extends WPBakeryShortCode { // Element Init function __construct() { add_action( 'init', array( $this, 'vc_infobox_mapping' ) ); add_shortcode( 'vc_infobox', array( $this, 'vc_infobox_html' ) ); } // Element Mapping public function vc_infobox_mapping() { // Stop all if VC is not enabled if ( !defined( 'WPB_VC_VERSION' ) ) { return; } // Map the block with vc_map() vc_map( array( 'name' => __('VC Infobox', 'text-domain'), 'base' => 'vc_infobox', 'description' => __('Another simple VC box', 'text-domain'), 'category' => __('My Custom Elements', 'text-domain'), 'icon' => get_template_directory_uri().'/assets/img/vc-icon.png', 'params' => array( array( 'type' => 'textfield', 'holder' => 'h3', 'class' => 'title-class', 'heading' => __( 'Title', 'text-domain' ), 'param_name' => 'title', 'value' => __( 'Default value', 'text-domain' ), 'description' => __( 'Box Title', 'text-domain' ), 'admin_label' => false, 'weight' => 0, 'group' => 'Custom Group', ), array( 'type' => 'textarea', 'holder' => 'div', 'class' => 'text-class', 'heading' => __( 'Text', 'text-domain' ), 'param_name' => 'text', 'value' => __( 'Default value', 'text-domain' ), 'description' => __( 'Box Text', 'text-domain' ), 'admin_label' => false, 'weight' => 0, 'group' => 'Custom Group', ), ), ) ); } // Element HTML public function vc_infobox_html( $atts ) { // Params extraction extract( shortcode_atts( array( 'title' => '', 'text' => '', ), $atts ) ); // Fill $html var with data $html = ' <div class="vc-infobox-wrap"> <h2 class="vc-infobox-title">' . $title . '</h2> <div class="vc-infobox-text">' . $text . '</div> </div>'; return $html; } } // End Element Class // Element Class Init new vcInfoBox();