bootstrap-4css-transitionsbootstrap-tabs

Smoothly transition tab activation in Bootstrap 4


I have created a page with bootstrap tabs at the bottom of the page.

The tabs themselves are of varying heights and I found it jarring how the browser just snaps to a lesser page height as I activate a tab with smaller overall height (and the page was scrolled to far down).

After trying half a dozen suggestions I ultimately arrived at a solution where I make all tabs same height, but I still wanted at least some transition between them and opted for opacity.

See my fiddle.

HTML

<div class="consistent-height">
  <ul class="nav nav-tabs">
    <li class="nav-item">
      <a class="nav-link active" data-toggle="tab" href="#tab1">tab 1</a>
    </li>
    <li class="nav-item">
      <a class="nav-link" data-toggle="tab" href="#tab2">tab 2</a>
    </li>
  </ul>
  <div class="tab-content">
    <img class="logo" alt="logo" src="/static/images/logo_icon.svg">
    <div id="tab1" class="tab-pane active">
      tra la la
    </div>
    <div id="tab2" class="tab-pane fade">
      juhuhu
    </div>
  </div>
</div>

CSS

.logo {
  float:  right;
  height: 20em;
}

.tab-content {
  padding-top: 2em;
}

.consistent-height .tab-content {
  position: relative;
  transition: opacity .5s ease 0s;
}

.consistent-height .tab-content > .tab-pane {
  display:    block; /* undo "display: none;" */
  opacity:    0;
  position:   absolute;
  width:      calc(100% - 15em);
}

.consistent-height .tab-content > .active {
  opacity: 100%;
}

This works almost good, but there's an additional delay when I move from "tab 2" to "tab 1" (vs immediate transition when activating "tab 2"). I suspect that the delay is caused by overlapping transitions, but I don't understand them well enough to understand what it is that's bothering the browser here.

What am I doing wrong?


Solution

  • The .fade class is applying additional css styling related to the opacity. only the second tab has the .fade class, hence why it feels inconsistent.

    If you add .fade to both, you will notice the delay on both transitions.

    not sure why you added .fade, it seems to be meant to be used with Modals. you might have defined it yourself and where unaware that bootstrap also has a fade class

    .tab-content {
      padding-top: 2em;
    }
    
    .consistent-height .tab-content {
      position: relative;
    }
    
    .consistent-height .tab-content>.tab-pane {
      display: block;
      opacity: 0;
      position: absolute;
      width: calc(100% - 15em);
      transition: opacity .5s ease 0s;
    }
    
    .consistent-height .tab-content>.active {
      opacity: 100%;
    }
    <h1> no fade </h1>
    <div class="consistent-height">
      <ul class="nav nav-tabs">
        <li class="nav-item">
          <a class="nav-link active" data-toggle="tab" href="#tab1">tab 1</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" data-toggle="tab" href="#tab2">tab 2</a>
        </li>
      </ul>
      <div class="tab-content">
        <div id="tab1" class="tab-pane active">
          tab 1 content
        </div>
        <div id="tab2" class="tab-pane">
          tab 2 content
        </div>
      </div>
    </div>
    
    <h1><br> with fade </h1>
    <div class="consistent-height">
      <ul class="nav nav-tabs">
        <li class="nav-item">
          <a class="nav-link active" data-toggle="tab" href="#tab3">tab 3</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" data-toggle="tab" href="#tab4">tab 4</a>
        </li>
      </ul>
      <div class="tab-content">
        <div id="tab3" class="tab-pane fade active">
          tab 3 content
        </div>
        <div id="tab4" class="tab-pane fade">
          tab 4 content
        </div>
      </div>
    </div>
    
    
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-fQybjgWLrvvRgtW6bFlB7jaZrFsaBXjsOMm/tB9LTS58ONXgqbR9W8oWht/amnpF" crossorigin="anonymous"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">