A Free WordPress Tab Plugin

The WordPress Block Editor (Gutenberg) is incredibly flexible, yet a simple, native solution for creating organized content tabs is still conspicuously missing. Many plugins solve this by injecting heavy, proprietary frameworks, but the LDE Tabs Plugin takes a different, ultra-lightweight approach that leverages the editor’s core power. Unlike complex tab solutions, this Free WordPress Tab Plugin has a simple implementation: you only need to use the existing Advanced block settings. If you’ve ever been unsure about how to correctly set the HTML Anchor or Additional CSS Class(es), don’t worry—I will demonstrate, with clear screenshots below, exactly where to apply these two essential attributes on your content. This approach keeps the code lean, avoids unnecessary JavaScript bloat, and results in a highly organized, mobile-friendly interface.

Table of Contents

Tutorial Code For My Free WordPress Tab Plugin

Here is a cut down version of the plugin code for you to checkout. It doesn’t support multiple tabs on the same page or have a settings page or help but you can play around with it if you like. Just respect the GPL license.

Create the files lde-tabs-tut-plugin.php, lde-tabs-tut-plugin.css and lde-tabs-tut-plugin.js and copy them to a zip folder called lde-tabs-plugin.zip

<?php
/**
 * Plugin Name: LDE Tabs Tutorial Plugin
 * Description: Creates a responsive tab menu to toggle
 *   visibility of Block Editor content.
 * Usage: Place [lde_tabs_tut config="Label 1:id-1, Label 2:id-2"]
 *   where you want the tabs. 
 * Limitations: Will only work within a single tab group.
 *  No custom setup form. Colors and styles must be customized in the CSS file.
 * Ensure content blocks (Group Blocks) have matching HTML 
 *   Anchor IDs and the CSS class 'lde-tab-tut-content'
 * (Use Advanced in the Block settings to set these values)
 * Version: 0.9.0 Tutorial
 * Author: Les Ey
 * Author URI:  https://les-ey.online/
 * License: GPL-2.0-or-later
 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain: lde-tabs-plugin
 */

// Prevent direct access to the plugin file
if ( ! defined( 'ABSPATH' ) ) exit;

/**
 * Enqueue the plugin's JavaScript and CSS files
 */
function lde_tabs_tut_assets() {
    // Enqueue CSS stylesheet
    wp_enqueue_style(
        'lde-tabs-tut-style',
        plugin_dir_url(__FILE__) . 'lde-tabs-tut-plugin.css',
        array(),
        '1.0' 
    );
    
    // Enqueue JavaScript (loading in the footer)
    wp_enqueue_script(
        'lde-tabs-tut-script',
        plugin_dir_url(__FILE__) . 'lde-tabs-tut-plugin.js',
        array('jquery'), // Dependency on jQuery is optional, but often useful
        '1.0',
        true
    );
}
add_action('wp_enqueue_scripts', 'lde_tabs_tut_assets');


/**
 * Shortcode handler: renders the tab buttons.
 *
 * Usage: [lde_tabs_tut config="Label 1:id-1, Label 2:id-2"]
 */
function lde_tabs_tut_shortcode($atts) {
    $atts = shortcode_atts(array(
        'config' => '', // Format: "Label:ID, Label:ID"
    ), $atts);

    if (empty($atts['config'])) return '';

    $pairs = explode(',', $atts['config']);
    $tabs = [];

    foreach ($pairs as $pair) {
        $parts = explode(':', sanitize_text_field(trim($pair)));
        if (count($parts) == 2) {
            $tabs[] = [
                'label' => trim($parts[0]),
                'id' => sanitize_html_class(trim($parts[1]))
            ];
        }
    }

    ob_start();
    ?>
    
    <div class="lde-tabs-tut-container">
        <?php foreach ($tabs as $index => $tab): ?>
            <button 
                class="lde-tab-tut-button <?php echo $index === 0 ? 'lde-active' : ''; ?>" 
                data-target="<?php echo esc_attr($tab['id']); ?>">
                <?php echo esc_html($tab['label']); ?>
            </button>
        <?php endforeach; ?>
    </div>
    <?php
    return ob_get_clean();
}
add_shortcode('lde_tabs_tut', 'lde_tabs_tut_shortcode');
/*
 * LDE Tabs Tutorial Plugin Stylesheet - Modern Aesthetic
 * Author: Les Ey
 */

/* --- Tab Controller Styling --- */
.lde-tabs-tut-container {
    display: flex;
    border-bottom: 2px solid #ddd;
    margin-bottom: 15px; /* FIX: Adds 15px gap between tab line and content */
}
.lde-tab-tut-button {
    /* Base style for all buttons */
    background-color: #f7f7f7; 
    border: 1px solid #ddd;
    border-bottom: none; 
    border-radius: 6px 6px 0 0; /* Rounded top corners */
    
    padding: 10px 18px;
    margin-right: 5px;
    margin-bottom: -2px; /* Pulls the button over the container border */
    
    cursor: pointer;
    font-size: 15px;
    font-weight: 500;
    color: #555;
    transition: all 0.2s ease;
}

/* Hover effect for inactive tabs */
.lde-tab-tut-button:hover:not(.lde-active) {
    background-color: #eee;
    color: #333;
}

/* Active tab state */
.lde-tab-tut-button.lde-active {
    background-color: #fff; 
    border-color: #ddd;
    border-bottom: 2px solid #fff; /* White line covers the container border line */
    
    color: #0073aa; 
    font-weight: 700;
}
.lde-tab-tut-button:focus {
    /* Accessibility focus styling */
    outline: 2px solid rgba(0, 115, 170, 0.5); 
    outline-offset: 1px;
}

/* --- Content Target Styling (CRITICAL) --- */
.lde-tab-tut-content {
    display: none; 
    
    /* Reset outer styling to prevent conflict with inner code block */
    padding: 0; 
    border: none;
    border-radius: 0;
    margin-top: 0; 
    margin-bottom: 0;
}

/* Specific styling to reset the default margin on the element *inside* the tab wrapper
   to ensure it respects the 8px margin from the container. */
.lde-tab-tut-content > * {
    margin-top: 0;
    margin-bottom: 0;
}
//
// LDE Tabs Tutorial Plugin JavaScript Logic
//

document.addEventListener("DOMContentLoaded", function() {
    const tabButtons = document.querySelectorAll(".lde-tab-tut-button");
    const contentSections = document.querySelectorAll(".lde-tab-tut-content");

    if (tabButtons.length === 0) return;

    // --- Core Logic Function ---
    function switchTab(targetId, clickedButton) {
        // 1. Hide all content targets with the common class
        contentSections.forEach(section => {
            // Only hide sections if they are present on the page
            if (section) section.style.display = 'none';
        });

        // 2. Show the specific target ID
        const targetElement = document.getElementById(targetId);
        if (targetElement) {
            targetElement.style.display = 'block';
        }

        // 3. Update active button class
        const container = clickedButton.closest('.lde-tabs-tut-container');
        if (container) {
            container.querySelectorAll('.lde-tab-tut-button').forEach(btn => {
                btn.classList.remove('lde-active');
            });
        }
        clickedButton.classList.add('lde-active');
    }

    // --- Add Event Listeners ---
    tabButtons.forEach(button => {
        button.addEventListener("click", function() {
            const targetId = this.getAttribute('data-target');
            if (targetId) {
                switchTab(targetId, this);
            }
        });
    });

    // --- Initial Load Initialization ---
    // Find the button marked active by PHP and trigger the switch function
    const activeOnLoad = document.querySelector(".lde-tab-tut-button.lde-active");
    if (activeOnLoad) {
        const initialTargetId = activeOnLoad.getAttribute('data-target');
        // Initial setup: Call switchTab, but pass a null element to prevent re-hiding if it's already hidden by CSS
        switchTab(initialTargetId, activeOnLoad); 
    } else if (contentSections.length > 0) {
        // Fallback: If no active button, ensure all content is hidden (CSS should cover this).
        contentSections.forEach(section => section.style.display = 'none');
    }
});

Download & Install

You can build the tutorial version yourself by copying the code above and adding the files to a zip folder called lde-tabs-tut-plugin.zip or download the full version here.

Here’s the download link for v0.9.1:

It is also available on GitHub https://github.com/Les-Ey/lde-tabs-plugin

See Easy Guide to Installing a Custom WordPress Plugin


Using the Plugin

Before implementing your tabs, remember that you can easily customize the plugin’s appearance using the built-in settings panel.

Note: For the tutorial version, see usage and limitations in the lde-tabs-tut-plugin.php file header.

The colors for the active tab, hover states, content background, and the padding/margins for the content area can all be adjusted in the WordPress admin:

  • Go to Settings -> LDE Tabs.
  • There, you can use the color pickers to match the tabs perfectly to your theme. You also have a Reset to Plugin Defaults button if you want to undo your changes.

Implementing the LDE Tabs Plugin is a simple three-step process that relies entirely on using the native WordPress Block Editor.

Step 1: Insert the Tab Controller Shortcode

The first step is to add the shortcode that generates your clickable tab buttons.

  • Add a Shortcode Block wherever you want the tabs to appear.
  • Enter the shortcode using the basic format: [lde_tabs config="Label:ID, Label:ID"].
  • Optional: Use the group attribute if you have more than one independent set of tabs on the same page.
Shortcode AttributeWhen to Use It
config="Label:ID,..."Mandatory for defining tabs and linking to content.
group="unique-name"Optional (defaults to set1). Mandatory if you use a second tab set on the same page (e.g., use group="set2").

Example Shortcodes:

  • Single Set: [lde_tabs config="PHP:php-sec, CSS:css-sec, JS:js-sec"]
  • Second Set on Same Page: [lde_tabs group="set2" config="TabA:content-a, TabB:content-b"]

Step 2: Prepare the Tab Content Structure

You need a container for all the content belonging to a single tab. This block will be the target of the corresponding tab button.

  • Add a Block (e.g., Code Block, Paragraph, or a reusable Group Block if your content is complex) immediately below the shortcode.
  • Add all the content (text, code, images, etc.) you want for your first tab inside this single container block.
  • Crucial: This single outer block is the element you will be linking to.

his step is critical: You must apply two key attributes to your content block to link it back to the shortcode controller and allow the JavaScript to control its visibility.

  1. Select the Content Block: Ensure the block containing all your tab content is selected in the editor.
  2. Open Advanced Panel: Go to the right-hand Settings Sidebar and scroll down to expand the Advanced panel.
  3. Set the ID (HTML Anchor): In the HTML Anchor field, type the target ID exactly as you used it in the shortcode’s config (e.g., php-sec).
  4. Set the Class (Additional CSS class(es)): In the Additional CSS class(es) field, type the required class that the plugin’s CSS and JavaScript rely on: lde-tab-content.
Settings Sidebar FieldValue to Enter
HTML AnchorYour unique ID (e.g., php-sec)
Additional CSS class(es)lde-tab-content

Repeat and Publish

Repeat Step 2 and Step 3 for every tab you defined in your shortcode. Ensure each content block has the class lde-tab-content and a unique, matching HTML Anchor.

When you view the published page, the JavaScript will automatically initialize the tabs, hiding all content blocks except the first tab’s content in each group!

Conclusion

The LDE Tabs Plugin provides a lightweight and efficient solution for displaying organized, toggleable content within the WordPress Block Editor. It achieves this by focusing on native Gutenberg functionality: you simply connect your content—contained within Group Blocks—to the shortcode via the built-in HTML Anchor and Additional CSS Class(es) fields.

While the WordPress ecosystem offers many excellent solutions, both free and paid, I am hope this specific, efficient tool will remain completely free for the community. You are encouraged to download, use, and modify the code under the standard GPL license.

Thank you for reading, and happy coding!

Got Questions?

Views: 189