Benjamin Spiegel
Benjamin Spiegel

Reputation: 113

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?

Upvotes: 4

Views: 1730

Answers (1)

xorspark
xorspark

Reputation: 16012

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>

Upvotes: 4

Related Questions