Tablist with interactive Bootstrap navigation on both the left and right sides

How can I create interactive navigation tabs with two tabs aligned to the left ("First" and "Second") and one tab aligned to the right ("More")? Currently, I can switch between "First" and "Second" without any issues. However, once I select "More," I can switch back to "First" or "Second" but not back to "More" as it seems to be deactivated.

Is there a way to treat both tab lists as a single entity, or should I only use one tab list with two tabs on the left and one tab on the right?

Link to the JS Fiddle

<!doctype html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
        integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    <title>Site</title>
</head>

<body>
    <div class="container">
        <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
            <a class="navbar-brand" href="#">Site</a>
            <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup"
                aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
                <div class="navbar-nav nav" id="nav-tab" role="tablist">
                    <a class="nav-item nav-link active" id="nav-first-tab" data-toggle="tab" href="#nav-first"
                        role="tab" aria-controls="nav-first" aria-selected="true">First</a>
                    <a class="nav-item nav-link" id="nav-second-tab" data-toggle="tab" href="#nav-second" role="tab"
                        aria-controls="nav-second" aria-selected="false">Second</a>
                </div>

                <div class="navbar-nav nav ml-auto" id="nav-tab-right" role="tablist">
                    <a class="nav-item nav-link" id="nav-more-tab" data-toggle="tab" href="#nav-more" role="tab"
                        aria-controls="nav-more" aria-selected="false">More</a>
                </div>
            </div>
        </nav>

        <div class="tab-content" id="nav-tabContent">
            <!--First tab-->
            <div class="tab-pane show active" id="nav-first" role="tabpanel" aria-labelledby="nav-first-tab">
                <p>First!</p>
            </div>

            <!--Second tab-->
            <div class="tab-pane" id="nav-second" role="tabpanel" aria-labelledby="nav-second-tab">
                <p>Second!</p>
            </div>

            <!--More tab-->
            <div class="tab-pane" id="nav-more" role="tabpanel" aria-labelledby="nav-more-tab">
                <p>More!</p>
            </div>
        </div>
    </div>

    <script src="https://code.jquery.com/jquery-3.4.1.min.js"
        integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
        integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous">
    </script>
</body>

</html>

Answer №1

While Bootstrap default JavaScript may not seem like pure "magic," it does require certain assumptions to function properly. One key assumption is that the provided markup is respected.

In your case, this assumption is not being met. You are trying to control the tablist from two parent containers with the role of "tablist" instead of just one. As a result, you will need to manually handle the deselection process:

$(function() {
  $('#navbarNavAltMarkup').on('click', '[role="tab"]', function(e) {
    $('[role="tab"].active', $(this).closest('.navbar-collapse')).each((i, el) => {
      $(el).removeClass('active show');
      $(el).attr('aria-selected', 'false');
    })
  })
});

To see this in action:

$(function() {
  $('#navbarNavAltMarkup').on('click', '[role="tab"]', function(e) {
    $('[role="tab"].active', $(this).closest('.navbar-collapse')).each((i, el) => {
      $(el).removeClass('active show');
      $(el).attr('aria-selected', 'false');
    })
  })
});
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>

<div class="container">
  <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
    <a class="navbar-brand" href="#">Site</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
      <div class="navbar-nav nav" id="nav-tab" role="tablist">
        <a class="nav-item nav-link active" id="nav-first-tab" data-toggle="tab" href="#nav-first" role="tab" aria-controls="nav-first" aria-selected="true">First</a>
        <a class="nav-item nav-link" id="nav-second-tab" data-toggle="tab" href="#nav-second" role="tab" aria-controls="nav-second" aria-selected="false">Second</a>
      </div>

      <div class="navbar-nav nav ml-auto" id="nav-tab-right" role="tablist">
        <a class="nav-item nav-link" id="nav-more-tab" data-toggle="tab" href="#nav-more" role="tab" aria-controls="nav-more" aria-selected="false">More</a>
      </div>
    </div>
  </nav>

  <div class="tab-content" id="nav-tabContent">
    <div class="tab-pane show active" id="nav-first" role="tabpanel" aria-labelledby="nav-first-tab">
      <p>First!</p>
    </div>

    <div class="tab-pane" id="nav-second" role="tabpanel" aria-labelledby="nav-second-tab">
      <p>Second!</p>
    </div>

    <div class="tab-pane" id="nav-more" role="tabpanel" aria-labelledby="nav-more-tab">
      <p>More!</p>
    </div>
  </div>
</div>


Another solution is to consolidate all tab controls within the same tablist parent and use custom CSS for positioning as needed:

@media(min-width: 992px) {
  #navbarNavAltMarkup .navbar-nav:first-child{
    flex-grow: 1;
  }
  #navbarNavAltMarkup .nav-item:last-child{
    margin-left: auto;
  }
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>

<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
  <a class="navbar-brand" href="#">Site</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
    <div class="navbar-nav nav" id="nav-tab" role="tablist">
      <a class="nav-item nav-link active" id="nav-first-tab" data-toggle="tab" href="#nav-first" role="tab" aria-controls="nav-first" aria-selected="true">First</a>
      <a class="nav-item nav-link" id="nav-second-tab" data-toggle="tab" href="#nav-second" role="tab" aria-controls="nav-second" aria-selected="false">Second</a>
      <a class="nav-item nav-link" id="nav-more-tab" data-toggle="tab" href="#nav-more" role="tab" aria-controls="nav-more" aria-selected="false">More</a>
    </div>
  </div>
</nav>


Upon further investigation, it appears that Bootstrap 4's implementation may not be as advanced as expected. Despite attempting to fix the issue by removing the role attribute from each .nav element and placing it on a common parent, the solution did not work as anticipated.

Delving into Bootstrap's source code, it is evident that they use NAV_LIST_GROUP: '.nav, .list-group' as selectors instead of [role="tablist"]. This design choice is puzzling, as using role would align better with the purpose of the attribute for screen readers.

In my opinion, the role attribute should have been utilized, as it clearly conveys the role of the elements for accessibility purposes. By relying on role attributes, users who rely on screen readers can navigate the content more efficiently. Omitting or removing role attributes could disrupt this functionality.

Answer №2

After some exploration, I stumbled upon a potential solution which involves injecting a snippet of javascript code. This code strategically assigns specific classes and attributes, effectively overruling the default behavior.

$('a[data-toggle="tab"]').on('show.bs.tab', function () {
    $('#nav-tab').children().removeClass('active');
    $('#nav-tab').children().removeClass('show');
    $('#nav-tab').children().attr('aria-selected', 'false');
    $('#nav-tab-right').children().removeClass('active');
    $('#nav-tab-right').children().removeClass('show');
    $('#nav-tab-right').children().attr('aria-selected', 'false');
});

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

Printed pages featuring neatly organized two-column div layout

Forgive me if this question has already been asked, but I need some guidance: I am designing reports using HTML and CSS which are then converted into PDF format. The report requires a two-column layout on most pages, so I am using: <div class="two_col ...

Content escapes its parent container and seamlessly transitions to the following element

I am facing an issue with the layout of my element, which includes an image and text centered inside a parent container. Whenever I try adding more elements below the existing image and text, the green text with a red border overflows the current parent . ...

Language translation API specifically designed to convert text content excluding any HTML formatting

I have a dilemma with translating text content in an HTML file into multiple languages based on user input. To accomplish this, I am utilizing the Microsoft Translator AJAX interface. The structure of my HTML file looks something like this; <h1>< ...

The concept of nested labels: defining conditions for displaying specific sections of a label

Let's say I have a label that contains the following text: <label>This is a text. This is another text.</label> Is there a way to indicate that the second sentence should only be visible when a boolean value is true? For example: <la ...

I'm attempting to arrange the movieCards in a horizontal row, but they keep stacking up vertically instead

I have created a movie list component with different attributes in the div section to display the cards in a row. However, all the cards are currently aligned in a column. Should I use flex or grid to achieve the desired layout? If so, how can I implement ...

Add a specific CSS class to a div element depending on the status of a checkbox

Is there a way to dynamically append data based on the selected items in a checkbox table? I want to be able to add multiple or single items by clicking the add button. The key is to avoid appending duplicate data that already exists in the view. Any sugge ...

The Transform feature doesn't seem to be functioning as expected within the Bootstrap

I was experimenting with creating a simple transform transition animation using css and js, so I wrote the following code: (test page) <!DOCTYPE html> <html> <head> <style type="text/css"> *{ ...

All elements on my webpage are enhanced with a CSS filter

I have a button centered on my page, but the CSS filter I applied to the HTML tag is also affecting the button. How can I prevent this from happening? HTML <body> <div class="button"> <a href="#">START EXPERIENCE</a> ...

Tips for updating sass import files as the body class changes

Is there a way to dynamically change the SCSS file with color variables based on the changing body class? For example, if my HTML includes: <body class="custom"> ... </body> I would like to load in style.scss: @import 'custom&a ...

Hide the div when hovering occurs

I need a way to hide the 'sample' div when hovering over it and then show it again when the mouse moves away $('.secmenu').hover(function() { $('.sample').css('opacity', '0'); if ($('.secmenu&a ...

Ways to trigger javascript following each ajax or complete request

I have a jQuery function that attaches a click event to specific elements, as shown below. $(".alert-message .close").click(function(e) { $(this).parent().fadeTo(200, 0, function() { $(this).slideUp(300); }); e.preventDefault(); }) ...

The overflow:hidden property does not seem to be effective for controlling the display of the

I'm attempting to construct a carousel using a ul element where the li items act as blocks within the ul container. However, I have encountered difficulties with two different approaches where the overflow property does not behave as expected. Approa ...

Place a div on top of a table

I am facing a challenge with table rows and divs. The height of the table row is set to 100px, while divs can be up to 200px. I want the div to overlay the table and cover the bottom row if it exceeds the row's height. Currently, I have achieved this ...

Mobile device causing issues with sticky footer functionality

Can anyone help me troubleshoot an issue with my sticky/floating bottom footer on a calorie calculator? It works fine on desktop but not on mobile. Any ideas what might be causing the problem? HTML: <footer class="footer"> <div class="summar ...

Bootstrap 4 modal experiencing issues with the form end tag functionality

Currently, I am facing an issue while attempting to incorporate a confirmation delete feature using a Bootstrap 4 modal in my Laravel project. The problem arises when the modal is opened, and the submit button fails to function. Upon inspecting the browser ...

Adjusting the heights of various divs as a percentage to fill the containing parent div

Is it possible for child divs to adjust their height automatically based on a percentage within a parent div with set max dimensions using CSS? HTML: <div id="parent"> <div id="top"></div> <div id="bottom"></div> < ...

Having trouble making class changes with ng-class

I am attempting to change the direction of the arrow in my checkbox by utilizing two classes with the assistance of ng-class. Unfortunately, it is not producing the desired outcome. Below is my code: Note: The angularJS CDN has already been incorporated. ...

Blocking users on a PHP social networking platform

I'm in the process of developing a social networking platform and I am currently working on adding a feature that allows users to block other users. However, I am facing challenges when it comes to implementing this feature. In my database, there is ...

Problem arising from implementing background and relative positioning in html and css

Encountering an issue with html and css. Today, attempted to create a page with a large background image for the first time. Utilizing the foundation framework, but facing a challenge. Foundation is an adaptive framework, and when resizing the browser, a ...

Tips for Passing On Parent tabindex Value to Children

Is there a way to propagate a parent's tabindex value to all of its children without individually setting tabindex for each child? Here is an example code snippet: <div id="app"> <div tabindex="2" class="parent-sec ...