What is the most effective way to switch between content in tabs using Bootstrap 5?

Can content in Bootstrap 5 tabs be toggled to close all tabs when clicking on an already open tab?

Bootstrap documentation

<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="62000d0d16111610031222574c514c50">[email protected]</a>/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f2909d9d868186809382b2c7dcc1dcc0">[email protected]</a>/dist/css/bootstrap.min.css" rel="stylesheet"/>
<ul class="nav nav-tabs" id="myTab" role="tablist">
  <li class="nav-item" role="presentation">
    <button class="nav-link" id="home-tab" data-bs-toggle="tab" data-bs-target="#home-tab-pane" type="button" role="tab" aria-controls="home-tab-pane" aria-selected="true">Home</button>
  </li>
  <li class="nav-item" role="presentation">
    <button class="nav-link" id="profile-tab" data-bs-toggle="tab" data-bs-target="#profile-tab-pane" type="button" role="tab" aria-controls="profile-tab-pane" aria-selected="false">Profile</button>
  </li>
  <li class="nav-item" role="presentation">
    <button class="nav-link" id="contact-tab" data-bs-toggle="tab" data-bs-target="#contact-tab-pane" type="button" role="tab" aria-controls="contact-tab-pane" aria-selected="false">Contact</button>
  </li>
</ul>
<div class="tab-content" id="myTabContent">
  <div class="tab-pane fade" id="home-tab-pane" role="tabpanel" aria-labelledby="home-tab" tabindex="0">Home content goes here</div>
  <div class="tab-pane fade" id="profile-tab-pane" role="tabpanel" aria-labelledby="profile-tab" tabindex="0">Profile content goes here</div>
  <div class="tab-pane fade" id="contact-tab-pane" role="tabpanel" aria-labelledby="contact-tab" tabindex="0">Contact content goes here</div>
</div>

View example on Jsfiddle

Answer №1

  1. Ensure to assign the attributes data-bs-toggle to collapse for tabs.
  2. Replace the classes tab-pane with collapse on the content.
  3. Add the attribute
    data-bs-parent="#myTabContent"
    to the content to allow for closing other content when one is opened.

<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="11737e7e65626563706151243f223f23">[email protected]</a>/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a1c3ceced5d2d5d3c0d1e1948f928f93">[email protected]</a>/dist/css/bootstrap.min.css" rel="stylesheet"/>
<ul class="nav nav-tabs" id="myTab" role="tablist">
  <li class="nav-item" role="presentation">
    <button class="nav-link" id="home-tab" data-bs-toggle="collapse" data-bs-target="#home-tab-pane" type="button" role="tab" aria-controls="home-tab-pane" aria-selected="true">Home</button>
  </li>
  <li class="nav-item" role="presentation">
    <button class="nav-link" id="profile-tab" data-bs-toggle="collapse" data-bs-target="#profile-tab-pane" type="button" role="tab" aria-controls="profile-tab-pane" aria-selected="false">Profile</button>
  </li>
  <li class="nav-item" role="presentation">
    <button class="nav-link" id="contact-tab" data-bs-toggle="collapse" data-bs-target="#contact-tab-pane" type="button" role="tab" aria-controls="contact-tab-pane" aria-selected="false">Contact</button>
  </li>
</ul>
<div class="tab-content" id="myTabContent">
  <div class="collapse" id="home-tab-pane" data-bs-parent="#myTabContent" role="tabpanel" aria-labelledby="home-tab" tabindex="0">Home: [Dummy text for illustration purposes]</div>
  <div class="collapse" id="profile-tab-pane" data-bs-parent="#myTabContent" role="tabpanel" aria-labelledby="profile-tab" tabindex="0">Profile: [Dummy text for illustration purposes]</div>
  <div class="collapse" id="contact-tab-pane" data-bs-parent="#myTabContent" role="tabpanel" aria-labelledby="contact-tab" tabindex="0">Contact: [Dummy text for illustration purposes]</div>
</div>

Answer №2

For a quick and simplistic fix, my approach would involve implementing a click listener to toggle the display of tabs (removing the active show class from the tab) when the same link is clicked. Additionally, I would toggle the button's active class and remove the focus outline from the button:

  let currentTab = '';

  function toggleTabContent(event) {

    const clickedButton = event.target;

    if (clickedButton.getAttribute('id') === currentTab) {
      const selectedTab = document.querySelector(clickedButton.getAttribute('data-bs-target'));
      
      selectedTab.classList.toggle('show');
      
      if (!selectedTab.classList.contains('show')) {
        clickedButton.blur();
        clickedButton.classList.toggle('active');
        selectedTab.classList.toggle('active');
      }
    }
    currentTab = clickedButton.getAttribute('id');
  }

  document.querySelectorAll('#myTabsContainer button').forEach(element => element.addEventListener('click', toggleTabContent));

Demo:

<script src="https://cdn.example.com/bootstrap.bundle.min.js"></script>
<link href="https://cdn.example.com/bootstrap.min.css" rel="stylesheet" />
<ul class="nav nav-tabs" id="myTabsContainer" role="tablist">
  <li class="nav-item" role="presentation">
    <button class="nav-link" id="home-tab" data-bs-toggle="tab" data-bs-target="#home-tab-pane" type="button" role="tab" aria-controls="home-tab-pane" aria-selected="true">Home</button>
  </li>
  <li class="nav-item" role="presentation">
    <button class="nav-link" id="profile-tab" data-bs-toggle="tab" data-bs-target="#profile-tab-pane" type="button" role="tab" aria-controls="profile-tab-pane" aria-selected="false">Profile</button>
  </li>
  <li class="nav-item" role="presentation">
    <button class="nav-link" id="contact-tab" data-bs-toggle="tab" data-bs-target="#contact-tab-pane" type="button" role="tab" aria-controls="contact-tab-pane" aria-selected="false">Contact</button>
  </li>
</ul>
<div class="tab-content" id="myTabsContentArea">
  <div class="tab-pane fade" id="home-tab-pane" role="tabpanel" aria-labelledby="home-tab" tabindex="0">Home: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ultricies neque eu turpis dapibus, nec hendrerit nibh malesuada. Proin imperdiet feugiat lacus, non volutpat urna sagittis nec. Etiam auctor nibh nec rhoncus fermentum. Fusce laoreet massa sem, a gravida lorem laoreet nec. Etiam justo tellus, ultricies nec mi a, lobortis tempor nulla.</div>
  <div class="tab-pane fade" id="profile-tab-pane" role="tabpanel" aria-labelledby="profile-tab" tabindex="0">Profile: Phasellus molestie ornare eros non dapibus. Curabitur sed massa a mi tristique lobortis. Mauris rhoncus aliquam ante, vel convallis tellus scelerisque id. Nam vel tincidunt elit, ac convallis ipsum. Vivamus id nisi sit amet dui pellentesque tristique. Nunc lacinia, felis sit amet tincidunt dapibus, erat nisi fermentum massa, nec fringilla sem nulla ultrices risus.</div>
  <div class="tab-pane fade" id="contact-tab-pane" role="tabpanel" aria-labelledby="contact-tab" tabindex="0">Contact: Integer consectetur non felis nec tempus. Fusce mauris ligula, sodales nec neque id, aliquam faucibus urna. Quisque ut sem sapien. Vestibulum congue, odio non bibendum bibendum, lorem sapien ultricies nunc, ut luctus elit dui ac ante. In mattis volutpat ipsum eu vehicula. Ut vel ornare massa. Nam mollis leo at erat mattis, vel interdum neque faucibus. Nullam fermentum accumsan erat, quis fermentum elit vestibulum at.</div>
</div>


<script>
  let currentTab = '';

  function toggleTabContent(event) {

    const clickedButton = event.target;

    if (clickedButton.getAttribute('id') === currentTab) {
      const selectedTab = document.querySelector(clickedButton.getAttribute('data-bs-target'));
      
      selectedTab.classList.toggle('show');
      
      if (!selectedTab.classList.contains('show')) {
        clickedButton.blur();
        clickedButton.classList.toggle('active');
        selectedTab.classList.toggle('active');
      }
    }
    currentTab = clickedButton.getAttribute('id');
  }

  document.querySelectorAll('#myTabsContainer button').forEach(element => element.addEventListener('click', toggleTabContent));
</script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Several queries for directions on Google Maps are resulting in the same response being returned for all requests

I've been experimenting with the Google Maps Directions service to retrieve three different travel methods for the same route (driving, walking, and bicycling). Despite successfully iterating through the array of methods and setting them in the respec ...

What is the best way to apply CSS styles to a child div element in Next.js?

I'm currently working on enhancing the menu bar for a website project. Utilizing nextjs for my application I am aiming to customize the look of the anchor tag, however, encountering some issues with it not rendering correctly. Here is a snippet of ...

I find the JSX syntax to be quite perplexing

While examining some code, I came across the following: const cardSource = { beginDrag(props) { return { text: props.text }; } }; When working with JSX block code or building objects, I usually use {}. The cardSource variable in this co ...

Using AngularJS to bind radio buttons to ng-model

Here is a snippet of my HTML code where I attempted to bind the "formFriendsAll" scope to the ng-model. <form ng-submit="submitForm()" > <div class="col-sm-3"> <div class="form-group"> <label>Which Persons to show?< ...

Is it possible to make the v-toolbar-title fixed within a v-navigation-drawer using Vuetify?

Can the <v-toolbar-title> be fixed within a <v-navigation-drawer>? <v-card class="d-inline-block elevation-12"> <v-navigation-drawer hide-overlay permanent stateless height="440" value="true"> <v-toolbar color="whi ...

Why does the getComputedStyle function return null for IE11 and Edge when using Kendo React Grid within a Popout window, while it works fine in Chrome, Opera, and Firefox?

Check out my stackblitz demo where I am experimenting with rendering a Kendo React Grid inside a popout window using the react-popout-component. The demo runs smoothly in Chrome, Opera, and Firefox, but encounters issues in Edge and IE11 due to a null valu ...

The React.js Redux reducer fails to add the item to the state

I'm just starting to learn about React.js and Redux. Currently, I am working on creating a basic shopping cart application. https://i.stack.imgur.com/BfvMY.png My goal is to have an item (such as a banana) added to the cart when clicked. (This sho ...

What are the steps for translating multiple meshes in various directions using three.js?

One issue that I am encountering involves creating 100 meshes with a for loop, all of which have the same position coordinates of 0,0,0. I would like these meshes to move in different directions individually. Below is my code for creating the 100 meshes: ...

Determine the location of an image with the help of Jquery

I'm currently working on finding the position of an image with Jquery. The issue I am facing is that it only provides me with the initial position of the image when the document was loaded. $(".frog").click(function(){ alert($(".frog").position() ...

Creating seamless shading effects using three.js with Blender integration

When I import a Blender scene into a three.js environment, the curved faces appear flat. Is there a method to ensure that these surfaces remain smooth as intended? Despite calculating vertex normals and activating the smoothShaded option, the issue persis ...

Using either AngularJS's simple .then method or the $q service to handle asynchronous requests

I'm trying to understand the distinction between AngularJS $q service and simply using .then() after an asynchronous request. For example, using .then(): function InboxService($http) { this.getEmails = function getEmails() { return $http.get(& ...

What is the JavaScript event object all about?

Can you provide an example of what is considered an 'event object' in the context of this program? Is it, for instance, the <p> element if a <p> is clicked, or the <html> element if <html> is clicked? Or is the event objec ...

Problems with the Chosen property of MenuItem within Material-UI

The MenuItem's "selected" property does not seem to be functioning correctly within the Select component. For reference, please visit https://codesandbox.io/s/9j8z661lny I have attempted to use comparison with the Id, and even tried using selected={t ...

Is there a way to incorporate a loading spinner into a MaterialUI DataTable without having to specify a fixed height for the parent component?

Currently, I am using a MaterialUI DataTable with the following setup: <div style = {{height: 300}}> <DataGrid loading={true} getRowHeight={() => "auto"} getEstimatedRowHeight={() => 250} ...

Guide to retrieving IDs of images on a canvas during drag and drop functionality

I've developed a finite state machine drawing tool that includes drag-and-drop functionality for different images, such as states and arrows. Each arrow creates a div tag for the transition, with unique ids assigned to every state, arrow, and transiti ...

"Using axios and async/await in VUE.JS to perform multiple asynchronous GET

Perhaps this is a somewhat basic inquiry, as I am still learning the ropes of vue.js and javascript. Please bear with me if my question is not well-articulated or if the solution is straightforward... I am facing an issue where I need to retrieve data from ...

Choose the option in real-time with Jquery

I'm currently developing a dynamic HTML for Select Option as seen below: item += "<td class='ddl' style='width:40%;'>"; item += "<select>" item += " <option id='list' name='selector' value=" + se ...

Switching background images with Javascript through hovering

I am currently working on implementing a background changer feature from removed after edits into my personal blog, which is only stored on my local computer and not uploaded to the internet. However, I am unsure of what JavaScript code I need to achieve t ...

Guide to presenting a personalized date format in an Angular table by utilizing the gantt-tooltip attribute

How can I customize the date format displayed in the tooltip to only show the month and day (e.g. Sep 01) within an Angular Gantt table? Currently, the date is being shown in the default format "MMM DD, HH:mm". Can anyone assist me in resolving this issue ...

There are multiple sets of radio buttons within nested ng-repeats, but only the final group displays the selected value

I am having an issue with updating a form that contains multiple radio buttons based on data retrieved from an API. The challenge is that only the last set of radio buttons displays the value correctly. Below is the code snippet I am using (angular bracket ...