How to Create Interactive Tabs in WordPress

Tabs are useful for closely related sections that visitors can switch between without leaving the page. This example separates Design, Build, and Launch details into three panels. It includes keyboard arrow navigation, a single selected tab in the normal tab sequence, and visible focus. It is not a substitute for separate pages when each topic needs its own URL and substantial content.

HTML + CSS + JSIntermediateNo external librariesUpdated 2026-10-09
✧ Live preview
You’ll build
Interactive Tabs in WordPress
Code required
HTML + CSS + JS
Installation
Theme and role dependent
On this pageBefore you startHow the tabs workInstall the component in WordPressCustomize content and stylingAdd or remove a tabTroubleshoot tab behaviorAccessibility and performanceFrequently asked questionsCheck your installation
YOUR CODE, READY TO CUSTOMIZE

Complete working code

The preview and download are generated from these same source files. The complete snippet requires permission to save inline styles and scripts.

<section class="iljs-demo iljs-tabs"><div role="tablist" aria-label="Project details"><button id="iljs-tab-1" role="tab" aria-selected="true" aria-controls="iljs-panel-1">Design</button><button id="iljs-tab-2" role="tab" aria-selected="false" aria-controls="iljs-panel-2" tabindex="-1">Build</button><button id="iljs-tab-3" role="tab" aria-selected="false" aria-controls="iljs-panel-3" tabindex="-1">Launch</button></div><div id="iljs-panel-1" role="tabpanel" aria-labelledby="iljs-tab-1" tabindex="0"><span>01 / START WITH AN IDEA</span><h2>Make room for possibility.</h2><p>Choose a direction, gather your content, and decide what visitors need.</p></div><div id="iljs-panel-2" role="tabpanel" aria-labelledby="iljs-tab-2" tabindex="0" hidden><span>02 / BRING IT TO LIFE</span><h2>Build one good thing.</h2><p>Work in small steps. Try your changes before publishing them.</p></div><div id="iljs-panel-3" role="tabpanel" aria-labelledby="iljs-tab-3" tabindex="0" hidden><span>03 / SHARE YOUR WORK</span><h2>Ready when you are.</h2><p>Check your links, keyboard controls, and narrow-screen layout before launch.</p></div></section>

Download standalone HTMLDownload source bundle

Before you start

Keep essential instructions available where visitors will find them. A tab interface hides inactive panels visually, so it should not bury an important warning. For independent questions whose answers can stay open together, the native FAQ accordion may be more suitable.

How the tabs work

The tablist contains three buttons with role="tab". Each button has a unique ID and aria-controls pointing to its corresponding panel. Each panel has role="tabpanel" and aria-labelledby pointing back to its tab. These relationships let assistive technology identify the control and the content it selects.

The first tab begins with aria-selected="true". The others have tabindex="-1", so pressing Tab enters the group through the selected control rather than visiting every inactive tab in sequence. Inactive panels use the hidden attribute, which removes their content from rendering and the ordinary focus sequence.

JavaScript gathers tabs and panels inside one .iljs-tabs root. The select function updates the selection state, tab indexes, and panel visibility in one pass. Arrow Left and Arrow Right wrap around the tab group; Home selects the first tab, and End selects the last. Selection follows focus because these small local panels do not require a network request to display.

Install the component in WordPress

  1. Add a Custom HTML block to a draft page and paste the markup. Keep the tablist before the panels and preserve the relationship attributes.
  2. Replace the three labels and each panel’s text. Do not change IDs in only one place: the matching aria-controls and aria-labelledby must change together.
  3. Install the CSS through an available Additional CSS interface or approved stylesheet. The custom CSS guide covers theme differences.
  4. Install the JavaScript using a permitted path. Read the JavaScript setup guide before embedding a script that your role might not be allowed to save.
  5. Save and inspect the front end. Test clicking every tab, keyboard arrows, Home, End, and tabbing from a selected tab into its panel.

The page-level structure can be used in block themes, classic themes, or an Elementor HTML widget when the account’s permissions allow it. WordPress 7.0’s JavaScript panel requires unfiltered_html; restricted roles or hosting may need an approved enqueue method. This component depends on JavaScript to expose all three panels through the supplied controls. If your installation cannot run the script, use ordinary headings and visible sections instead of leaving unreachable hidden content.

Customize content and styling

The tablist’s pale background separates controls from content. Selected tabs receive a white surface, a small shadow, and the accent color. Change --iljs-accent for selected text, and edit the list background if your brand needs a different palette. Check the inactive tab text contrast as well as the active control.

Panel padding is 32 pixels and the minimum height is 180 pixels. A minimum can reduce visible jumping for similar-length panels, but it does not clip longer content. Avoid replacing it with a fixed height when your actual text needs more space. Let the panel grow naturally on phones.

Add ordinary semantic content inside panels. A copy-to-clipboard component can work inside a panel because it initializes without relying on a measured width. An image comparison slider also uses a percentage-based layout. Test nested controls to ensure arrow keys on the tab group do not interfere with inputs inside a panel; this implementation listens only on the tabs themselves.

Add or remove a tab

To add a fourth tab, add one new button and one matching panel. Use unique IDs such as iljs-tab-4 and iljs-panel-4, and keep the tab and panel order aligned. Give the new tab aria-selected="false" and tabindex="-1"; give its panel hidden. The script automatically uses the number of tabs it finds.

To remove a tab, remove its matching panel too. A mismatch between the two arrays would leave selection behavior incomplete. When copying the entire component multiple times on one page, prefix every ID in the second instance with another unique value and update both relationship directions. Reusable classes are fine, but IDs cannot repeat. The WordPress class and ID guide helps with that distinction.

Do not turn the tab buttons into anchors with fake href="#" values. These controls change local interface state rather than navigate. If the content needs independent linkable pages, a navigation list of real anchors is a better model.

Troubleshoot tab behavior

Only Design is visible and nothing changes. The CSS and initial hidden states may have loaded without the script. Check whether WordPress stripped JavaScript or whether the installed file failed to load.

The wrong panel opens. Confirm the button and panel order match. Check the IDs and ARIA relationships, especially after copying the component or adding a tab.

Every panel is visible. A theme’s display rule may override the hidden state. Keep the explicit [role="tabpanel"][hidden] { display: none; } rule and inspect higher-specificity declarations.

Arrow navigation stops at the first or last tab. The supplied handler wraps using the actual tab count. Verify that a customization did not replace the key names or the modulo calculation.

Focus is invisible. Restore the shared :focus-visible outline. A selected background alone is not a focus indication, because selection and keyboard focus are related but distinct states.

Accessibility and performance

The control uses a conventional horizontal tab pattern. Arrow keys move within the group; Tab continues into the active panel and onward. There is no modal focus trap and no forced animation. Panels are already present in the HTML, so switching does not fetch content or send a visitor’s selection to a service.

Keep labels short enough for a narrow screen, but do not abbreviate them beyond recognition. If you need many tabs, consider another structure or a carefully designed horizontal scroll area. Test actual labels at 320 pixels and with larger text. Do not assume three sample words prove every possible content layout works.

Frequently asked questions

Can I show a tab by its URL hash?

This version does not synchronize tabs with the URL. Adding that behavior requires interpreting the hash and preserving correct state and focus. Use separate pages when direct linking is central to the content.

Does content load only when selected?

No. The panels are local HTML. That makes switching immediate, but it also means any images or embedded services need their own loading strategy.

Can tabs contain forms?

Yes, with careful focus and validation testing. Do not switch away from a panel automatically while someone is editing it, and ensure errors identify the relevant panel.

Check your installation

Click and keyboard-select every tab, inspect the panel relationships, and confirm no content becomes unreachable when your chosen script installation path fails. Keep a plain-section alternative for environments that cannot run the behavior.