How to animate toggling of table rows?
As table
row
/cell
don't respect a height
smaller than its content we need to use an inner div
, we can't animate display
and we can't animate a height
set to auto
, so I here show a solution using max-height
.
The trick is to give max-height
a value high enough to enable the highest content.
$('button').on('click', function() {
$('tr:nth-child(2)').toggleClass('active');
});
table {
border-collapse: collapse;
}
tr {
background: #eee;
border-bottom: 1px solid #fff;
}
tr, td {
padding: 0;
}
tr td div {
max-height: 0;
padding: 0 10px;
box-sizing: border-box;
overflow: hidden;
transition: max-height 0.3s, padding 0.3s;
}
tr.active td div {
max-height: 100px;
padding: 10px 10px;
transition: max-height 0.6s, padding 0.6s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<button type="button">Toggle</button>
<table>
<tbody>
<tr class="active">
<td><div>Row 1</div></td>
<td><div>...</div></td>
<td><div>...</div></td>
</tr>
<tr>
<td><div>Row 2</div></td>
<td><div>...</div></td>
<td><div>...</div></td>
</tr>
<tr class="active">
<td><div>Row 3</div></td>
<td><div>...</div></td>
<td><div>...</div></td>
</tr>
</tbody>
</table>
Using CSS transition and class toggle to show/hide table rows
best way to do this is indeed to play with height and opacity.
But you can't set height on table elements (tr/td)
so here is an example on how to do it with only CSS
#expand {
/* hide the checkbox */
display: none
}
label {
/* style as a button (you can't use button inside label with for attribute) */
padding: 2px 5px;
border: 1px solid rgba(0,0,0,.2);
border-radius: 5px;
font-size: .7rem;
cursor: pointer;
}
table {
border-spacing: 0;
border-collapse: collapse;
}
table tr:nth-child(n+4)>td {
padding: 0;
}
table tr:nth-child(n+4)>td>div {
opacity: 0;
max-height: 0;
transition: all 250ms ease-in;
}
#expand:checked + table tr:nth-child(n+4)>td {
padding: 1px;
/* default */
}
#expand:checked + table tr:nth-child(n+4)>td>div {
opacity: 1;
/* try to use something just slightly above the true height */
max-height: 20px;
overflow: hidden;
transition-timing-function: ease-out;
}
<input type="checkbox" id="expand"/>
<table id="table">
<tbody>
<tr>
<td>
<div>Row 1</div>
</td>
</tr>
<tr>
<td>
<div>Row 2</div>
</td>
</tr>
<tr>
<td>
<div>Row 3</div>
</td>
</tr>
<tr>
<td>
<div>Row 4</div>
</td>
</tr>
<tr>
<td>
<div>Row 5</div>
</td>
</tr>
<tr>
<td>
<div>Row 6</div>
</td>
</tr>
<tr>
<td>
<div>Row 7</div>
</td>
</tr>
<tr>
<td>
<div>Row 8</div>
</td>
</tr>
<tr>
<td>
<div>Row 9</div>
</td>
</tr>
<tr>
<td>
<div>Row 10</div>
</td>
</tr>
</tbody>
</table>
<br/>
<label for="expand">Toggle</label>
Collapse entire table on click with animation
You don't really need to do it with keyframe
animation.
You could do it just by adding a transition
rule to the table
element, like this:
table {
height: 100%;
display: block;
overflow: hidden;
transition: height 2s ease-in;
}
.collapsed {
height: 40px;
}
What this does, is tell the browser to transition the height
of the table
from 100% to 40px and vice cersa over a duration of 2s with an ease-in
function
For more info you can read the entry about the transition property at MDN
Cheers
UPDATE:
In your current setup I suppose the parent of the table
element does not have a strictly defined height.
The way the percentage based height works is like this: The element gets the 100% of its parent height.
However when you do not specify a height for the parent, be it in px
, em
, rem
, vh
or what have you, the child with height: 100%
is like having height: auto
. Reference
And here is the actual problem: You cannot transition from auto
to any other value, like %
, px
etc.
You can only transition from one defined value (!== auto
) to any other defined value. e.g. from px
to rem
, etc
And this is why your transition is not working.
See this fiddle
I made. Play with the #cont
element's height and see what happens.
So, in short: You will either have to give a strict height to your table, or, if you want to keep it percentage based, give a strict height to its parent element.
Vue - how to animate table row change
You could either look at transitioning the state as @craig_h suggests or perhaps just set up a regular javascript event that watches for animation end.
To utilise the second method you could add a new param changed: false
to each rows data, then set this to true when it is changed. This could then add a class to the row of 'changed'. Then have your CSS fire an animation when the row has the 'changed' class. Now all you need to do is listen for the 'animationend' event on that row and reset the changed param to false. Something like:
html - row element
<table>
<tr
ref="rows"
:class="{ changed: row.changed }"
v-for="(row, index) in rows">
<td><input v-model="row.title" type="text"></td>
<td>
<button @click="saveRowEdits(index)">save</button>
</td>
...
component
data () {
return {
rows: [
{ title: 'foo', changed: false },
{ title: 'bar', changed: false },
],
...
}
},
methods: {
saveRowEdits (index) {
// get the rows DOM el
const row = this.$refs.rows[index]
// watch for animationend
const callback = () => {
row.removeEventListener("animationend", callback);
this.rows[index].changed = false
}
row.addEventListener("animationend", callback, false)
// update param
this.rows[index].changed = true
},
...
CSS
row.changed {
animation: changed-row 1s ...
How can I animate a table row with a single column that spans multiple columns?
Nevermind. I figured it out. It has to do with the display
CSS property. Angular's ngShow
directive applies display: none
to the element when it hides it. This property would make the collapse animation not work at all. To get around that I applied display: block !important
to the animation selectors (I've done this many times in the past so I didn't think twice about it). Table rows are not displayed with display: block
, they need to be set to display: table-row !important
.
Once I changed my animation rules to this:
.animate-slide-down.ng-hide-add,
.animate-slide-down.ng-hide-remove.ng-hide-remove-active {
transition: 1s ease-out all;
transform: scale(1);
transform-origin: right;
line-height: 1.42857;
display: table-row !important;
}
.animate-slide-down.ng-hide-remove,
.animate-slide-down.ng-hide-add.ng-hide-add-active {
transition: 1s ease-out all;
transform: scale(0);
transform-origin: left;
line-height: 0;
display: table-row !important;
}
That solved the issue :)
Make an animation for collapsing tr with Bootstrap
The answer that was given wasn't actually providing the correct solution. It was a solution, but when you need to keep the tr
and td
elements this solution is more complete
The fact is that there is no way in bootstrap to animate tr
td
elements.
What you can do is instead of toggling the tr
or td
is create a div
or span
element in which you are going to add all of your content and then there animate the element.
As you can see it looks the same as if you had an actual table
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript" ></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" type="text/javascript" ></script>
<table class="table">
<tr class="content-row" id="content_1">
<td><a id="more_1" class="more" role="button" data-toggle="collapse" href="#additional_row1" aria-expanded="false" aria-controls="collapseExample">More</a>
</td>
</tr>
<tr>
<td class="additional-row-td">
<div class="collapse additional-row" id="additional_row1">Content</div>
</td>
</tr>
</table>
How to Use slideDown (or show) function on a table row?
Animations are not supported on table rows.
From "Learning jQuery" by Chaffer and Swedberg
Table rows present particular
obstacles to animation, since browsers
use different values (table-row and
block) for their visible display
property. The .hide() and .show()
methods, without animation, are always
safe to use with table rows. As of
jQuery version 1.1.3, .fadeIn() and
.fadeOut() can be used as well.
You can wrap your td contents in a div and use the slideDown on that. You need to decide if the animation is worth the extra markup.
Related Topics
Google Webfont Conflict with Local Font
How to Recreate Perspective-Origin Effect by Transforming Child Elements
Css3 Animation and Background-Image in Firefox
Why Doesn't Justify-Content: Center Work in Ie
Does IE9 Not Support Display: Inline-Flex at All
Why Does Width/Height Work on an Inline Img Element
Ie10/11 Uses Transition:-Webkit-Transform
CSS Alternative for Display:Box for Ie and Opera
Fieldset Firefox Overflow CSS Fix
How to Draw a Diagonal Line Using CSS3
Change Body Bgcolor on Hovering a Div, Using CSS Only
Difference Between Relative and Absolute
Do Values in CSS Attribute Selector Values Need to Be Quoted
Absolutely Positioning with Flexbox in Safari
Svg: Why Does External CSS Override Inline Style for Text
Using a Percentage Margin in CSS But Want a Minimum Margin in Pixels