How To Create Tabs On WordPress Settings Pages


Using tabs in a user interface can help you better organize content, so it’s only natural that WordPress themes that have a lot of options would benefit from tabs on their settings page. In this tutorial, you will learn how to create a tabbed settings page, and you’ll get to download a WordPress theme that implements the code.



To get a quick grasp of the tabs we’ll be creating, go to Appearance/Themes in the WordPress admin area. You will find two tabs there: “Manage Themes” and “Install Themes.” When you click on one, the content changes and the tab’s title is highlighted.

The process is actually fairly simple: we set and send a tab variable when a tab is clicked. By querying this tab variable later, in $_GET['tab'], we will know which tab was selected so that we can highlight the corresponding title and display the corresponding tab.

In our approach, there are three times when we will need to know which tab the user is currently on:

  1. When we initially display the tabs and the form fields for the settings (in order to display the correct set of fields);
  2. When the user saves their settings (in order to save the correct fields);
  3. When redirecting the user after they have saved their settings (in order to redirect the user to the correct tab).

For the sake of brevity, we won’t explain all of the code, only the snippets that are relevant to this approach. You can, however, find all of the code in the accompanying theme.

Creating The Tabs

The first snippet we will inspect is the code that produces the tabs:

function ilc_admin_tabs( $current = 'homepage' ) {
    $tabs = array( 'homepage' => 'Home Settings', 'general' => 'General', 'footer' => 'Footer' );
    echo '<div id="icon-themes" class="icon32"><br></div>';
    echo '<h2 class="nav-tab-wrapper">';
    foreach( $tabs as $tab => $name ){
        $class = ( $tab == $current ) ? ' nav-tab-active' : '';
        echo "<a class='nav-tab$class' href='?page=theme-settings&tab=$tab'>$name</a>";

    echo '</h2>';

This function will be called later in the content for the settings page. We first define an array that contains all of our tabs. The first tab, which is displayed first by default, is homepage, where we can set up some option for the appearance of the home page. Then we have general, which could be a page containing options used throughout the website, and, finally, footer, to include a tracking code in the footer.


We then set up the URL links for each tab and output them. Notice that if the tab is open, an additional class, nav-tab-active, is added.

Displaying The Tabbed Content

The content for the settings page is displayed in the callback function for add_theme_page (which is an abstraction of add_submenu_page3, with the parent slug set to themes.php), which in our theme will be named ilc_settings_page. This is where you will call the function that we just went over.

function ilc_settings_page() {
   global $pagenow;
   $settings = get_option( "ilc_theme_settings" );

//generic HTML and code goes here

if ( isset ( $_GET['tab'] ) ) ilc_admin_tabs($_GET['tab']); else ilc_admin_tabs('homepage');

If the tab is the default one, then $_GET['tab'] is not defined, in which case the current tab will be homepage and, thus, the highlighted one. Otherwise, the highlighted tab will be the one defined in $_GET['tab'].

Following the same function, we now need to display the right set of fields. Depending on the value of $tab, we would display the fields for the settings tab for the home page or for one of the other tabs:

<form method="post" action="<?php admin_url( 'themes.php?page=theme-settings' ); ?>">
wp_nonce_field( "ilc-settings-page" ); 

if ( $pagenow == 'themes.php' && $_GET['page'] == 'theme-settings' ){

   if ( isset ( $_GET['tab'] ) ) $tab = $_GET['tab'];
   else $tab = 'homepage';

   echo '<table class="form-table">';
   switch ( $tab ){
      case 'general' :
            <th>Tags with CSS classes:</th>
               <input id="ilc_tag_class" name="ilc_tag_class" type="checkbox" <?php if ( $settings["ilc_tag_class"] ) echo 'checked="checked"'; ?> value="true" />
               <label for="ilc_tag_class">Checking this will output each post tag with a specific CSS class based on its slug.</label>
      case 'footer' :
            <th><label for="ilc_ga">Insert tracking code:</label></th>
               Enter your Google Analytics tracking code:
               <textarea id="ilc_ga" name="ilc_ga" cols="60" rows="5"><?php echo esc_html( stripslashes( $settings["ilc_ga"] ) ); ?></textarea><br />

      case 'homepage' :
            <th><label for="ilc_intro">Introduction</label></th>
               Enter the introductory text for the home page:
               <textarea id="ilc_intro" name="ilc_intro" cols="60" rows="5" ><?php echo esc_html( stripslashes( $settings["ilc_intro"] ) ); ?></textarea>
   echo '</table>';

   <p class="submit" style="clear: both;">
      <input type="submit" name="Submit"  class="button-primary" value="Update Settings" />
      <input type="hidden" name="ilc-settings-submit" value="Y" />

All of the settings will be stored in a single array in order to prevent several queries from being made.

Saving The Tabbed Fields

Now we need to know which slots of the array to save. Depending on the tab being displayed, certain options stored in the settings array will be displayed. If we just save all of the array slots, then we would overwrite some of the positions not shown in the current tab and thus not meant to be saved.

function ilc_save_theme_settings() {
   global $pagenow;
   $settings = get_option( "ilc_theme_settings" );

   if ( $pagenow == 'themes.php' && $_GET['page'] == 'theme-settings' ){
      if ( isset ( $_GET['tab'] ) )
           $tab = $_GET['tab'];
           $tab = 'homepage';

       switch ( $tab ){
           case 'general' :
         $settings['ilc_tag_class'] = $_POST['ilc_tag_class'];
           case 'footer' :
         $settings['ilc_ga'] = $_POST['ilc_ga'];
      case 'homepage' :
         $settings['ilc_intro'] = $_POST['ilc_intro'];
   //code to filter html goes here
   $updated = update_option( "ilc_theme_settings", $settings );

We’ve used a switch conditional again to query the value of $tab and store the right values in the array. After that, we’ve updated the option in the WordPress database.

Redirecting The User To The Right Tab

Now that the contents are saved, we need WordPress to redirect the user back to the appropriate tab on the settings page.

function ilc_load_settings_page() {
  if ( $_POST["ilc-settings-submit"] == 'Y' ) {
   check_admin_referer( "ilc-settings-page" );

   $url_parameters = isset($_GET['tab'])? 'updated=true&tab='.$_GET['tab'] : 'updated=true';

Depending on whether the $_GET['tab'] variable is set, we use wp_redirect to send the user either to the default tab or to one of the other tabs.

Now our tabs are working, displaying the right set of fields, saving the right fields, and then redirecting the user to the correct tab.

Download The Theme

Almost any theme with a moderate number of options would benefit from tabs on the settings page. Just remember that this is one approach. Another approach would be to add several collapsable meta boxes, as seen on the page for writing posts, and to automatically collapse the boxes that are not frequently used. However, tabs enable you to better separate each set of options.

Finally, here is the theme, so that you can take a closer look:

The theme also implements the function whereby each tag is outputted with a unique CSS class5, so you can check that out, too.



  1. 1
  2. 2
  3. 3
  4. 4
  5. 5

↑ Back to topShare on Twitter


Note: Our rating-system has caused errors, so it's disabled at the moment. It will be back the moment the problem has been resolved. We're very sorry. Happy Holidays!

  1. 1

    very helpful! you rock Elio!

  2. 2

    Greaaaaattttt article. Thanks a lot!

    I will use this soon..

  3. 3

    Thanks for the tutorial. I’ve been seeing a lot of themes and option frameworks take this tabbed approach lately… is it the one WordPress is pushing for?

  4. 4

    hi ..
    thanks for details and focus on this section. i have one question . week ago i used jquery ui and tabs script that comes with wp. is this method faster than using inbuilt jquery UI and tabs getting custom tabs as u like? what is difference here ?

    • 5

      Since these tabs are completely JavaScript agnostic they are very easy on client system resources and also fully compatible with browsers. These tabs use the same approach and styling than WordPress own tabs so by using these tabs you can get a settings page that blends nicely into the overall WP Admin look and feel, if that’s what you’re looking for.

      • 6

        so if you need some customization or different design then my way is correct !
        thanks for the efforts and answer ;)

  5. 7

    Useful tutorial. Thank you Elio!

  6. 8

    For interest sake, a similar great post on the same subject :

  7. 9

    Thank you for sharing, very useful information for upcoming project.

  8. 10

    I am sure it was obvious that this question would be coming, but do you have any thoughts as to what would be the best way to add an image upload field using this method?

  9. 11

    I’ve asked elsewhere, so might as well ask here also as this is a great tutorial.

    I’m working with the bbPress plugin which has a settings page, but no tabs. I want to have my own plugin add tabs to the bbPress settings page, so that I can store all my custom options in a central location instead of creating yet another settings page.

    How would I go about ‘extending’ an existing settings page to add tabs and my own options to it?
    -because original settings page does not use tabs, there seems to be no ‘home’ to place the original bbPress options under. Just one of the issues I am stuck with.

    Would make a unique tutorial, as so far I have yet to find anything that describes adding tabs to existing settings pages…

  10. 12

    Thanks for the information Friend :)

    Very useful post thanks for the sharing

  11. 13
  12. 14

    Awesome tutorial! This is great for themes or plugins with a small set of options. I’m using Infinity ( to create more advanced custom dashboards, where I don’t even need to write any code to add options or tabs. I love creating themes, but I pretty much suck at php, so Infinity helps me solve this.

  13. 15

    Konstantin Kovshenin

    October 22, 2011 1:31 am

    Seriously, the Settings API is what you should be using and teaching and as Brad pointed out above: comes with a demo plugin you can download and play around with too ;)

    ~ K

  14. 16

    nice one, who did the graphic with the tabs?

  15. 17

    Its realy great tutorial.Thank you.

  16. 18

    Looks like the author did the graphic by himself

  17. 19

    This is fantastic. Thank you!

  18. 20

    Thanks for the help on creating tabs, that’s really great now I can do it right. I appreciate the time you took of explaining it and actually showing us the code. There are many others who don’t really share this so thanks.

  19. 21


    first of all i am not really PHP expert.

    I am working on a blog website.

    On home page they are looking for recent post to show up.
    on archive page it should be all the collection.

    I was wondering is there any how i can make categories to get data from recent post (which is on the home page) also same content on the archive.

    Here is how i am thinking of getting post from archive and showing it on home page.

    Please give me any help will be appreciated.

    Thank you.

  20. 22

    thanks a lot man.. really helpfull :)

  21. 23

    So good! Thank you. I will use it :)

  22. 24

    Great tutorial – helped me alot.

    But now that I’ve created the tabs and it’s working like it should, I came to think WHY…

    Why are these tabs a lot more slower than the JQuery UI tabs? I mean.. obviously it’s because we’re loading the page every time we switch between the tabs, but what’s the pro’s for doing it this way.

    I’m thinking… it isn’t very user friendly, and could be potentionally annoying to our theme customers, having to wait a second every time they click a new tab?

    So my question is: Why make it this way, and not the mere fluid and quicker way (like just show/hide using jQuery, like the JQuery UI example? I simply don’t understand why.

  23. 25

    Great post but the UI for the tabs do not exist in WordPress from the first version. Anyone know what was the first version of WordPress that include the tabs ? In that way, it could be possible to adapt this code for older version of WordPress.
    Thanks in advance for those who may have this answer.

  24. 26


    Great tutorial! Thanks! Any idea why sometimes the setting for one of my tabs get not saved? Then I just repeat the process and mysteriously, after few tries, it finally get saved.

    Anyone experienced this?


  25. 27

    What’s the output code?

  26. 28

    I’d like to see a demo using jQuery to switch the tabs – it would make it easier to save since you are saving all the fields, and though more intensive on the browser, save trips to the server.


  27. 29

    sandeep kumar dan

    February 21, 2014 2:27 am

    Hi, Thanks for helping , I have used it on my site and ,its working fine thanks a lot.
    Sandeep Kumar Dan
    Dan Web Technologies

  28. 30

    Hey… Thanks for nice and awesome tutorial. I have been using this repeatedly in my projects. Do you mind helping a noob like me out here…? How can I take the “Theme setting” page to the top level option menu? I mean just in between Appearance and Plugins menu??

  29. 31

    Great article. But it is under apearance menu, I want to use it under menu page. how to..? please help me, I cant convert it to under menu.

  30. 32

    I have been using tabs on 6 different pages in CSV 2 POST for a long time.

    However there is a major flaw especially if you want to stick to WordPress standards. You cannot use postboxes on each tab very easily. I’m hacking away right now and if there is a solution it evades me.

    Each view needs to be registered as a WP admin page so WP Ajax handles the moving and closing of postbox settings properly.

    Problem there is not building the tab menu but loading the view with the menu on it when visiting one of the sub/tab pages. As I type this I have a possible solution but it’s not very clean. It would require a more dynamic main admin menu that hides all tabs not being viewed, only showing one item in the menu with the slug being for the page being viewed, but the title of the item in the menu always being the same so it gives the desired visual effect.

↑ Back to top