skip to Main Content

I’m trying to use CSS/HTML to create a multi-panel widget where users can advance through the different panels. Ideally the next button rests below the content, and doesn’t move.

To support this, I’d like to make it so that the panels are always the same height (even if one had more content than the other). I’ve tried using grid to force these to the same height, but if I use display: none then the height of the grid doesn’t account for those not displayed elements. If I used visibility: hidden then the hidden panels still take up space in the DOM, but just don’t show anything.

$('#next-button-display').click(function() {
  $('#first-display').toggleClass('none');
  $('#second-display').toggleClass('none');
});

$('#next-button-vis').click(function() {
  $('#first-vis').toggleClass('hidden');
  $('#second-vis').toggleClass('hidden');
});
.container {
  background-color: blue;
  padding: 10px;
  display: grid;
  grid-auto-rows: 1fr;
}

.first {
  background-color: purple;
}

.second {
  background-color: yellow;
}

.none {
  display: none;
}

.hidden {
  visibility: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>

<h1>Using display</h1>
<div class="container">
  <div class="first" id="first-display">
    panel one
  </div>
  <div class="second none" id="second-display">
    panel two<br>
    which has two lines
  </div>
</div>
<input type="button" id="next-button-display" value="Next button" />

<h1>Using visibility</h1>
<div class="container">
  <div class="first" id="first-vis">
    panel one
  </div>
  <div class="second hidden" id="second-vis">
    panel two<br>
    which has two lines
  </div>
</div>
<input type="button" id="next-button-vis" value="Next button" />

Any ideas for making a reactive solution to this problem?

2

Answers


  1. Use a container with overflow: hidden to contain the entire thing. We will flex (or grid) the slides in one line, which then we can slide (translateX) to the correct location.

    var index = 0
    var slider = document.querySelector(".slider")
    var length = document.querySelectorAll(".slider .slide").length;
    
    function showSlide(index) {
      slider.style.transform = `translateX(-${index * 100}%)`;
    }
    
    document.querySelector("#next-button-display").addEventListener('click', function(ev) {
      showSlide(++index % length)
    })
    
    document.querySelector("#prev-button-display").addEventListener('click', function(ev) {
      showSlide((--index % length + length) % length)
    })
    .container {
      background-color: blue;
      padding: 10px;
      position: relative;
    }
    
    .inner-container-for-padding {
      overflow: hidden;
    }
    
    .slider {
      display: flex;
      transform: translateX(0);
      /* optional */
      transition: transform 0.3s ease-in-out;
    }
    
    .slide {
      flex-grow: 0;
      width: 100%;
      flex-shrink: 0;
      background: lightblue;
    }
    
    .first {
      background-color: purple;
    }
    
    .second {
      background-color: yellow;
    }
    <div class="container">
      <div class="inner-container-for-padding">
        <div class="slider">
          <div class="slide first" id="first-display">
            panel one
          </div>
          <div class="slide second " id="second-display">
            panel two<br> which has two lines
          </div>
    
          <div class="slide " id="another">
            panel three
          </div>
        </div>
      </div>
    </div>
    <input type="button" id="prev-button-display" value="Prev button" />
    <input type="button" id="next-button-display" value="Next button" />
    Login or Signup to reply.
  2. Keep the use of visibility but place all the items above each other.

    $('#next-button-vis').click(function() {
      $('#first-vis').toggleClass('hidden');
      $('#second-vis').toggleClass('hidden');
    });
    .container {
      background-color: blue;
      padding: 10px;
      display: grid;
    }
    .container > * {
     grid-area: 1/1; /* all the items in the same area */
     
    }
    .hidden {
      visibility: hidden;
    }
    
    .first {
      background-color: purple;
    }
    
    .second {
      background-color: yellow;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    
    <h1>Using visibility</h1>
    <div class="container">
      <div class="first" id="first-vis">
        panel one
      </div>
      <div class="second hidden" id="second-vis">
        panel two<br>
        which has two lines
      </div>
    </div>
    <input type="button" id="next-button-vis" value="Next button" />
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search