Creating an Interactive Tabbed Interface with JavaScript

Creating an Interactive Tabbed Interface with JavaScript

Hey guys! In today’s article, we'll explore how to create a dynamic and interactive tabbed interface using the power of HTML, CSS, and JavaScript. We’ll also implement the spread operator that we discussed in our previous article in this article. In case you missed it, you can catch up on it here 👇🏽

Spread operator

Let’s dive right in😉

🧰 Prerequisites

  • Basic knowledge of HTML and CSS.

  • Fundamental knowledge of JavaScript (I will still explain everything).

🏚️ HTML Structure

First, Let's analyze the code before diving into the explanation 👇🏽

    <body>
    <div class="tabs">
      <ul class="tabs-header">
        <li class="default-tab">Introduction</li>
        <li>Features</li>
        <li>Documentation</li>
      </ul>
      <ul class="tabs-content">
        <li class="tab">
          <h2>Welcome to the Introduction</h2>
          <p>This tab provides an overview of our product.</p>
        </li>
        <li class="tab">
          <h2>Explore the Features</h2>
          <p>
            In this tab, you will discover the exciting features of our product.
          </p>
        </li>
        <li class="tab">
          <h2>Access the Documentation</h2>
          <p>
            Here, you can find detailed documentation on how to use our product.
          </p>
        </li>
      </ul>
    </div>
    <script src="script.js"></script>

From the code above, You’ll see that In the <body> section, we have a <div> element with the class "tabs" that acts as the parent container for our tabbed interface. Inside this container, there are two nested <ul> elements: one with the class "tabs-header" and another with the class "tabs-content."

The "tabs-header" <ul> contains three <li> elements, representing the tabs: "Introduction," "Features," and "Documentation." The first tab has an additional class of "default-tab" to indicate it as the default active tab.

The "tabs-content" <ul> also includes three <li> elements, each representing the content of the corresponding tab. These content sections contain <h2> headings and <p> paragraphs to provide relevant information for each tab.

💡 You can also change the <li> to <button> if you want to. Just have fun with it 😃

Before we move on to the CSS styling, Let’s see what we have so far 👇🏽

Wow, Look at how awesome it looks 😅. I am just kidding.

Now let’s make it look better.

🏡 CSS Styling

Next, let's see the CSS code that styles our Tabs 👇🏽

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;700&display=swap');

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: 'Poppins', sans-serif;
  font-size: 1rem;
  line-height: 1.5;
  background: #f8fafc;
  color: #333;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
}

ul {
  list-style: none;
}

h2 {
  margin-bottom: 0.3rem;
}

p {
  font-weight: 400;
}

.tabs-header {
  display: flex;
  justify-content: center;
  gap: 3rem;
  background: #333;
  color: #fff;
  padding: 1rem 3rem;
}

.tabs-header li {
  cursor: pointer;
  font-weight: 400;
}

.tabs-content {
  padding: 20px;
  border: 1px solid #333;
  font-weight: bold;
  background: #f4f4f4;
}

.tab {
  display: flex;
  flex-direction: column;
}

.active {
  color: orange;
  font-weight: 800;
}

The CSS code starts with an @import rule that imports the "Poppins" font family from Google Fonts. This ensures consistent and visually pleasing typography throughout the tabbed interface.

The remaining CSS styles target different elements of the tabbed interface, such as the body selector, which sets the font family, font size, background color, and centers the content vertically and horizontally.

The ul, h2, and p selectors define styles for unordered lists, headings, and paragraphs, respectively, ensuring proper formatting and typography within the tabbed interface.

The .tabs-header selector applies styles to the container of the tab headers, such as background color, text color, and padding. This helps distinguish the tab headers from the content sections.

The .tabs-content selector defines styles for the container of the tab content sections. It sets the padding, border, and background color, creating a clear visual separation between different tabs' content.

The .tab selector arranges the tab content sections in a column layout, ensuring proper alignment and spacing.

The .active selector modifies the appearance of the active tab header by changing the text color and font weight. This visual cue helps users identify the currently active tab.

Let’s see how the output looks 👇🏽

Looking really nice. But you’ll notice that the three contents are showing but we need only the first one to show. We can achieve that using CSS or JavaScript, But we’ll use the JavaScript approach in this article.

🏗️ JavaScript Code

This is the fun part of the project because we’ll be adding interactivity to the tabbed interface. Let's take a look at the code 👇🏽

const createTabs = (tabContainers) => {
  // Selecting header and content containers
  const headerContainer = document.querySelector('.tabs-header');
  const contentContainer = document.querySelector('.tabs-content');

  // Converting HTML collections to arrays
  const tabHeaders = [...headerContainer.children];
  const tabContents = [...contentContainer.children];

  // Hide all tab contents
  tabContents.forEach((content) => (content.style.display = 'none'));

  let currentTabIndex = -1;

  const setTab = (index) => {
    // Remove active class and hide previous tab content
    if (currentTabIndex > -1) {
      tabHeaders[currentTabIndex].classList.remove('active');
      tabContents[currentTabIndex].style.display = 'none';
    }

    // Add active class and display selected tab content
    tabHeaders[index].classList.add('active');
    tabContents[index].style.display = 'flex';

    // Update currentTabIndex
    currentTabIndex = index;
  };

  // Determine default tab index
  let defaultTabIndex = tabHeaders.findIndex((header) =>
    header.classList.contains('default-tab')
  );
  defaultTabIndex = defaultTabIndex === -1 ? 0 : defaultTabIndex;

  // Set default tab
  setTab(defaultTabIndex);

  // Add click event listeners to tab headers
  tabHeaders.forEach((header, index) => {
    header.addEventListener('click', () => {
      setTab(index);
    });
  });
};

// Select all tab containers and apply createTabs function
const tabContainers = [...document.querySelectorAll('.tabs')];
tabContainers.forEach(createTabs);

The code above begins by defining a function called createTabs that accepts an array of tab container elements as a parameter.

Inside the createTabs function, we selected the header and content containers by querying the DOM using their respective class names. It then converts the resulting HTML collections of tabHeaders and tabContents into regular arrays using the spread operator.

We then hide all tabContents by setting their display property to 'none'. This ensures that only the content of the active tab is initially visible.

The variable currentTabIndex is initialized to -1. This variable keeps track of the currently active tab.

The function setTab is defined to handle tab switching. It takes an index as an argument, representing the tab to be activated. Inside the function, it first checks if there is a currently active tab. If so, it removes the 'active' class from the corresponding header and hides the associated content section.

Next, it adds the 'active' class to the new tab header and displays the corresponding content section by setting its display property to 'flex'. Finally, it updates the currentTabIndex variable to the index of the newly activated tab.

We then determined the default tab index by finding the index of the header element with the class 'default-tab'. If no default tab is found, it defaults to index 0.

The default tab is then set using the setTab function with the default tab index as the argument.

We then added event listeners to each tab header using the forEach loop. When a header is clicked, the corresponding tab is activated by calling the setTab function with the header's index as the argument.

Finally, we selected all tab container elements and applies the createTabs function to each container using another forEach loop.

That’s all guys, Hope it makes sense.

Now let’s our output so far 👇🏽

Conclusion

Congrats on getting to the end of the article 🎉 🎉. I sincerely hope you've gained valuable insights along the way. I highly recommend writing out the code instead of simply copying and pasting it. This hands-on approach will deepen your understanding and allow you to explore modifications to achieve similar results. For instance, you can try replacing the spread operator in tabHeaders or tabContents with something like Array.from(). Remember, it's absolutely normal if you don't grasp everything immediately. You're not alone, and always keep in mind that PRACTICE is the key to mastery. Wishing you a fantastic weekend, and I’ll see you next week. 😃

##