Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS transitions parent to match a childs final height

Jade example

div.parent
    div.child1
    div.child2

Child1 is visible on load, based on a click, Child1 will become hidden and Child2 will become visible. Another click can reverse this.

When hiding / un-hiding the children should transition via height change - from 100% to 0% and visa versa. The parent should transition also via a height change to match the newly visible child.

Visually child1 will appear to "roll up" while child2 is "rolling down", parent will extend or contract depending on final size.

Can this be done with CSS transitions?

like image 753
iss42 Avatar asked Oct 19 '25 14:10

iss42


1 Answers

It can be done ONLY if you know previously the final height of the children.

var button = document.querySelector('button');
var parent = document.querySelector('.parent');

button.onclick = function(){
  parent.classList.toggle('toggle');
}
.child1,
.child2 {
  height: 100px;
  background: #faa;
  overflow: hidden;
  transition: all .3s;
}

.child2 {
  background: #aff;
  height: 0;
}

.toggle .child1 {
  height: 0;
}

.toggle .child2 {
  height: 100px;
}
<div class="parent">
  <div class="child1">Something here</div>
  <div class="child2">Or here</div>
</div>
<button>Click me</button>

You can also do it even if you don't know the final height, but it's really too hacky to be worth implementing in pure CSS. It has something to do with adding a transition and a max-height of X where X >>> height. But it has an issue when folding into a small thing, as there's a delay caused by 100 * (X - height) % of the time.

Based on the comments (and for the kicks), you can also do it without Javascript, but I don't really recommend it because it's not so clear (JS is normally the controller):

.child1,
.child2 {
  height: 100px;
  background: #faa;
  overflow: hidden;
  transition: all .3s;
  cursor: pointer;
}

.child2 {
  background: #aff;
  height: 0;
}

.toggle {
  display: none;
}

:checked ~ .child1 {
  height: 0;
}

:checked ~ .child2 {
  height: 100px;
}
<label>
  <input class="toggle" type="checkbox" name="el" />
  <div class="child1">Click me</div>
  <div class="child2">Now me</div>
</label>
like image 59
Francisco Presencia Avatar answered Oct 21 '25 03:10

Francisco Presencia