had some trouble researching this, maybe I'm just not thinking clearly. I am using Bootstrap 3 and have a table to pull in data and I am highlighting certain data with their Alert styled divs.
The problem I have is that depending on the data they all have differing heights and I want them to all be the same. I've seen other examples but they weren't utilizing a table structure.
Is there a way to do this or is my only option to ditch the tables and do individual bootstrap columns?
Attached is an example of a table row.
I've updated your fiddle. I'm assuming that you have alerts throughout each of your rows, therefore we're iterating through each <tr> and finding the .alert divs, then determining which alert has the most "height". Then we add this height CSS to every .alert in the row.
The HTML structure has changed, I've added <thead> and <tbody>
<table class="table">
<thead>
<tr>
<th>Address</th>
<th>Super Permits</th>
<th>Active?</th>
</tr>
</thead>
<tbody>
....
....
$('.table').find('tbody tr').each(function (e) {
var heights = $(".alert").map(function ()
{
return $(this).outerHeight();
}).get(),
maxHeight = Math.max.apply(null, heights);
$(this).find('.alert').css('height', maxHeight);
});
Just add custom css for the "alert" class, and it will apply to all alert types, like:
.alert {
height: 90px
}
https://jsfiddle.net/W3AVE/4j72mfeo/
HTML
<table>
<tr class='same-height'>
<td><div><span>text</span></div></td>
<td><div><span>some long text here</span></div></td>
<td><div><span>text medium</span></div></td>
</tr>
</table>
CSS
div {
border: 1px solid black;
}
span {
text-align: center;
display: block;
position: relative;
top: 50%;
transform: translate(0, -50%)
}
JS
(function($){
var $el = $(".same-height"),
h = $el.height();
$el.find("div").each(function()
{
var $self = $(this);
$self.css({"height": h});
});
}(jQuery));
Related
I've got a table
<table id="mytable">
<tr style="display: none;"><td> </td></tr>
<tr><td> </td></tr>
<tr style="display: none;"><td> </td></tr>
<tr><td> </td></tr>
<tr><td> </td></tr>
<tr><td> </td></tr>
</table>
I'm trying to set the table striping to use nth-child selectors but just can't seem to crack it.
table #mytable tr[#display=block]:nth-child(odd) {
background-color: #000;
}
table #mytable tr[#display=block]:nth-child(odd) {
background-color: #FFF;
}
I'm pretty sure I'm close ... can't quite seem to crack it.
anyone pass along a clue?
Here's as close as you're going to get. Note that you can't make the nth-child count only displayed rows; nth-child will take the nth child element no matter what, not the nth child that matches a given selector. If you want some rows to be missing and not affect the zebra-striping, you will have to remove them from the table entirely, either through the DOM or on the server side.
#mytable tr:nth-child(odd) {
background-color: #000;
}
#mytable tr:nth-child(even) {
background-color: #FFF;
}
<table id="mytable">
<tr><td> </td></tr>
<tr><td> </td></tr>
<tr><td> </td></tr>
<tr><td> </td></tr>
<tr><td> </td></tr>
<tr><td> </td></tr>
</table>
Here are the fixes that I made:
table #mytable tr[#display=block]:nth-child(odd) {
background-color: #000;
}
There's no need to specify an ancestor selector for an id based selector; there is only ever one element that will match #table, so you're just adding extra code by adding the table in.
#mytable tr[#display=block]:nth-child(odd) {
background-color: #000;
}
Now, [#display=block] would match elements which had an attribute display set to block, such as <tr display=block>. Display isn't a valid HTML attribute; what you seem to be trying to do is to have the selector match on the style of the element, but you can't do that in CSS, since the browser needs to apply the styles from the CSS before it can figure that out, which it's in the process of doing when it's applying this selector. So, you won't be able to select on whether table rows are displayed. Since nth-child can only take the nth child no matter what, not nth with some attribute, we're going to have to give up on this part of the CSS. There is also nth-of-type, which selects the nth child of the same element type, but that's all you can do.
#mytable tr:nth-child(odd) {
background-color: #000;
}
And there you have it.
If you are using JQuery to change the visibility of rows you can apply the following function to the table to add an .odd class where appropriate. Call it each time the rows visible is different.
function updateStriping(jquerySelector){
$(jquerySelector).each(function(index, row){
$(row).removeClass('odd');
if (index%2==1){ //odd row
$(row).addClass('odd');
}
});
}
And for the css simply do
table#tableid tr.visible.odd{
background-color: #EFF3FE;
}
While you can't Zebra stripe a table with hidden rows using CSS3 you can do it with JavaScript. Here is how:
var table = document.getElementById("mytable");
var k = 0;
for (var j = 0, row; row = table.rows[j]; j++) {
if (!(row.style.display === "none")) {
if (k % 2) {
row.style.backgroundColor = "rgba(242,252,244,0.4)";
} else {
row.style.backgroundColor = "rgba(0,0,0,0.0)";
}
k++;
}
}
For a jquery way, you could use this function which iterates through the rows in your table, checking the visbility of the row and (re)setting a class for visible odd rows.
function updateStriping(jquerySelector) {
var count = 0;
$(jquerySelector).each(function (index, row) {
$(row).removeClass('odd');
if ($(row).is(":visible")) {
if (count % 2 == 1) { //odd row
$(row).addClass('odd');
}
count++;
}
});
}
Use css to set a background for odd rows.
#mytable tr.odd { background: rgba(0,0,0,.1); }
Then you can call this zebra-striper whenever by using:
updateStriping("#mytable tr");
I came up with a sort of solution but it's reliant on the fact that the table can only ever have a maximum number of hidden rows and comes with the downside of requiring 2 additional CSS rules for each possible hidden row. The principle is that, after each hidden row, you switch the background-color of the odd and even rows around.
Here's a quick example with just 3 hidden rows and the necessary CSS for up to 4 of them. You can already see how unwieldy the CSS can become but, still, someone may find some use for it:
table{
background:#fff;
border:1px solid #000;
border-spacing:1px;
width:100%;
}
td{
padding:20px;
}
tr:nth-child(odd)>td{
background:#999;
}
tr:nth-child(even)>td{
background:#000;
}
tr[data-hidden=true]{
display:none;
}
tr[data-hidden=true]~tr:nth-child(odd)>td{
background:#000;
}
tr[data-hidden=true]~tr:nth-child(even)>td{
background:#999;
}
tr[data-hidden=true]~tr[data-hidden=true]~tr:nth-child(odd)>td{
background:#999;
}
tr[data-hidden=true]~tr[data-hidden=true]~tr:nth-child(even)>td{
background:#000;
}
tr[data-hidden=true]~tr[data-hidden=true]~tr[data-hidden=true]~tr:nth-child(odd)>td{
background:#000;
}
tr[data-hidden=true]~tr[data-hidden=true]~tr[data-hidden=true]~tr:nth-child(even)>td{
background:#999;
}
tr[data-hidden=true]~tr[data-hidden=true]~tr[data-hidden=true]~tr[data-hidden=true]~tr:nth-child(odd)>td{
background:#999;
}
tr[data-hidden=true]~tr[data-hidden=true]~tr[data-hidden=true]~tr[data-hidden=true]~tr:nth-child(even)>td{
background:#000;
}
<table>
<tbody>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr data-hidden="true"><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr data-hidden="true"><td></td><td></td></tr>
<tr data-hidden="true"><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
</tbody>
</table>
in jquery ..
var odd = true;
$('table tr:visible').each(function() {
$(this).removeClass('odd even').addClass(odd?'odd':'even');
odd=!odd
});
You can easily fake the zebra stripes if you apply a vertically repeating gradient on the parent table, positioned exactly to match the rows' height (the rows would have to be transparent). That way the table won't care if anything's hidden, it will repeat no matter what.
If anyone tries to do something like me, where I have alternating hidden and visible rows, you can do this:
.table-striped tbody tr:nth-child(4n + 1) {
background-color: rgba(0,0,0,.05);
}
This will get every 4th element starting with the 1st one, and allows you to maintain striping with hidden rows between each visible row.
Here is a 2022 version of a javascript version
let cnt = 0;
document.querySelectorAll("#mytable tbody tr").forEach(tr => {
cnt += tr.hidden ? 0 : 1;
tr.classList.toggle("odd",cnt%2===0);
});
.odd { background-color: grey; }
<table id="mytable">
<thead><tr><th>Num</th></tr></thead>
<tbody>
<tr><td>1</td></tr>
<tr><td>2</td></tr>
<tr><td>3</td></tr>
<tr hidden><td></td></tr>
<tr><td>5</td></tr>
<tr><td>6</td></tr>
</tbody>
</table>
I add in css:
tr[style="display: table-row;"]:nth-child(even) {
background-color: #f3f6fa;
}
and on create tr add in tag
style="display: table-row;"
Jquery codes for zebra color in html table
$("#mytabletr:odd").addClass('oddRow');
$("#mytabletr:even").addClass('evenEven');
And CSS you can do
.oddRow{background:#E3E5E6;color:black}
.evenRow{background:#FFFFFF;color:black}
I'm having an issue where I can't seem to find an answer to, but I can't imagine it's not possible.
I have a table with two columns: the left column contains a label, the right side contains a value. However, the value can be empty. The label is fixed text.
What I want is to hide the entire row if the right cell of the row (the value) is empty.
For example:
<table>
<tr>
<td class="label">number of users:</td>
<td class="value">8</td>
</tr>
<tr>
<td class="label">total number of people:</td>
<td class="value"></td>
</tr>
</table>
Since the last row does not contain a value, I want the entire row to be hidden.
I can hide the cell using td:empty, but that's not enough. I tried to work around this by setting the height of the row to 0px and make it expand when the 'value'-cell is shown, but I can't get that to work either since the label cell already expands the row.
Anyone knows how I can tackle this problem using just HTML/CSS?
There's no parent selector in css, so you can't do this with css.
You may use jQuery:
$('td').each(function(){
if($(this).is(:empty)){
$(this).closest('tr').hide();
}
});
Or in shorter form,
$('tr:has("td:empty")').hide();
See the docs: :empty, :has,closest and each
While JavaScript is necessary to solve this problem, jQuery is, by no means, a requirement. Using the DOM, one can achieve this with the following:
function hideParentsOf(cssSelector) {
var elems = document.querySelectorAll(cssSelector);
if (elems.length) {
Array.prototype.forEach.call(elems, function (el) {
el.parentNode.style.display = 'none';
});
}
}
hideParentsOf('td:empty');
function hideParentsOf(cssSelector) {
// cssSelector: String,
// a string representing a CSS selector,
// such as 'td:empty' in this case.
// retrieving a NodeList of elements matching the supplied selector:
var elems = document.querySelectorAll(cssSelector);
// if any elements were found:
if (elems.length) {
// iterating over the array-like NodeList with Array.forEach():
Array.prototype.forEach.call(elems, function(el) {
// el is the current array-element (or NodeList-element in
// this instance).
// here we find the parentNode, and set its 'display' to 'none':
el.parentNode.style.display = 'none';
});
}
}
hideParentsOf('td:empty');
<table>
<tr>
<td class="label">number of users:</td>
<td class="value">8</td>
</tr>
<tr>
<td class="label">total number of people:</td>
<td class="value"></td>
</tr>
</table>
References:
CSS:
:empty pseudo-class.
JavaScript:
Array.prototype.forEach().
document.querySelectorAll().
Function.prototype.call().
Node.parentNode.
HTMLElement.style.
An HTML/CSS solution exists if you don't mind throwing out <table> <tr> and <td>. You can get the same end result with CSS - including still rendering like a table:
CSS:
/* hide if empty */
.hideIfEmpty:empty { display: none; }
/* label style */
.hideIfEmpty::before { font-weight:bold; }
/* labels */
.l_numberofusers::before { content:"Number of users: "; }
.l_numberofpeople::before { content: "Number of people:"; }
.l_numberofdogs::before { content: "Number of dogs:" }
/* table like rows/cells */
.table { display: table; }
.row { display: table-row; }
.cell { display: table-cell; }
HTML
<!-- if the div.hideIfEmpty is empty, it'll be hidden;
labels come from CSS -->
<div class="table">
<div class="row hideIfEmpty l_numberofusers"><span class="cell">8</span></div>
<div class="row hideIfEmpty l_numberofpeople"><span class="cell">12</span></div>
<div class="row hideIfEmpty l_numberofdogs"></div>
</div>
The caveat is that your <div> has to be empty to hide the row, and values in the <div> must have a class .cell applied to them.
Result:
Number of users: 8
Number of people: 12
This will make your CSS very long if you have many labels/rows since you have to have one rule for every row to populate the label.
My previous question got an answer using min-width to set the width of a containing block but allow it to grow when its children are too big.
This worked fine with some kinds of children (simple divs with their own min-width and max-width specified explicitly). Now I'm looking at a more complex variation in which the children are tables. (Legitimate tables with semantically meaningful rows and columns, not page-layout tables.)
There is no manually-specified min-width or max-width on these tables, but tables have an inherent maximum and minimum width, corresponding to the width that the table would have if rendered with no line breaks in any of the cells (maximum) and the width that it would have with line breaks inserted insertion of all possible line breaks (minimum).
In the existing page layout which I'm trying to replace, the outermost container is a table (the bad kind of table) with a single cell in a single row, and a CSS width (not min-width) set to the preferred width. When the children are tables, they try really hard to fit into the container's width. A wide table will be rendered with line breaks to make it fit, and the container will expand only if the child still doesn't fit after all line breaks are inserted.
In other words, the parent's width property is treated as a minimum, but it is also a strongly preferred width, which has a higher priority than the child's preferred (i.e. maximum) width.
By contrast, when the parent is a plain div with display:inline-block and a specified min-width, the parent's min-width is not strongly preferred. The child prefers to be wider, so the parent expands, even if the child is capable of being rendered with a smaller width.
Here's a snippet, much like the one in the previous question, which demonstrates all of this. The goal is to make the second container act like the first one in some way that is more "proper" than using display:table for layout.
(Note: the table widths at the heart of this question are very sensitive to choice of font. I hope the Courier New comes through and everybody sees the same widths in the snippet.)
var containers = document.querySelectorAll(".container");
for(var i = 0; i < containers.length; ++i) {
(function() {
var c = containers[i],
b = c.nextElementSibling;
b.addEventListener("click", function(ev) {
big = c.querySelector(".bigchild");
medium = c.querySelector(".mediumchild");
small = c.querySelector(".smallchild");
if(big.style.display != "block" &&
medium.style.display != "block" &&
small.style.display != "block") {
big.style.display = "block";
} else if(big.style.display == "block") {
big.style.display = "none";
medium.style.display = "block";
} else if(medium.style.display == "block") {
medium.style.display = "none";
small.style.display = "block";
} else {
small.style.display = "none";
}
});
})();
}
body {
background-color: #ccc;
text-align: center;
font-size: 14px;
font-family: "Courier New";
}
table {
border-collapse: collapse;
}
td {
border: 1px solid black;
padding: 5px;
}
.container {
background-color: white;
min-height: 250px;
margin-left: auto;
margin-right: auto;
}
.bigchild, .mediumchild, .smallchild {
display: none;
}
button {
display: block;
margin: 10px auto 20px;
}
#container1 {
display: table;
width: 400px;
}
#container2 {
display: inline-block;
min-width: 400px;
}
<div class="container" id="container1">
<table class="bigchild">
<tr>
<td>Lots of</td>
<td>columns</td>
<td>make this</td>
<td>a very</td>
<td>wide</td>
<td>table</td>
<td>that won't</td>
<td>fit</td>
<td>even with</td>
<td>added</td>
<td>line breaks</td>
</tr>
</table>
<table class="mediumchild">
<tr>
<td>This table</td>
<td>is smaller</td>
<td>and</td>
<td>it fits</td>
<td>but</td>
<td>only with</td>
<td>added</td>
<td>line breaks</td>
</tr>
</table>
<table class="smallchild">
<tr>
<td>very</td>
<td>small</td>
</tr>
</table>
</div>
<button>Next</button>
<div class="container" id="container2">
<table class="bigchild">
<tr>
<td>Lots of</td>
<td>columns</td>
<td>make this</td>
<td>a very</td>
<td>wide</td>
<td>table</td>
<td>that won't</td>
<td>fit</td>
<td>even with</td>
<td>added</td>
<td>line breaks</td>
</tr>
</table>
<table class="mediumchild">
<tr>
<td>This table</td>
<td>is smaller</td>
<td>and</td>
<td>it fits</td>
<td>but</td>
<td>only with</td>
<td>added</td>
<td>line breaks</td>
</tr>
</table>
<table class="smallchild">
<tr>
<td>very</td>
<td>small</td>
</tr>
</table>
</div>
<button>Next</button>
I think .container {min-width: 400px;width: min-content;}, modulo vendor prefixes, is what you want.
I am using the following css to rotate the text inside table header cells but the header cells is of the same width as if the text were horizontal.How can I just rotate the text and the width will reduce automatically..
table#MyTable tr th a{
color: #FFFFFF;
display: block;
/*Firefox*/
-moz-transform: rotate(-90deg);
/*Safari*/
-webkit-transform: rotate(-90deg);
/*Opera*/
-o-transform: rotate(-90deg);
/*IE*/
writing-mode: tb-rl;
filter: flipv fliph;
padding: 60px 1px;
}
If you need to adjust just the width of the cells and they contain only one line of text each you can do this: http://jsfiddle.net/sSP8W/3/ — set width of an element to it's line-height.
The problem with CSS3-transforms is that they work like as CSS' position: relative: their original box stays the same, so rotating, skewing etc. don't cause the changes in the element's dimensions. So: there is really no perfect CSS solution, you can use JS to adjust the dimensions, or try to find hackety workarounds. So if you have only links in a table, you can do something like that: http://jsfiddle.net/sSP8W/4/ — rotating the table itself.
If your case have another content that you don't want to rotate — update the post, so we could try to find a better solution.
upd: Just found out a solution to the rotated text in tables: using some magic with vertical paddings we could make cells stretch to the content, so look at this almost final example: http://dabblet.com/gist/4072362
I solved it this using a jQuery plugin by David Votrubec and the comment by Mike below the blog post.
Put this in a .js-file:
(function ($) {
$.fn.rotateTableCellContent = function (options) {
/*
Version 1.0
7/2011
Written by David Votrubec (davidjs.com) and
Michal Tehnik (#Mictech) for ST-Software.com
*/
var cssClass = ((options) ? options.className : false) || "vertical";
var cellsToRotate = $('.' + cssClass, this);
var betterCells = [];
cellsToRotate.each(function () {
var cell = $(this)
, newText = cell.text()
, height = cell.height()
, width = cell.width()
, newDiv = $('<div>', { height: width, width: height })
, newInnerDiv = $('<div>', { text: newText, 'class': 'rotated' });
newInnerDiv.css('-webkit-transform-origin', (width / 2) + 'px ' + (width / 2) + 'px');
newInnerDiv.css('-moz-transform-origin', (width / 2) + 'px ' + (width / 2) + 'px');
newDiv.append(newInnerDiv);
betterCells.push(newDiv);
});
cellsToRotate.each(function (i) {
$(this).html(betterCells[i]);
});
};
})(jQuery);
And this at the top of your page:
<script src="rotatetablecellcontent.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
$('.yourtableclass').rotateTableCellContent();
});
</script>
And this in your CSS:
/* Styles for rotateTableCellContent plugin*/
table div.rotated {
-webkit-transform: rotate(270deg);
-moz-transform: rotate(270deg);
writing-mode:tb-rl;
white-space: nowrap;
}
thead th {
vertical-align: top;
}
table .vertical {
white-space: nowrap;
}
Then make sure your table has the class "yourtableclass", and that all the TDs you want rotated have the class "vertical".
Here's a demo running in a jsFiddle.
Hope it helps someone, even though I'm a year late!
In IE and Chrome (Blink and Webkit), you can put the text in a child with a vertical writing mode rather than using a transform. Saves you all the CSS and JavaScript tricks. Chrome has a minor display bug at the moment (Chrome 37), but it's been reported.
.vertical {
-webkit-writing-mode:vertical-rl;
-ms-writing-mode:tb-rl;
writing-mode:vertical-rl;
}
<td><span class="vertical">This text should be vertical.</span></td>
I recommend using white-space:nowrap on the vertical text within the table.
The solution by jobjorn above now breaks in Chrome, because it supports writing-mode as of early 2016, so essentially tries to rotate the text twice, and ends up with mispositioned horizontal text. From my understanding, Firefox and Safari will probably support this soon too, which will cause them to break too. After some banging my head against the wall, I fixed it by changing the CSS to:
#supports not (writing-mode:vertical-rl) {
table div.rotated {
-webkit-transform: rotate(270deg);
-moz-transform: rotate(270deg);
white-space: nowrap;
}
}
#supports (writing-mode:vertical-rl) {
table div.rotated {
writing-mode:vertical-rl;
-webkit-transform: rotate(180deg) translate(8px,0px);
-moz-transform: rotate(180deg) translate(8px,0px);
white-space: nowrap;
}
}
The 8 pixel translation was what it took for the alignment to look right in my particular example. You mileage may vary. The 180 degree rotation was to make the top of the text face left instead of right. If you don't need that, you can probably skip the transforms in the second part.
In the JavaScript, you also need to make sure that you don't move the origin for those last transforms, as that was only needed if you were using a transform to do the vertical orientation itself, so I wrapped that part in a conditional:
var supportsWM = CSS.supports('writing-mode', 'vertical-rl');
if (!supportsWM) {
newInnerDiv.css('-webkit-transform-origin', (width / 2) + 'px ' + (width / 2) + 'px');
newInnerDiv.css('-moz-transform-origin', (width / 2) + 'px ' + (width / 2) + 'px');
}
Mods: sorry that this post "responds to an answer". But I don't have the karma necessary to comment on it. Catch-22.
The code in #jobjorn's answer and fiddl depends on cell width to calculate header height, which leads to erroneous heights when any cell is wide. This modified fiddle uses the header text width instead: http://jsfiddle.net/marvmartian/76z82/
cellsToRotate.each(function () {
var cell = $(this);
var s = '<div id="killme" style="position:absolute; top:-10000px; left:-10000px;"><span id="string_span" style="font-weight: bold; font-size: 1em">'+
cell.text()+'</span></div>';
$(window).append(s);
var width = $('#string_span').width();
var newText = cell.text()
, height = cell.height()
//, width = cell.width()
, newDiv = $('<div>', { height: width, width: height })
, newInnerDiv = $('<div>', { text: newText, 'class': 'rotated' });
Get rid of padding:60px 1px; (unless you need it for some other reason...but that's what's causing the problem).
Example: http://jsfiddle.net/purmou/sSP8W/
This is now possible without any browser specific transforms used in the other answers. Note that the wrapping span is required as of 2022 in order to get firefox in particular to center the rotated text within the column (webkit does this by default).
<style type="text/css">
#myTable td {
text-align: right;
}
th.r span {
transform: rotate(185deg);
writing-mode: vertical-lr;
}
</style>
<table id="myTable" border="1" cellpadding="2" style="border-collapse:collapse;">
<tr>
<th class='r'><span>Display</span></th>
<th class='r'><span>Year made (TV?)</span></th>
<th class='r'><span>Native Res</span></th>
</tr>
<tr>
<td style="color:rgb(17, 85, 204);">Dell U2410 (game) </td>
<td>2010</td>
<td>1080p</td>
</tr>
<tr>
<td style="color:rgb(17, 85, 204);">Dell U2410 (sRGB)</td>
<td>2010</td>
<td>1080p</td>
</tr>
<tr>
<td style="color:rgb(17, 85, 204);"> Sony 40VL130 (game)</td>
<td style="color:rgb(0, 0, 255);">2008</td>
<td>1080p</td>
</tr>
</table>
<style type="text/css">
#myTable td {
text-align: right;
}
th.r span {
transform: rotate(185deg);
writing-mode: vertical-lr;
}
</style>
<table id="myTable" border="1" cellpadding="2" style="border-collapse:collapse;">
<tr>
<th class='r'><span>Display</span></th>
<th class='r'><span>Year made (TV?)</span></th>
<th class='r'><span>Native Res</span></th>
</tr>
<tr>
<td style="color:rgb(17, 85, 204);">Dell U2410 (game) </td>
<td>2010</td>
<td>1080p</td>
</tr>
<tr>
<td style="color:rgb(17, 85, 204);">Dell U2410 (sRGB)</td>
<td>2010</td>
<td>1080p</td>
</tr>
<tr>
<td style="color:rgb(17, 85, 204);"> Sony 40VL130 (game)</td>
<td style="color:rgb(0, 0, 255);">2008</td>
<td>1080p</td>
</tr>
</table>
I've got a table
<table id="mytable">
<tr style="display: none;"><td> </td></tr>
<tr><td> </td></tr>
<tr style="display: none;"><td> </td></tr>
<tr><td> </td></tr>
<tr><td> </td></tr>
<tr><td> </td></tr>
</table>
I'm trying to set the table striping to use nth-child selectors but just can't seem to crack it.
table #mytable tr[#display=block]:nth-child(odd) {
background-color: #000;
}
table #mytable tr[#display=block]:nth-child(odd) {
background-color: #FFF;
}
I'm pretty sure I'm close ... can't quite seem to crack it.
anyone pass along a clue?
Here's as close as you're going to get. Note that you can't make the nth-child count only displayed rows; nth-child will take the nth child element no matter what, not the nth child that matches a given selector. If you want some rows to be missing and not affect the zebra-striping, you will have to remove them from the table entirely, either through the DOM or on the server side.
#mytable tr:nth-child(odd) {
background-color: #000;
}
#mytable tr:nth-child(even) {
background-color: #FFF;
}
<table id="mytable">
<tr><td> </td></tr>
<tr><td> </td></tr>
<tr><td> </td></tr>
<tr><td> </td></tr>
<tr><td> </td></tr>
<tr><td> </td></tr>
</table>
Here are the fixes that I made:
table #mytable tr[#display=block]:nth-child(odd) {
background-color: #000;
}
There's no need to specify an ancestor selector for an id based selector; there is only ever one element that will match #table, so you're just adding extra code by adding the table in.
#mytable tr[#display=block]:nth-child(odd) {
background-color: #000;
}
Now, [#display=block] would match elements which had an attribute display set to block, such as <tr display=block>. Display isn't a valid HTML attribute; what you seem to be trying to do is to have the selector match on the style of the element, but you can't do that in CSS, since the browser needs to apply the styles from the CSS before it can figure that out, which it's in the process of doing when it's applying this selector. So, you won't be able to select on whether table rows are displayed. Since nth-child can only take the nth child no matter what, not nth with some attribute, we're going to have to give up on this part of the CSS. There is also nth-of-type, which selects the nth child of the same element type, but that's all you can do.
#mytable tr:nth-child(odd) {
background-color: #000;
}
And there you have it.
If you are using JQuery to change the visibility of rows you can apply the following function to the table to add an .odd class where appropriate. Call it each time the rows visible is different.
function updateStriping(jquerySelector){
$(jquerySelector).each(function(index, row){
$(row).removeClass('odd');
if (index%2==1){ //odd row
$(row).addClass('odd');
}
});
}
And for the css simply do
table#tableid tr.visible.odd{
background-color: #EFF3FE;
}
While you can't Zebra stripe a table with hidden rows using CSS3 you can do it with JavaScript. Here is how:
var table = document.getElementById("mytable");
var k = 0;
for (var j = 0, row; row = table.rows[j]; j++) {
if (!(row.style.display === "none")) {
if (k % 2) {
row.style.backgroundColor = "rgba(242,252,244,0.4)";
} else {
row.style.backgroundColor = "rgba(0,0,0,0.0)";
}
k++;
}
}
For a jquery way, you could use this function which iterates through the rows in your table, checking the visbility of the row and (re)setting a class for visible odd rows.
function updateStriping(jquerySelector) {
var count = 0;
$(jquerySelector).each(function (index, row) {
$(row).removeClass('odd');
if ($(row).is(":visible")) {
if (count % 2 == 1) { //odd row
$(row).addClass('odd');
}
count++;
}
});
}
Use css to set a background for odd rows.
#mytable tr.odd { background: rgba(0,0,0,.1); }
Then you can call this zebra-striper whenever by using:
updateStriping("#mytable tr");
I came up with a sort of solution but it's reliant on the fact that the table can only ever have a maximum number of hidden rows and comes with the downside of requiring 2 additional CSS rules for each possible hidden row. The principle is that, after each hidden row, you switch the background-color of the odd and even rows around.
Here's a quick example with just 3 hidden rows and the necessary CSS for up to 4 of them. You can already see how unwieldy the CSS can become but, still, someone may find some use for it:
table{
background:#fff;
border:1px solid #000;
border-spacing:1px;
width:100%;
}
td{
padding:20px;
}
tr:nth-child(odd)>td{
background:#999;
}
tr:nth-child(even)>td{
background:#000;
}
tr[data-hidden=true]{
display:none;
}
tr[data-hidden=true]~tr:nth-child(odd)>td{
background:#000;
}
tr[data-hidden=true]~tr:nth-child(even)>td{
background:#999;
}
tr[data-hidden=true]~tr[data-hidden=true]~tr:nth-child(odd)>td{
background:#999;
}
tr[data-hidden=true]~tr[data-hidden=true]~tr:nth-child(even)>td{
background:#000;
}
tr[data-hidden=true]~tr[data-hidden=true]~tr[data-hidden=true]~tr:nth-child(odd)>td{
background:#000;
}
tr[data-hidden=true]~tr[data-hidden=true]~tr[data-hidden=true]~tr:nth-child(even)>td{
background:#999;
}
tr[data-hidden=true]~tr[data-hidden=true]~tr[data-hidden=true]~tr[data-hidden=true]~tr:nth-child(odd)>td{
background:#999;
}
tr[data-hidden=true]~tr[data-hidden=true]~tr[data-hidden=true]~tr[data-hidden=true]~tr:nth-child(even)>td{
background:#000;
}
<table>
<tbody>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr data-hidden="true"><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr data-hidden="true"><td></td><td></td></tr>
<tr data-hidden="true"><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
</tbody>
</table>
in jquery ..
var odd = true;
$('table tr:visible').each(function() {
$(this).removeClass('odd even').addClass(odd?'odd':'even');
odd=!odd
});
You can easily fake the zebra stripes if you apply a vertically repeating gradient on the parent table, positioned exactly to match the rows' height (the rows would have to be transparent). That way the table won't care if anything's hidden, it will repeat no matter what.
If anyone tries to do something like me, where I have alternating hidden and visible rows, you can do this:
.table-striped tbody tr:nth-child(4n + 1) {
background-color: rgba(0,0,0,.05);
}
This will get every 4th element starting with the 1st one, and allows you to maintain striping with hidden rows between each visible row.
Here is a 2022 version of a javascript version
let cnt = 0;
document.querySelectorAll("#mytable tbody tr").forEach(tr => {
cnt += tr.hidden ? 0 : 1;
tr.classList.toggle("odd",cnt%2===0);
});
.odd { background-color: grey; }
<table id="mytable">
<thead><tr><th>Num</th></tr></thead>
<tbody>
<tr><td>1</td></tr>
<tr><td>2</td></tr>
<tr><td>3</td></tr>
<tr hidden><td></td></tr>
<tr><td>5</td></tr>
<tr><td>6</td></tr>
</tbody>
</table>
I add in css:
tr[style="display: table-row;"]:nth-child(even) {
background-color: #f3f6fa;
}
and on create tr add in tag
style="display: table-row;"
Jquery codes for zebra color in html table
$("#mytabletr:odd").addClass('oddRow');
$("#mytabletr:even").addClass('evenEven');
And CSS you can do
.oddRow{background:#E3E5E6;color:black}
.evenRow{background:#FFFFFF;color:black}