How to create a tabbed options page for your WordPress theme using CMB

If you are a WordPress developer like me creating your own themes, you most probably would have wanted to add easy customisability to your theme by incorporating a theme options page. But you might have found out that it’s a big hassle to create one, having to write lots of code to render the options page and more to process the input data. It’s especially complicated if you want to do anything fancy like including file upload fields or color-pickers. Fortunately there are several WordPress options frameworks out there that make the job quite easy.

Personally I have been using the WP Theming Options Framework Theme for my recent themes’ options pages and Custom Metaboxes and Fields (CMB) for WordPress to create my custom metaboxes for those themes. However it was a bit of a hassle and redundant to use two separate frameworks for two very similar tasks. However it turns out that CMB is actually capable of creating a Theme Options page!

The CMB Wiki has a great example on how to create your own theme options page. But I wanted to go one step further and also add tabs to the options page. I have adapted the code from the Wiki to achieve this task. All the code you need for this is given below (of course you’d first have to properly install CMB). Add this code to your theme functions.php file and you are good to go.

Once you have added the code you should be left with an options page with 3 tabs like the one shown below.

You should be able to access your custom saved theme options by using  my_option( option_id );  inside your theme files.

Adding New Tabs

If you want to add new tabs to the options page all you have to do is to add extra tab arrays inside the  option_fields() function. The below example will add a tab called New Tab with a single text field.

Remember that the tabs will be rendered in the order that you add them. Also each tab id and field id must be unique. Most importantly the tab id and value inside  'show_on' => array( 'key' => 'options-page', 'value' => array( 'new_tab' ), ), must be exactly same.

You can add extra fields by adding more arrays inside the fields array. For a list of available field types you can check here.


If you set a default value for a field, when you try to save a blank value for the particular field, it would change back to the default value. So if you want to allow blank values for any field, set an empty string as the default value.

In future versions I would like to add a “reset to defaults” button to the options page which would make it easier for theme users to reset the theme if they mess up the settings.


  • Hi Arushad,

    that is this is really a great work! I have CMB installed correctly and it works for my Custom Post Type and the original example of the Theme Options Page, but unfortunately your code will not work for me.

    I am using WordPress 4.0 and CMB2 and have copied your code and pasted without further changes. The menu item and the page with the tabs are displayed correctly, but the individual metaboxes are not. What am I doing wrong? Do you have any idea?

    Thanks in advance


    • Hi Peter,

      Are the metaboxes not being displayed at all on the options page?

      Where are you adding the code? Try putting this code in a separate file and include it from functions.php right after the CMB library files are included.

  • Can’t access custom saved theme options by using my_option( option_id );

  • Nice work Arushad!

    Do you have an example of how to display an image upload in your theme? I use CMB2 as well for custom post types, but I can’t use the same logic here apparently to display images.

    Any thoughts?

  • I am unfamiliar on how to display a saved theme option by using my_option( option_id ); Can you please explain how to use this and how it calls a specific metabox? I have looked around and can not figure this out

    • Have you tested to see that the options panel is working and saving data within WordPress first? If it’s working on the admin side, then just use something like below to display in your theme. I’ll keep it in context of the demo in this article so you can see the relationship.

      This example would get the “YouTube” option data:

      Also make sure that you’re using the correct call to retrieve the theme option. It should match the function name that is on line 290 of the provided example – if you’ve modified that, make sure to update this. ‘youtube’ is the ID found on line 193.

      Hope this helps.

  • How to create same theme option page by using Plugins , it’s upgraded version of CMB.

  • Hi Arushad,
    Thanks a lot about this article !
    unfortunately i can’t use this code with CM2 group fields .
    is it match with CM2 group repeatable fields ?
    thanks !

    • Do this: array(
      ‘id’ => ‘tp_ads’,
      ‘type’ => ‘group’,
      ‘options’ => array(
      ‘group_title’ => esc_html__( ‘Entry {#}’, ‘cmb2’ ), // {#} gets replaced by row number
      ‘add_button’ => esc_html__( ‘Add New’, ‘cmb2’ ),
      ‘remove_button’ => esc_html__( ‘Remove’, ‘cmb2’ ),
      ‘sortable’ => true, // beta
      // ‘closed’ => true, // true to have the groups closed by default
      ‘fields’ => array(
      ‘name’ => esc_html__( ‘Banner Image’, ‘cmb2’ ),
      ‘desc’ => esc_html__( ‘Upload an image or enter a URL.’, ‘cmb2’ ),
      ‘id’ => ‘ad_imagey’,
      ‘type’ => ‘file’,
      ‘name’ => esc_html__( ‘Banner Image’, ‘cmb2’ ),
      ‘desc’ => esc_html__( ‘Upload an image or enter a URL.’, ‘cmb2’ ),
      ‘id’ => ‘ad_imagex’,
      ‘type’ => ‘file’,

  • Thank you. Seems to work with CMB2 with some minor adjustments.
    I haven’t tried all field types, but your setup above is working as expected.

  • would u please update with cmb2.

  • works on cmb2 too, just need to change cmb_metabox_form( $tab_form, $tab_form[‘id’] ); to cmb2_metabox_form( $tab_form, $tab_form[‘id’] );

  • how do you echo out the fields to the wordpress template

  • awesome. thanks for this. saved me a lot of time. This should be included in the examples!

  • For those following along, there is now a snippet in the snippet library for adding tabbed navigation for options-pages :

    And even better, the ‘tab_group’ box property will be in the next version of CMB2 to make things easier:

  • Thank’s man! You have this much better documented then CMB2 😉

Leave a Reply