alej27 alej27 - 2 months ago 23
CSS Question

Change whole table row color with gradient and transition after clicking on a child cell

I have a table with two columns and multiple rows.

HTML



<table cellspacing="0">
<tr class="title">
<th>Column 1</th>
<th>Column 2</th>
</tr>
<tr>
<td>Content 1</td>
<td>Content 2</td>
</tr>
<tr>
<td>Content 1</td>
<td>Content 2</td>
</tr>
<tr>
<td>Content 1</td>
<td>Content 2</td>
</tr>
<tr class="title">
<th>Column 1</th>
<th>Column 2</th>
</tr>
<tr>
<td>Content 1</td>
<td>Content 2</td>
</tr>
<tr>
<td>Content 1</td>
<td>Content 2</td>
</tr>
<tr>
<td>Content 1</td>
<td>Content 2</td>
</tr>
</table>
<p style="background-color: #EEE;
background-image: linear-gradient(#F7F7F7, #EEE); padding: 2em; display: block; border: 1px solid #C3C3C3; font-family: Arial, sans-serif;">
The background should actually be like this
</p>


CSS



table {
margin-right: 1px;
font-family: Arial, sans-serif;
}
table td {
width:auto;
padding: 1em 2em;
text-align:center;
background: gray;
/* Old browsers */
background:
-webkit-linear-gradient(right, transparent 50%, #1F7DE2 50%), linear-gradient(#F7f7f7, #EEE);
background:
-moz-linear-gradient(right, transparent 50%, #1F7DE2 50%), linear-gradient(#F7f7f7, #EEE);
background:
-o-linear-gradient(right, transparent 50%, #1F7DE2 50%), linear-gradient(#F7f7f7, #EEE);
background:
linear-gradient(to left, transparent 50%, #1F7DE2 50%), linear-gradient(#F7f7f7, #EEE);
background-size: 200% 100%;
background-position:right bottom;
margin-left:10px;
transition:all 0.3s ease-in;
}

table td:active {
background-position: left bottom;
color: white;
}


Clicking on a cell (and not header) "changes" its background color. It transitions from left to right, from a gradient (two colors) gray to a solid (monochromatic) blue.

The cells (and not the headers) have two linear backgrounds. The first one (
linear-gradient(right, transparent 50%, #1F7DE2 50%)
) is the "solid" blue one (activated when the cell has a state of
:active
, i.e. clicked). The second one (
linear-gradient(#F7f7f7, #EEE)
) is the two-gray-tones background.

The reason for using two linear background per cell is because when you click on them, the background doesn't really change, but instead the position: the gradient gray background is pushed by the solid blue background.

However, what I want is when you click on any cell (row's children), the whole corresponding row changes its color. So when you click on any cell, the whole row starts to change its color, from left to right.

Maybe instead of changing the whole row, we could make in a manner where the left cell changes first, and then the second, but I believe that'd use JavaScript, plus it'd be more complicated.

Thank you everybody in advance, and for those with questions don't hesitate to ask.

Answer

I think this is what you're after. As someone mentioned you have to use javascript to do this. I used jQuery to make it a little simpler to throw together. It could probably be cleaned up somewhat, but basically it's going to loop thru each td in the row of the td you clicked on, and add the class to it with the CSS animation. There is a setTimeout handling the class and the delay matches the delay in your css animation, so that they happen one after the other in order to make it look like it's transitioning across the row.

The only issue with this is, that I changed your ease-in to linear because with two of them easing, there was a slight 'bump' between cells. You can probably play around with it a bit to make it more seamless. I wrote this so it accommodates any number of cells in a row, but if you know its' always going to be 2, you could do ease-in on the first child and ease out on the second and it would be a nice effect.

Also you'll need to modify the method a bit to handle the 'reverse' animation, as right now it would be backwards. If you can't figure it out, just comment, and I'll see if I can do that later. Gotta run right now.

$("td").on("click",function() {
  var $row = $(this).closest("tr");
  var $numColumns = $row.children().length;
  for (var $i = 0; $i < $numColumns; $i++) {
    handleClass($i);
  }
  function handleClass($i) {
    setTimeout(function() { 
       $row.children().eq($i).toggleClass('active'); 
    }, $i*300);
  }
});
table {
margin-right: 1px;
font-family: Arial, sans-serif;
}
table td {
    width:auto;
    padding: 1em 2em;
    text-align:center;
    background: gray;
    /* Old browsers */
    background:
    -webkit-linear-gradient(right, transparent 50%, #1F7DE2 50%), linear-gradient(#F7f7f7, #EEE);
    background:
    -moz-linear-gradient(right, transparent 50%, #1F7DE2 50%), linear-gradient(#F7f7f7, #EEE);
    background:
    -o-linear-gradient(right, transparent 50%, #1F7DE2 50%), linear-gradient(#F7f7f7, #EEE);
    background:
    linear-gradient(to left, transparent 50%, #1F7DE2 50%), linear-gradient(#F7f7f7, #EEE);
    background-size: 200% 100%;
    background-position:right bottom;
    margin-left:10px;
    transition:all 0.3s linear;
}

table td.active {
    background-position: left bottom;
    color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table cellspacing="0">
<tr class="title">
    <th>Column 1</th>
    <th>Column 2</th>
</tr>
<tr>
  <td>Content 1</td>
  <td>Content 2</td>
</tr>
<tr>
  <td>Content 1</td>
  <td>Content 2</td>
</tr>
<tr>
  <td>Content 1</td>
  <td>Content 2</td>
</tr>
<tr class="title">
    <th>Column 1</th>
    <th>Column 2</th>
</tr>
<tr>
  <td>Content 1</td>
  <td>Content 2</td>
</tr>
<tr>
  <td>Content 1</td>
  <td>Content 2</td>
</tr>
<tr>
  <td>Content 1</td>
  <td>Content 2</td>
</tr>
</table>