As always, thanks a lot for reading!
[ad_1]
In this tutorial, we’ll learn how to convert WordPress child pages into shareable navigation tabs. However, unlike common tabs where visitors remain on the same page upon clicking them and just the associated panel appears, ours will behave like menu links and force the page to reload.
Tabs are a popular way of organizing and categorizing groups of content. For example, on the Airbnb site, tabs behave like filters that allow visitors to select homes grouped under a specific tag like Amazing views, Beachfront, etc.
In the past, I’ve shown you how to build a custom JavaScript-based responsive tab component. In addition, some years ago, I went through the process of customizing Bootstrap tabs by giving each tab an identifiable URL, making their content more navigable and shareable.
Today, I’ll show you how to simulate this functionality in WordPress with child pages.
Each tab will represent a child page with a panel of the page’s content. This behavior is ideal when your design requires a tabbed interface, yet for SEO purposes, you need clean shareable URLs. Another scenario arises when each tab panel contains complex content and not just some text, and you want to avoid having all the content on one page—something that can slow the admin page.
Here’s an introductory video that showcases the expected behavior:
Our WordPress Tabbed Interface
Consider the following hierarchical structure where we have one parent page and four child ones:
Each child page will have a layout like this:
Regarding the page elements:
- At the top, there will be breadcrumbs where only the first level (home page) will be clickable.
- Then, we’ll have the tabs that will represent the child pages. The current page will be the active tab.
- Below the tabs, we’ll have the tab panel that will show the content of the current page.
Depending on the tabs we have, we need to think about the tabbed interface on mobile screens. A quick solution is to show a vertical scrollbar if the tabs’ width is larger than the device’s width.
All child pages will share the same custom page template.
Implementation
For the implementation part, I’ll work with my usual custom Playground theme. I’ll use the files from a previous tutorial and only update two things—these are the ones that interest you if you plan to embed this technique in your projects:
- First and most importantly, I’ll add the custom
tabs.php
file—the page template of all child pages and - secondly, I’ll update the
style.css
file with the tab styles.
For your convenience, as usual, all the theme assets will be available on a GitHub repo.
Inside the custom template, we’ll do the following:
- Create the breadcrumbs that will be three levels deep. The first level, which will be clickable, will link to the home page. The second one will show the title of the parent page (“Company” in my case). It won’t be clickable as we won’t have any layout for the parent page. The third one will show the title of the current page.
- Grab the child pages of the parent of the current page. You can always customize the order of your pages by using the
sort_column
key inside the arguments array of theget_pages()
function. Default sorting is via their post title in ascending order which works in our example. - Loop through them and generate the tabs. To determine the active tab, still inside the loop, we’ll compare the URL of the current page with the URL of the looped element. If they match, we’ll denote the active tab using the
active
class. - Print the current page’s content that will behave as the active tab panel.
Here’s the required PHP code:
1 | <?php
|
2 | /* Template Name: Tabs Page */
|
3 | get_header(); |
4 | |
5 | $parent_id = wp_get_post_parent_id(); |
6 | $parent_title = get_the_title( $parent_id ); |
7 | $child_pages = get_pages( |
8 | array( |
9 | 'parent' => $parent_id, |
10 | )
|
11 | );
|
12 | ?>
|
13 | |
14 | <main class="site-main"> |
15 | <?php
|
16 | if ( have_posts() ) : |
17 | while ( have_posts() ) : |
18 | the_post(); |
19 | ?>
|
20 | <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>> |
21 | <section class="section-with-tabs"> |
22 | <div class="container container-sm"> |
23 | <?php
|
24 | if ( ! empty( $child_pages ) ) : |
25 | /*BREADCRUMBS*/
|
26 | ?>
|
27 | <ul class="breadcrumbs"> |
28 | <li class="breadcrumb"> |
29 | <a href="<?php echo esc_url( home_url( '/' ) ); ?>"> |
30 | <?php esc_html_e( 'Home', 'playground' ); ?> |
31 | </a>
|
32 | </li>
|
33 | <li class="breadcrumb"> |
34 | <?php echo esc_html( $parent_title ); ?> |
35 | </li>
|
36 | <li class="breadcrumb"> |
37 | <?php the_title(); ?> |
38 | </li>
|
39 | </ul>
|
40 | |
41 | <?php /*TABS*/ ?> |
42 | <div class="tabs-wrapper"> |
43 | <ul class="tabs"> |
44 | <?php
|
45 | foreach ( $child_pages as $key => $child_page ) : |
46 | $child_page_id = $child_page->ID; |
47 | $child_page_link = get_page_link( $child_page_id ); |
48 | $active = get_permalink() === $child_page_link ? ' active' : ''; |
49 | ?>
|
50 | <li class="tab<?php echo $active; ?>"> |
51 | <a class="tab-link" href="<?php echo esc_url( $child_page_link ); ?>"> |
52 | <?php echo esc_html( $child_page->post_title ); ?> |
53 | </a>
|
54 | </li>
|
55 | <?php endforeach; ?> |
56 | </ul>
|
57 | </div>
|
58 | <?php endif; ?> |
59 | </div>
|
60 | </section>
|
61 | |
62 | <?php /*TAB CONTENT*/ ?> |
63 | <section class="section-with-content"> |
64 | <div class="container container-sm"> |
65 | <?php the_content(); ?> |
66 | </div>
|
67 | </section>
|
68 | </article>
|
69 | <?php
|
70 | endwhile; |
71 | endif; |
72 | ?>
|
73 | </main>
|
74 | |
75 | <?php
|
76 | get_footer(); |
And the associated styles:
1 | /*CUSTOM VARIABLES HERE*/
|
2 | |
3 | .section-with-tabs .breadcrumbs { |
4 | padding: 0; |
5 | margin: 0 0 20px; |
6 | list-style: none; |
7 | display: flex; |
8 | gap: 20px; |
9 | font-size: 14px; |
10 | color: var(--darkgray); |
11 | }
|
12 | |
13 | .section-with-tabs .breadcrumbs .breadcrumb { |
14 | position: relative; |
15 | }
|
16 | |
17 | .section-with-tabs .breadcrumbs .breadcrumb:not(:first-child)::before { |
18 | content: "/"; |
19 | position: absolute; |
20 | top: 50%; |
21 | left: -13px; |
22 | transform: translateY(-50%); |
23 | }
|
24 | |
25 | .section-with-tabs .tabs-wrapper { |
26 | white-space: nowrap; |
27 | padding-bottom: 10px; |
28 | overflow-x: auto; |
29 | }
|
30 | |
31 | .section-with-tabs .tabs-wrapper::-webkit-scrollbar { |
32 | height: 8px; |
33 | }
|
34 | |
35 | .section-with-tabs .tabs-wrapper::-webkit-scrollbar-thumb, |
36 | .section-with-tabs .tabs-wrapper::-webkit-scrollbar-track { |
37 | border-radius: 6px; |
38 | }
|
39 | |
40 | .section-with-tabs .tabs-wrapper::-webkit-scrollbar-thumb { |
41 | background: var(--darkpink); |
42 | }
|
43 | |
44 | .section-with-tabs .tabs-wrapper::-webkit-scrollbar-track { |
45 | background: var(--lightgray); |
46 | }
|
47 | |
48 | .section-with-tabs .tabs { |
49 | padding: 0; |
50 | margin: 0; |
51 | list-style: none; |
52 | display: flex; |
53 | }
|
54 | |
55 | .section-with-tabs .tabs .tab { |
56 | flex-grow: 1; |
57 | }
|
58 | |
59 | .section-with-tabs .tabs .tab-link { |
60 | display: block; |
61 | text-decoration: none; |
62 | font-weight: bold; |
63 | font-size: 18px; |
64 | padding: 5px; |
65 | color: var(--darkgray); |
66 | min-width: 120px; |
67 | border-bottom: 2px solid var(--lightgray); |
68 | transition: all 0.2s; |
69 | }
|
70 | |
71 | .section-with-tabs .tabs .tab.active .tab-link, |
72 | .section-with-tabs .tabs .tab .tab-link:hover { |
73 | color: var(--darkpink); |
74 | border-color: var(--darkpink); |
75 | }
|
76 | |
77 | .section-with-content { |
78 | text-align: left; |
79 | margin-top: 60px; |
80 | }
|
Conclusion
Here’s a final screenshot of what you’ve built!
During this tutorial, we learned how to transform WordPress child pages into navigation tabs. This technique works great if you plan to have a tabbed navigation with clean, shareable URLs.
In an upcoming tutorial, I’ll show you how to navigate between child pages with next/previous links. Stay tuned!
[ad_2]