ABC
ABC

Reputation: 763

How to proportion collapsible items in a flexbox

I have a 3-panel page built with flexbox. It looks like this:

enter image description here

If I expand the second section, the first section will collapse and it'll look like this:

enter image description here

This is great, but I want it so that the first section to not automatically close when the second section opens up. Ideally, both the first and second section take up the same amount of height (50/50).

<ul>
  <li class="active">
    <div class="wrap">
      <a href="#">open1</a>
        <div>text 1</div>    
    </div>
  </li>
  <li>
    <div class="wrap">
      <a href="#">open2</a>
        <div>text 2</div>    
    </div>
  </li>
  <li>
    <div class="wrap">
      <a href="#">open3</a>
      <div>text 3</div>
    </div>
  </li>
</ul>
* {
  box-sizing: border-box;
}
html, body {
  height: 100%;
  margin: 0;
}
ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  height: 100%;
  flex-direction: column;
}

ul li {
  background:gray;
  padding:10px 30px;
  border-top: 2px solid #fff0ed;
}
ul li:first-child{
  border-top: none;
}

ul a {
  background: green;
  display: block;
  padding: 5px;
}

ul .wrap {
  background: #000;
  display: flex;
  flex-direction: column;
  width: 100%;
  min-height: 100%;
  color: #fff;
}

ul .wrap div {
  display: none;
  padding: 20px;
}

ul li.active {
  display: flex;
  flex: 1 1 auto;
}

ul li.active .wrap div {
  display: block;
}

How could I achieve this?

CODEPEN here

Upvotes: 2

Views: 692

Answers (2)

Nenad Vracar
Nenad Vracar

Reputation: 122047

You could use toggleClass that will remove class on the clicked element if it already exists otherwise it will add the class.

$('li').on('click', function() {
  $(this).toggleClass('active')
})
* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
  margin: 0;
}

ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  height: 100%;
  flex-direction: column;
}

ul li {
  background: gray;
  padding: 10px 30px;
  border-top: 2px solid #fff0ed;
}

ul li:first-child {
  border-top: none;
}

ul a {
  background: green;
  display: block;
  padding: 5px;
}

ul .wrap {
  background: #000;
  display: flex;
  flex-direction: column;
  width: 100%;
  min-height: 100%;
  color: #fff;
}

ul .wrap div {
  display: none;
  padding: 20px;
}

ul li.active {
  display: flex;
  flex: 1 1 auto;
}

ul li.active .wrap div {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
  <li class="active">
    <div class="wrap">
      <a href="#">open1</a>
      <div>text 1</div>
    </div>
  </li>
  <li>
    <div class="wrap">
      <a href="#">open2</a>
      <div>text 2</div>
    </div>
  </li>
  <li>
    <div class="wrap">
      <a href="#">open3</a>
      <div>text 3</div>
    </div>
  </li>
</ul>

Upvotes: 1

alcoceba
alcoceba

Reputation: 423

You can control it using Javascript:

$('li').each(function(){
  var $this = $(this);
  
  $this.on('click', function(){
    if ($this.hasClass('active')) $this.removeClass('active');
    else $this.addClass('active');
  });
});

Shorter:

 $('li').each(function(){
  var $this = $(this);
  
  $this.on('click', function(){
    $this[$this.hasClass('active') ? 'removeClass' : 'addClass' ]('active');
  });
});

Upvotes: 1

Related Questions