Menu Search
Jump to the content X X
Smashing Conf Barcelona

You know, we use ad-blockers as well. We gotta keep those servers running though. Did you know that we publish useful books and run friendly conferences — crafted for pros like yourself? E.g. our upcoming SmashingConf Barcelona, dedicated to smart front-end techniques and design patterns.

How To Create A Tab Widget In WordPress

In this tutorial, you’ll learn how to create the Tabber widget, which is very useful for when multiple widgets need to fit in a sidebar. It saves space and streamlines the appearance and functionality of your WordPress-powered website.

In the past, there were different methods of doing this, most of which were theme-dependent. As we’ll see in this tutorial, creating a tabbed widget that works on its own and with any theme is easily accomplished. So, let’s jump in and learn how to create our own Tabber widget, which we’ve made available for downloading at the end of this article.


Saving Sidebar Space Link

The main advantage of tabs is that you can fit more widgets into the sidebar. And tabs look good. The image below shows how much vertical space is taken up by three standard widgets (using the default Twenty Ten theme). The default layout is on the left, and our tabber widget is on the right:


Before We Start Link

A few things are useful to know. Because we are building a widget in this article, you might want to learn about WordPress’ Widgets API and how to create a basic widget:

Use these resources as needed while following the tutorial along.

The Basic Idea Link

The idea for this widget is simple: select a sidebar, and the Tabber widget will grab all of its widgets and display them as tabs. In the widget’s interface, you can select a sidebar, specify an extra CSS class and optionally apply your own styles. When enabled, the plugin will register an extra sidebar (which may be removed if you have other ways to add a sidebar). Then, using the same code, you can add more sidebars, and each of them can hold instances of the Tabber widget.

Further Reading on SmashingMag: Link

To control your widgets, Tabber uses idTabs1410 for jQuery, created by Sean Catchpole, but you could always use another solution. Note that additional CSS is loaded to style the resulting widget.

Here is the basic HTML structure required to create tabs:

  <li><a href="#widget-1">Widget one</a></li>
  <li><a href="#widget-2">Widget two</a></li>
<div id="widget-1">
  Widget one's content
<div id="widget-2">
  Widget two's content

Unfortunately, you can’t get such a structure directly by using WordPress’ sidebar and widget rendering. Typically, WordPress’ widget structure looks like this:

<div id="widget-1">
  <h2>Widget one</h2>
  Widget one's content
<div id="widget-2">
  <h2>Widget two</h2>
  Widget two's content

So, the goal with Tabber is to transform any widget’s output into markup that can be used to display tabs. To complicate matters, different themes might register sidebars that do not use a <div> to hold a widget or use <h2> to show its title. For example, WordPress’ new default theme, Twenty Twelve, uses <aside> and <h3> tags for this. Other themes may use complicated markup that can’t be predicted or successfully transformed into the output needed for tabs.

The solution to this problem is to intercept the widget’s parameters before rendering, and then to restructure them into useful structures using JavaScript or jQuery for the tabbed output. More on that later.

Tabber Widget Loading Link

Now that we understand the goal, let’s look at the demo plugin. Our plugin contains a main PHP file, one JavaScript file and one CSS file. The PHP file contains the widget and loads the CSS and JavaScript, like so:

add_action('init', 'd4p_st_init');
add_action('widgets_init', 'd4p_st_widgets_init');

function d4p_st_init() {
    register_sidebar(array('name' => 'Tabber Example Sidebar', 'description' => 'Add widgets to this sidebar to use it from Tabber widget.'));

    if (!is_admin()) {
        $url = plugins_url('d4p-smashing-tabber');

        wp_enqueue_script('d4p_st_tabber', $url.'/tabber.js', array('jquery'));
        wp_enqueue_style('d4p_st_tabber', $url.'/tabber.css');

function d4p_st_widgets_init() {

Here, the function d4p_st_init is run during WordPress’ init action. It will register one sidebar (line 5) and enqueue the jQuery, JavaScript and CSS files using the wp_enqueue_script and wp_enqueue_style functions (lines 10 to 12).

Then, the function d4p_st_widgets_init is called during WordPress’ widgets_init action. We register the widget on line 17.

Widget Interface11
Widget interface.

The Main Tabber Widget Class Link

Tabber is a normal widget, and in this case it is located in the d4p_sr_tabber class.

Settings: Plugin Interface Link

The widget has two settings:

  • “sidebar”
    to hold the ID of the selected sidebar
  • “css”
    for extra CSS classes to style the Tabber widget

When selecting which sidebar to use, you must avoid using the sidebar that holds the Tabber widget. Otherwise, it will spin into endless recursion. To avoid this, before rendering the widget’s content, check whether the selected sidebar is the same as the parent sidebar. This can’t be prevented while the widget is set up, because the widget’s panel affords very little control over this.

Also, using sidebars that are not normally used is a good idea. To help with this, the plugin includes sample code to help you add an extra sidebar.

The form and update methods contained in the d4p_sr_tabber class are used to display the widget’s interface in the “Widgets” panel and to save its settings, and they are not that interesting. But it is worth taking a closer look at how to display the widget on the front end.

Main Display Method Link

Here is the main widget method:

public function widget($args, $instance) {
  add_filter('dynamic_sidebar_params', array(&$this, 'widget_sidebar_params'));

  extract($args, EXTR_SKIP);
  $this->id = $widget_id;

  echo $before_widget;
  if ($args['id'] != $instance['sidebar']) {
    echo '<div id="'.$widget_id.'">';
    echo '<ul></ul>';
    echo '</div>';
  } else {
    echo 'Tabber widget is not properly configured.';
  echo $after_widget;

  remove_filter('dynamic_sidebar_params', array(&$this, 'widget_sidebar_params'));

In this code, line 2 adds a filter that modifies the widget’s rendering parameters before they are processed. With this filter, all widgets rendered after that point will have their parameters modified as needed for successful transformation to tabbed form. And that will be done for the widgets in the selected sidebar on line 11, using the dynamic_sidebar function.

This function requires the name of the sidebar, and it will display all widgets in it. Line 9 contains the check mentioned before, to prevent recursion when displaying sidebar content if the selected sidebar is the same as the parent sidebar.

Lastly, the filter is removed, and any widgets belonging to other sidebars are displayed normally, without modification.

Widget Modification Link

To prepare for the transformation done with JavaScript, the tabber widget includes the d4p-tabber-widget class, which contains an empty <ul> tag.

The filter used to modify the widget’s parameters looks like this:

public function widget_sidebar_params($params) {
  $params[0]['before_widget'] = '<div id="'.$params[0]['widget_id'].'">';
  $params[0]['after_widget'] = '</div>';
  $params[0]['before_title'] = '<a href="#">';
  $params[0]['after_title'] = '</a>';

  return $params;}

Depending on how the sidebar is registered, this code will change the rendering parameters to a format that is close to the format needed for tabs. But JavaScript is still needed to move the widget’s title into the <ul> tag for the control tabs. After this filter, the widget’s output will look like this:

<div id="widget-1">
  <a href="#">Widget one</a>
  Widget one's content

JavaScript For Widget Transformation Link

Once the widget’s presentation is modified, one thing remains: to complete the transformation and get the titles from the widgets and turn them into tabs:

  var ul = jQuery(this).find("ul.d4p-tabber-header");

  jQuery(this).children("div.d4p-st-tab").each(function() {
    var widget = jQuery(this).attr("id");
    jQuery(this).find('a.d4p-st-title').attr("href", "#" + widget).wrap('<li></li>').parent().detach().appendTo(ul);


This code uses jQuery to get all of the Tabber widgets based on the .d4p-tabber-widget CSS class, and each one gets the element (where the tabs will go):

  • With line 5, we find all individual widgets belonging to the Tabber widget.
  • On line 6, we get the widget’s ID needed for the tab to connect it to the widget’s content.
  • On line 7, we find the title <a> element, set its href attribute to that of the widget’s ID, wrap it in a </li> element, remove it from its current location, and move it into the tab’s <ul> element.
  • After this, the <div> will hold only its content.

Final Tabber Example12
Final Tabber example.

Finally, when all this is done, we enable idTabs to activate the tabs control. And with the default styling loaded from the tabber.css file, you can see how Tabber looks with three widgets in it (see screenshot above). Feel free to experiment and adjust the styling to your theme.

How To Install The Tabber Plugin Link

As with any other plugin, unpack it, upload it to WordPress’ plugins folder, and activate it from the plugins panel. When you go to the “Widgets” panel, you will see an additional sidebar, “Tabber Example Sidebar,” at the end on the right. And “Available Widgets” will show one more widget, “D4P Smashing Tabber.”

Add this new widget to the “Main Sidebar.” From the “Sidebar” widget drop-down menu, select “Tabber Example Sidebar,” and save the widget. Now, open the “Tabber Example Sidebar” and add the widgets you want to be displayed as tabs. You can add as many widgets as you want, but pay attention because if you add too many, the tab’s control will break to two or more lines, and it will not look pretty. Starting with two or three widgets is best.

Conclusion Link

Creating one widget to display several other widgets as a tab isn’t very difficult, as you can see. The trick is in adjusting the widgets’ output to a format that can be transformed into tabs, and then using JavaScript to display them. We’ve explored just one possible transformation method; you can always experiment with ways to rearrange widget elements.

We used idTabs here, but there are many methods of displaying tabs, and not all of them require JavaScript:

I prefer using a jQuery-based solution, and idTabs is very easy to use and easy to style and it works in all browsers. Check out other solutions, and see what extra features they offer to enhance your own tabbed widgets.


Footnotes Link

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16

↑ Back to top Tweet itShare on Facebook

Founder of Dev4Press, dedicated to development for WordPress, focusing on premium plugins. Dev4Press website offers wide selection of practical tutorials for WordPress. Milan is author of many popular WordPress plugins, including GD Star Rating, GD Press Tools and GD CPT Tools. Milan also developed several plugins for bbPress for WordPress powered forums: GD bbPress Toolbox.

  1. 1

    Nice and useful tutorial, thanks for sharing!

  2. 2

    Awesome tutorial on something that had been running around in my brain as something to try all day. Now I don’t have to fumble with it!

  3. 3

    Simple but very useful tip. Thank for sharing this.

  4. 4

    Interesting and creative article. But there is one small thing that I’d like to point out. The first wp_enqueue_script call is redundant because you specify jquery as a dependency in your second wp_enqueue_script call so it is automatically loaded.

    • 5

      Milan Petrović

      April 6, 2013 2:26 am

      Thanks for pointing that out. I always find it useful to include jQuery (and any other JS that comes with WordPress) that way since it is easier to follow and understand. Dependency parameter later can be easy to miss.

  5. 6

    Geert-Jan Brits

    April 4, 2013 2:41 pm

    Nice tutorial.

    Always wondered what kind of rules you have to follow so other people could theme your plugin. Any guides to this?

  6. 7

    Thanks for the tutorial, very informative!

    One thing I notice though is that the additional CSS class doesn’t output anywhere. I think the instance “class” should be added after line 52 of the plugin file?

  7. 8


    Its really nice tutorial for wordpress developer. thanks for sharing this useful article.

  8. 9

    Hi Milan, It’s a great plugin for me as I have been looking for these. I’ve just downloaded the plugin and have installed on my site. Everything seems okay except one thing. The TABS are not showing horizontally rather showing vertically. I couldn’t figure out what to change in CSS. Could you please help me out? Thanks in advance.

    FYI, you may get the clear idea what I’m talking about if you see this image:

  9. 10

    Andrew Sapiens

    April 16, 2013 5:57 pm

    Been wanting to learn how to do this. Thanks for sharing your wisdom!

  10. 11

    We also have plugins to this. Will it harm using that plugin in a website???

  11. 12

    Hi there.

    I downloaded the plugin for WordPress, activated it and tried to make some css changes directly on the /tabber.css file. Nothing hapened. Then, I created a new file, name it as tabber-fb.css, uploaded it. Then on the php file of the plugin I changed this line wp_enqueue_style(‘d4p_smashing_tabber’, $url.’/tabber.css’); with this: wp_enqueue_style(‘d4p_smashing_tabber’, $url.’/tabber-fb.css’);

    Now it loads the style from tabber-fb.css and is fine, but when editing it i have this title: Editing d4p-smashing-tabber/tabber-fb.css (inactive)

    This means that the css file is inactive? If so, why is taking the style from it?

    Also I would like to know, how to add 2 tabber widgets on my site, I mean creating another zone where to drag the widgets.

    Thank you, cool plugin!

  12. 13


    How to align to header to left? I cannot figure out the way, any change I made it just mess up the current css.

    Thank you.

  13. 14

    Great walkthrough of creating a plugin.. why not submit plugin to the wordpress site? Then if I want to use your plugin I can get updates and feedback etc.

  14. 15

    One thing I noticed was that this strips the ‘current-menu-item’ from the . Is there a way to make sure this can be added back in to the output?

  15. 16

    Great pluggin!

    How can I modify it so all CSS classes from the widgets included in the tabber remain in an original form? I have many wordpress classes predefined by my theme (which I bought) and now they are removed. I would like to integrate this plugin in my sidebars.

    Thanks for the great work and insights!

  16. 17

    Nice one.. But still need some more clarity like basic structures to create wordpress plugin. That is before starting we need to know

    1. Register with widget-init hook
    2. extend the class with WP_Admin
    3. Class structure..

    Hope I this may help you to learn in detail with clean structure.

  17. 18

    Oh hi! I was wondering if you have a CSS coding to change the color of the tabs. Blue does not compliment the color branding of my blog.

    Thanks so much!

  18. 19

    I have a small validation error I can’t seem to fix: the aside tag has the same ID as the div, thus the W3 validator wont pass it as valid.

    I know its a small detail, but its the only error left that I have to fix ;)

  19. 20

    This blog about how to create the Tabber widget, which is very useful for when multiple widgets need to fit in a sidebar.

  20. 21

    Yes, but can you teach us how create a tab for comments like in this post: Thank you very much..

  21. 22

    Hi there

    This is brilliant. A very elegant way to achieve this effect – much better than what I have used in the past. However, I had a problem getting it to work in a Genesis theme. The .js wasn’t being enqueued, I don’t think (I’m far from an expert on these things).

    What I did in the end was copy the .js file from the plugin folder into my js folder within my child theme, then enqueued it in functions.php and it works perfectly.

    Is this Genesis specific, do you think?

    Other than that, amazing. Thanks.

  22. 23

    thank you very much, work in my wordpress


↑ Back to top