Benjamin Spiegel Benjamin Spiegel - 3 months ago 13
CSS Question

HTML Table Row nth-child Dynamic Content Issue

I have a table whose

<tr>
s I populate on the fly by manually changing the table's
innerHTML
. When I do, the CSS I have in place (which implements
nth-child(odd/even)
) fails.

tr:nth-child(odd) {
background-color: #000000;
}

tr:nth-child(even) {
background-color: #FFFFFF;
}


The resulting table has all
<tr>
s with the color scheme of an
nth-child(odd)
selector.

When the table is populated dynamically with
tableVar.innerHTML += "<tr>...</tr>"
the issue arises, however, it turns out if you change the way the
innerHTML
is modified by first assembling a string with
stringVar += "<tr>...</tr>"
and then assigning the innerHTML to the string with
tableVar.innerHTML = stringVar
the problem goes away and the expected behavior returns.

Why does this happen?

Answer

The browser wraps your new rows in <tbody> elements when you concatenate a new row directly to the table element, so each subsequent row is a single row per new <tbody>, making it apply to the nth-child(odd) selector. This explains why constructing new HTML from scratch and assigning it to the table doesn't show that problem. You can see this by inspecting the HTML generated in your browser's developer console when you run this example:

var table = document.getElementById("table");
setInterval(function() {
  table.innerHTML += "<tr><td>Test1</td><td>Test 2</td></tr>";
}, 1000)
tr:nth-child(odd) {
  background-color: #cccccc;
}
tr:nth-child(even) {
  background-color: #FFFFFF;
}
<table id="table">
  <tbody id="tbody">
    <tr>
      <td>Test 1</td>
      <td>Test 2</td>
    </tr>
    <tr>
      <td>Test 1</td>
      <td>Test 2</td>
    </tr>
    <tr>
      <td>Test 1</td>
      <td>Test 2</td>
    </tr>
  </tbody>
</table>

If you append directly to the table's <tbody> element instead, you'll see the CSS apply to your new rows as expected:

var tbody = document.getElementById("tbody");
setInterval(function() {
  tbody.innerHTML += "<tr><td>Test1</td><td>Test 2</td></tr>";
}, 1000)
tr:nth-child(odd) {
  background-color: #cccccc;
}
tr:nth-child(even) {
  background-color: #FFFFFF;
}
<table id="table">
  <tbody id="tbody">
    <tr>
      <td>Test 1</td>
      <td>Test 2</td>
    </tr>
    <tr>
      <td>Test 1</td>
      <td>Test 2</td>
    </tr>
    <tr>
      <td>Test 1</td>
      <td>Test 2</td>
    </tr>
  </tbody>
</table>