I was recently working on a WordPress project that required me to create multiple content tabs per page. Considering this was a WordPress project naturally all the tab content needed to be powered through the CMS. With Advanced Custom Fields this is actually a pretty straight forward task.

Step 1

Create a repeater field for the tabs

Repeater Group

Repeater Text

Repeater Content

as you can see I’ve created a Tab Label (text) field and a Tab Content (wysiwyg) field.

Step 2

Next we need to create the PHP template. The main thing here is that we want to generate some dynamic classes and ids that we can use later in our jQuery. The link tab-section--<?php echo $tabSection++; will generate a class called .tab-section--0, .tab-section--1, an so on, for as many tabs that exist. Likewise the anchor tags within the tab-nav will get a hash id that matches the id of a corresponding .tab-content.

  $tabSection = 0;
  $tabLabel = 0;
  $tabContent = 0;

<section class="tab-section tab-section--<?php echo $tabSection++; ?>">
  <nav class="tab-nav">
   <?php if(have_rows('tabs'): ?>
    <?php while(have_rows('tabs'): the_row(); ?>
     <a href="#tab-content--<php $tabLabel++; ?>"><?php the_sub_field('tab_label'); ?></a>
    <?php endwhile; ?>
   <?php endif; ?>

  <?php if(have_rows('tabs'): ?>
    <?php while(have_rows('tabs'): the_row(); ?>
     <div id="tab-content--<?php $tabContent++; ?>" class="tab-content">
      <?php the_sub_field('tab_content'); ?>
    <?php endwhile; ?>
  <?php endif; ?>


Step 3

Next let’s give our tabs some styles. Pretty straight forward.

.tab-nav {
  span {
    display: inline-block;
  a {
    color: #fff;
    @include font($roboto-bold);
    display: inline-block;
    padding: .5em 1em;
    background-color: lightgray;
  .tab-nav--active {
    a {
      background-color: gray;

.tab-content {
  border: 1px solid lightgray;
  padding: 1em;


Step 4

Finally, it’s time to make them work with jQuery. We want to initially hide all the .tab-content div except for the first one. Also, we give the first .tab-nav an active state by default. I’m using an each function with an iterator variable that will match up with the iterator variable in the php template. This way all the tabs sets will function independently from each other.

    $('.tab-section--' + i + ' .tab-content').not(':first').hide();
    $('.tab-section--' + i + ' .tab-content:first').show();

    $('.tab-section--' + i + ' .tab-nav span:first').addClass('tab-nav--active');

    $('.tab-section--' + i + ' .tab-nav').on('click', 'span', function(){
        //Remove class of active tab
        $('.tab-section--' + i + ' .tab-nav span.tab-nav--active').removeClass('tab-nav--active');
        //Add class of active to clicked tab
        $('.tab-section--' + i + ' .tab-content').hide();
        //Show clicked tab
        return false;


5 responses to “Creating Tabs with Advanced Custom Fields and jQuery”

  1. Alexander says:

    Hi, i could not get this to work. I guess the PHP template is a page template? What is SCSS, and how i can use this?

    • admin says:

      Hi Alexander,

      Yes you can put the PHP in any of your templates. SCSS is a CSS preprocessor. It basically extends the functionality of CSS. You can nest your styles, create variables and mixins, and even write functions. Here’s a link for more info http://sass-lang.com/. However, you don’t need to use SCSS in order to create these tabs, plain CSS will work fine. Can you provide more details on what you are having problems with? If you have a link to your code that would be helpful.


  2. Armando says:

    hey, how are you, im following this guide and wanted to know where to place the jquery, im new to php developing

    • John says:

      Hi Armando,

      Usually you’ll have a main JavaScript file where you put all your jQuery. So at the bottom of your page after you’ve loaded the jQuery library you would reference your main.js file. Hope that helps

  3. Ruud van Bergen says:

    Didn’t you forget the question mark at the php-tag in the following bit of code?

Leave a Reply

Your email address will not be published. Required fields are marked *