CSS3 makes it trivial to have alternating row colours for tables, but when the table is in a fixed height scroll panel, it’s much more difficult to have those alternating row colours extend beyond the bottom of the table content to fill the available space. Here’s the approach I use.
First let’s start with a simple table with alternating colours in a scroll panel:
<!DOCTYPE html><html><head><meta charset=UTF-8><title>Alternating Rows Example</title><style>* { margin: 0; padding: 0; }table { border-collapse: collapse; width: 100%; height: 100%;}.scroll { position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow-y: scroll; overflow-x: auto;}.scroll tr { height: 20px;}.striped tr:nth-child(odd) { background-color: #EAEAEA;}</style></head><body><div class="scroll"><table class="striped"><tbody><tr><td>Row 1</td></tr><tr><td>Row 2</td></tr><tr><td>Row 3</td></tr><tr><td>Row 4<br>With an extra line</td></tr><tr><td>Row 5</td></tr></tbody></table></div></body></html>That gets us alternating row colours where there is table content. To get it to extend beyond the table content we need to add a filler row:
<div class="scroll"><table class="striped"><tbody><tr><td>Row 1</td></tr><tr><td>Row 2</td></tr><tr><td>Row 3</td></tr><tr><td>Row 4<br>With an extra line</td></tr><tr><td>Row 5</td></tr><tr class="filler"><td></td></tr></tbody></table></div>This gives us an extra row in the table that we know will always start immediately after the last row of content in the table and line up. We can now set a prepared image as the background of that row that preserves the alternating colours and stretch it out to take up the remaining space:
.striped .filler { line-height: 0; background: url(stripes.png) repeat top left; height: 100%; padding: 0;}
.striped .filler td { padding: 0;}
.striped .filler:nth-child(even) { background-position: 0 20px;}Apart from the background image, we set the height to 100% so that our filler row fills the remaining space. If the table is empty, the filler row will get 100% height and fill all available space, if however the table has other rows in it, the table rendering algorithm will shrink our filler row down so that it can fit within the bounds of the table – preventing the filler row from overflowing the scroll container and activating the scroll bar.
Since our background image starts with an odd row colour, if the filler row is an even row, we use background-position to shift the background image down by the height of a stripe so it effectively starts with an odd row colour.
We also add line-height: 0 and padding: 0 so that when the table content fills all available space (or starts scrolling), the filler row has no minimum height and disappears entirely.
Note that this approach will adjust perfectly well even if the content rows vary in height, because the filler row will always start immediately after the last content row and fill the available space. The height of the alternating colours in our image will just provide the default row height in the filler space.
If we’re only targeting modern browsers anyway, we can go ahead and replace the background image with a dynamically generated gradient:
.striped .filler { line-height: 0; height: 100%; padding: 0; background-image: linear-gradient(bottom, rgb(255,255,255) 50%, rgb(234,234,234) 50%); background-image: -o-linear-gradient(bottom, rgb(255,255,255) 50%, rgb(234,234,234) 50%); background-image: -moz-linear-gradient(bottom, rgb(255,255,255) 50%, rgb(234,234,234) 50%); background-image: -webkit-linear-gradient(bottom, rgb(255,255,255) 50%, rgb(234,234,234) 50%); background-image: -ms-linear-gradient(bottom, rgb(255,255,255) 50%, rgb(234,234,234) 50%);
background-image: -webkit-gradient( linear, left bottom, left top, color-stop(0.5, rgb(255,255,255)), color-stop(0.5, rgb(234,234,234)) );
-webkit-background-size: 40px 40px; -moz-background-size: 40px 40px; -ms-background-size: 40px 40px; -o-background-size: 40px 40px; background-size: 40px 40px;}The final version of our page is:
<!DOCTYPE html><html><head><meta charset=UTF-8><title>Alternating Rows Example</title><style>* { margin: 0; padding: 0; }table { border-collapse: collapse; width: 100%; height: 100%;}.scroll { position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow-y: scroll; overflow-x: auto;}.scroll tr { height: 20px;}.striped tr:nth-child(odd) { background-color: #EAEAEA;}.striped .filler { line-height: 0; height: 100%; padding: 0; background-image: linear-gradient(bottom, rgb(255,255,255) 50%, rgb(234,234,234) 50%); background-image: -o-linear-gradient(bottom, rgb(255,255,255) 50%, rgb(234,234,234) 50%); background-image: -moz-linear-gradient(bottom, rgb(255,255,255) 50%, rgb(234,234,234) 50%); background-image: -webkit-linear-gradient(bottom, rgb(255,255,255) 50%, rgb(234,234,234) 50%); background-image: -ms-linear-gradient(bottom, rgb(255,255,255) 50%, rgb(234,234,234) 50%);
background-image: -webkit-gradient( linear, left bottom, left top, color-stop(0.5, rgb(255,255,255)), color-stop(0.5, rgb(234,234,234)) );
-webkit-background-size: 40px 40px; -moz-background-size: 40px 40px; -ms-background-size: 40px 40px; -o-background-size: 40px 40px; background-size: 40px 40px;}
.striped .filler td { padding: 0;}
.striped .filler:nth-child(even) { background-position: 0 20px;}</style></head><body><div class="scroll"><table class="striped"><tbody><tr><td>Row 1</td></tr><tr><td>Row 2</td></tr><tr><td>Row 3</td></tr><tr><td>Row 4<br>With an extra line</td></tr><tr><td>Row 5</td></tr><tr class="filler"><td></td></tr></tbody></table></div></body></html>Or try the demo in your browser.