Reputation: 23530
On one part of my page I'm using css3 transitions to show/hide some divs with a nice sliding effect
.service_status {
max-height: 0;
-webkit-transition: max-height 1s ease-in-out;
-moz-transition: max-height 1s ease-in-out;
-ms-transition: max-height 1s ease-in-out;
-o-transition: max-height 1s ease-in-out;
transition: max-height 1s ease-in-out;
}
.service_status.open {
max-height: 500px;
-webkit-transition: max-height 1s ease-in-out;
-moz-transition: max-height 1s ease-in-out;
-ms-transition: max-height 1s ease-in-out;
-o-transition: max-height 1s ease-in-out;
transition: max-height 1s ease-in-out;
}
I'd like to use the same technique on some table rows but max-height and height aren't having any effect (due to the CSS specs for tables I guess). Is there a way I can show/hide table rows with an animation using just CSS3 transitions and no js?
Upvotes: 28
Views: 66050
Reputation: 403
IMHO This achieves smooth 'Do it all' solution. It does not require extra HTML tags (unless non-div blocks are in table) and handles all tricky situations known to me (even border-collapse: separate).
It is based on 'line-height' solution of @Tim Schoch and 'div max-height' solution of @Vitox. All explanations are in CSS comments. On reuse, please set all three transition times and make sure the preset max-height is save for your table cells.
tr.Collapsible.Collapsed { /* hide row reminder on end of transition */
transition-delay: 2020ms;
visibility: collapse;
}
tr.Collapsible td {
transition: all 2000ms linear;
line-height: 140%; /* % or UoM required for good transition */
}
tr.Collapsible.Collapsed td { /* disappear cell in all its aspect (blocks resist) */
line-height: 0%; /* TD ignores height, line-height works (except blocks) */
padding-top: 0;
padding-bottom: 0;
border-top-color: rgba(0, 0, 0, 0); /* disappear border gradually (transparency works) */
border-bottom-color: rgba(0, 0, 0, 0);
opacity: 0; /* lines overlapping is neutralized by disappearing text */
}
tr.Collapsible td > div { /* reduces blocks in collapsible cells */
transition: max-height 2000ms ease-in;
max-height: 10rem; /* make sure to be height enough !!! */
overflow: hidden;
}
tr.Collapsible.Collapsed td > div {
max-height: 0rem;
transition-timing-function: cubic-bezier(0, 0.8, 0, 0.8); /* fast on the unused max-height (stackoverflow.com/a/27787456/3158048) */
}
/* just example desing */
table {
border-collapse: collapse; /* works on separate as well */
}
td, th {
border: 2px solid teal;
width: 10rem;
padding: 0.5rem;
margin: 1rem;
}
tr:nth-child(even) {
background-color: #f2f2f2;
}
.Image {
display: inline-block;
background-image: linear-gradient(orange, cyan);
height: 3rem;
width: 3rem;
float: left;
}
<button onclick="$('.Collapsible').toggleClass('Collapsed');">Expand / collapse</button>
<table>
<tr>
<th>Column 1</th>
<th>Column 2</th>
</tr>
<tr class="Collapsible">
<td>Hide hide ipsum</td>
<td>Hide hide ipsum</td>
</tr>
<tr>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
</tr>
<tr class="Collapsible">
<td>Hide hide ipsum</td>
<td>
<div> <!-- onlyone div added because of the image -->
<span class="Image"></span>
Hide image Hide image
</div>
</td>
</tr>
<tr class="Collapsible">
<td>Hide hide ipsum Hide hide ipsum Hide hide ipsum Hide hide ipsum</td>
<td>Hide hide ipsum</td>
</tr>
<tr>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
</tr>
</table>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Upvotes: 4
Reputation: 18595
Line Height
: Here you go.
var doc = document;
var myElements = doc.querySelectorAll("[data-row='047384']");
if(myElements.length > 0){
myElements[0].addEventListener("click", function(){
showRows(myElements);
});
}
function showRows(elements){
for (var i = 0; i < elements.length; i++) {
if(elements[i].tagName.toLowerCase() !== 'button'){
elements[i].classList.toggle('show');
}
}
}
.table-part-row{
line-height:0;
transition: 1s;
opacity: 0;
}
.table-part-row.show {
line-height:1em;
opacity: 1;
}
<br>
<table>
<tr>
<th></th>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
</tr>
<tr data-row="047384">
<td><button data-row="047384">👓</button></td>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr class="table-part-row" data-row="047384">
<td></td>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr class="table-part-row" data-row="047384">
<td></td>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
</table>
Upvotes: 3
Reputation: 1
Add an animation on table rows, for example :
@keyframes show-row {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
And apply it like this :
animation: show-row .5s forwards;
Upvotes: -4
Reputation: 6454
I found one way to hide a table row with css that works for plain text without adding those nasty div's. It's not the "does all, fixes all" solution but you might want to give it a try if you're only dealing with text in your tables.
(It might work for other content too, but I haven't tested that)
// just used to toggle the hide class - use what every you fancy
$('button').click(function(){ $('.toggle').toggleClass('hide'); });
td {
opacity: 1;
padding: 10px;
line-height: 20px;
transition: all 0.2s ease-in-out;
}
.hide td {
opacity: 0;
line-height: 0px;
padding: 0 10px;
}
/* just some basic setup */
table {
border-collapse: collapse;
}
td {
background: #f1f1f1;
}
tr:nth-child(odd) td {
background: #f9f9f9;
}
<button>Toggle Table Row</button>
<br /><br />
<table>
<tr>
<td>foo</td>
</tr>
<tr class="toggle">
<td>Hide Me!</td>
</tr>
<tr>
<td>foo</td>
</tr>
</table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Upvotes: 4
Reputation: 1
I just came over same thing my solution was to use div in cell as well, but to animate I've used inner div and margin-bottom instead of max-height. Snipped would be:
html:
<tr><td colspan="7">
<div class="content">
<div class="amin">
multi line text
</div>
</div>
</td></tr>
css:
.content {
overflow: hidden:
margin: 0;
float: left;
}
.anim {
margin-bottom: -50%; /*use calc() to whatever suits you*/
transition: all 5s;
}
.content:hover anim {
margin-bottom: 0;
}
I've tested in FF only.
Upvotes: 0
Reputation: 4424
Update:
In fact my previous answer DOES ANSWER the question! But not absolutely explicitly. It's like: "Hey, the idea is here, just apply it wherever you want". I thought that the essence of the solution was clear, and anybody would be able to use it... But any way, I will expose the whole idea, in the most clear way I can, and also will apply the solution to a simple table (since OP don't shown any structure).
Solution:
Short Version:
Using a Div to wrapper the content into the cell, we are able to use max-height property, and also the max-height transition. With a custom transition curve, we can "mask off" the delay of using a high max-height.
Demo here: http://jsfiddle.net/1rnc9bbm/4/
Long Version:
The whole problem is that a table-cell's height is the minimum to fit its content, and table-row's height is the minimum height required for all cells (so, the height of the table-row is the minimum height required by its tallest cell).
From W3 (About Table-Cells Height):
In CSS 2.1, the height of a cell box is the minimum height required by the content.
From W3 (About Table-Rowss Height):
The height of a 'table-row' element's box is calculated once the user agent has all the cells in the row available: it is the maximum of the row's computed 'height', the computed 'height' of each cell in the row, and the minimum height (MIN) required by the cells.
Under these circumstances, our only choice is restrict the height indirectly using inner markup, normally a div element. Because a Div element respect a max-height, it will stretch our content, and our table-cell will also respect the "div's max-height", because this is all the required height it needs.
The problem with max-height transition is only a delay, caused by how the transition is calculated. In a table, usually you display a dynamic content that have dynamic and unpredictable length (which becomes table-cell height), so We don't know the precise max-height that our table will need to exactly fit the expanded content. Thus, We need to set a higher max-height, that will be more than the needed by some cells. When it happens, our transition is calculated wrong (based on the max-height and not in total height that will be shown/animated), and animation becomes weird and imprecise. To show a nice and smooth transition for user, I found a brilliant solution using a custom transition curve. More details about this problem and its solution are at the end of this answer.
Well, we have our "max-height respectful element", a smooth transition for our max-height animation, and our table... Now is time to put everything together:
Html:
<table>
<tr>
<td>
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris ac lorem ante. Vestibulum quis magna pretium, lacinia arcu at, condimentum odio. Ut ultrices tempor metus, sit amet tristique nibh vestibulum in. Pellentesque vel velit eget purus mollis placerat sed sit amet enim. Sed efficitur orci sapien, ac laoreet erat fringilla sodales.
</div>
</td>
</tr>
</table>
Css:
table{
border: 1px solid #ddd;
}
div{
background-color: #ddd;
width: 400px;
overflow: hidden;
-webkit-transition: max-height 1.5s cubic-bezier(0, 1.05, 0, 1);
-moz-transition: max-height 1.5s cubic-bezier(0, 1.05, 0, 1);
transition: max-height 1.5s ease cubic-bezier(0, 1.05, 0, 1);
max-height: 38px;
}
div:hover{
-webkit-transition: max-height 2s ease;
-moz-transition: max-height 2s ease;
transition: max-height 2s ease;
max-height: 400px;
}
Simple demo here (the code shown above): http://jsfiddle.net/1rnc9bbm/3/ , and a more complete (and common) table demo here: http://jsfiddle.net/1rnc9bbm/4/
I don't think that the downvotes were fair, but I agree that this version now is a lot more complete, and does answer in a explicitly way the OP's question. If you have any questions, or points that want me to clarify, you don't need to downvote (please), just ask/comment above. I'll be very happy to help if I can.
Obs: OP don't provided a Html, neither details about the table He want's to expand, so my whole solution is based in the usually table use.
Previous (Original) Answer:
I just answered this exacly situation in another question here. And in my specific case, I needed to do exactly what You said. I have a table, and want to expand a table row when user hovers it.
The same answer applies to your question:
https://stackoverflow.com/a/27773588/3395460
Linked Answer (Smooth Transitions with Higher Max-Height value than needs by container):
As pointed by @maskacovnik, it'll be a more complete (and integral) answer if it also contains the code of my first answer, and also the code that explains part of the solution of my updated answer. Here is it:
[...] I needed to show mode details of a product description inside a cell-table when user hovers the cell. Without user hovering, only the maximum of 2 lines of description are shown. Once user hovers it, all lines (text can be since 1 to 8 lines, dynamic and unpredictable length) must be show with some kind of height animation.
I come to the same dilemma, and choose to use the max-height transition (setting a high max-height, which I was sure that will not cut my text), because this approach appears to me to be the cleanest solution to animate the height.
But I couldn't be satisfied with the delay on the "slide up" animation, just like You. That's when I found a commentary about transition curve here: http://css3.bradshawenterprises.com/animating_height/ .
The Idea of this guy is brilliant, but just this solution alone "cut-off" the effect of "slide down" animation. So thinking a little I just come to a final solution.
So here is my solution using the Rhys's Idea (Guy of link above):
Slide Down Animation (Hover), with a "smooth grow", and Slide Up Animation without (virtually) "delay":
div {
background-color: #ddd;
width: 400px;
overflow: hidden;
-webkit-transition: max-height 1.5s cubic-bezier(0, 1.05, 0, 1);
-moz-transition: max-height 1.5s cubic-bezier(0, 1.05, 0, 1);
transition: max-height 1.5s cubic-bezier(0, 1.05, 0, 1);
max-height: 38px;
}
div:hover {
-webkit-transition: max-height 2s ease;
-moz-transition: max-height 2s ease;
transition: max-height 2s ease;
max-height: 400px;
}
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris ac lorem ante. Vestibulum quis magna pretium, lacinia arcu at, condimentum odio. Ut ultrices tempor metus, sit amet tristique nibh vestibulum in. Pellentesque vel velit eget purus mollis
placerat sed sit amet enim. Sed efficitur orci sapien, ac laoreet erat fringilla sodales.
</div>
This is a perfect (in my opinion) solution for menu, descriptions and everything that isn't extremely unpredictable, but as You pointed before, there is the need to set up a high max-height, and may cut-off a surprisingly tall dynamic content. In this specific situation, I'll use jQuery/JavaScript to animate the height instead. Since the update of the content will be done using some sort of JavaScript already, I can't see any harm using a Js approach to animation.
Hope I helped!
Upvotes: 21
Reputation: 13396
You cannot apply height transitions to <td>
or <tr>
elements. However, if you can wrap the contents of the <td>
elements with a <div>
, you can apply CSS transitions to the <div>
elements.
HTML:
<tr>
<td><div>Contents</div></td>
<td><div>Contents</div></td>
</tr>
CSS:
tr div {
max-height:0;
transition: max-height 1s ease-in-out;
}
tr.open div {
max-height: 500px;
}
Upvotes: 9
Reputation: 1125
Something like this is the minimum you need. Working version: http://jsfiddle.net/GCJrd/
head
<style>
.togglebox {
background-color:#CCC;
height: 100px;
max-height: 100px;
-webkit-transition: max-height 1s ease-in-out;
-moz-transition: max-height 1s ease-in-out;
-ms-transition: max-height 1s ease-in-out;
-o-transition: max-height 1s ease-in-out;
transition: max-height 1s ease-in-out;
}
</style>
<script src="js/jquery-1.7.1.min.js"></script>
<script>
$(document).ready(function(){
//Hide the toggle-area when page load
$(".togglebox").hide();
//slide up and down when click over id #one
$("#one").click(function(){
// slide toggle effect set to 600 you can set it faster too.
$(".togglebox").slideToggle(600);
return true;
});
});
</script>
body
<button id="one">showLine1</button>
<table id="my_table">
<tbody>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr class="togglebox">
<td>hidden 1</td>
<td>hidden 2</td>
</tr>
</tbody>
</table>
Upvotes: -3