I need to animate the shrink and expand transitions for subsets of elements in a nested set of divs. The expand works fine, but the shrink is broken.
I have a structured collection of items (say, squares for purposes here) that I want to display selectively and whose transitions I want to animate.
The structure is: collection > groups > rows > squares
In static layout,
- squares appear in horizontal rows;
- rows are gathered vertically in groups;
- a column of groups forms the collection.
Squares can be of varying sizes, so containers must adjust accordingly (no fixed heights or widths).
I have obtained a static layout that is just what I want.
The problem comes with animation. I want to hide various subsets of squares, rows and/or groups. Nearby items can look similar so it is difficult for users to tell just what is being added or subtracted, so I need a smooth animation so users can follow what is changing.
I am trying to do this with a CSS-animated shrink:
- A
shrinkMe
class marks all element that I will want to shrink/expand at the moment - CSS transition times are set for these
shrinkMe
elements - A
shrunken
class is defined whose CSS has all its size parameters set to 0 - To shrink or expand, jQuery adds or removes
the the
shrunken
class tag to the$('shrinkMe')
items, to animate items between the full and shrunken (=0) sizes
The un-shrink animated transition is exactly what I want. But the shrink animation does not work at all - contents spill out of containers along the way.
shrink = function(bool,nsec) {
$('.shrinkMe').css("transition", 'all ' + nsec+ 's');
if (bool) $('.shrinkMe').addClass('shrunk')
else $('.shrinkMe').removeClass('shrunk');
}
anim = function(secs) {
return 'all ' + secs + 's'
}
.controls {
display: inline-block;
vertical-align: top;
}
.collection {
display: inline;
text-align: center;
border: 2px solid black;
padding: 3px;
display: inline-block;
}
.group {
display: block;
margin: 2px;
border: 2px solid black;
padding: 3px;
}
.row {
display: block;
vertical-align: middle;
background: #0cc;
margin: 1px;
border: 2px solid black;
}
.sq {
display: inline-block;
background: white;
width: 20px;
height: 20px;
margin: 5px;
border: 2px solid black;
}
.lg {
width: 25px;
height: 25px;
}
.shrinkMe {
border-color: red;
}
.shrunk {
height: 0px;
width: 0px;
border-width: 0px;
padding: 0px;
margin: 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
<div class='controls'>
<button type='button' onclick='shrink(true,2)'>shrink reds </button>
<br>
<button type='button' onclick='shrink(false,2)'>unshrink reds </button>
</div>
<div class='collection'>
<div class='group'>
<div class='row '>
<div class='sq'></div>
<div class='sq'></div>
</div>
<div class='row shrinkMe'>
<div class='sq lg shrinkMe'></div>
<div class='sq shrinkMe'></div>
<div class='sq lg shrinkMe'></div>
</div>
</div>
<div class='group shrinkMe' id='group2'>
<div class='row shrinkMe' id='group2container2'>
<div class='sq shrinkMe'></div>
<div class='sq shrinkMe'></div>
</div>
<div class='row shrinkMe'>
<div class='sq shrinkMe'></div>
<div class='sq lg shrinkMe'></div>
<div class='sq shrinkMe'></div>
</div>
</div>
</div>
Among other things, I've tried using different explicit transition speeds, so containers shrink more slowly than their contents, but to no avail. If I set explicit heights and widths of the rows and groups, I can get a coordinated nested-shrink but it is ugly:
- It shrinks by squashing to the left side and;
- The final layouts can have empty spaces in them (e.g., when a row shrinks inside an unshrunk group, the fixed explicit group container height means there is now a hole where the row was).
What I want is to achieve is simple: a shrink animation that is the time-reverse of the nice clean un-shrink.
Here also is a jsfiddle showing the problem that additionally has buttons for trying separate timings of more deeply nested divs (which does not help...)
https://jsfiddle.net/furnas/dgq8yusy/
Any explanation of what is going wrong and suggestions on how to fix it?