Search code examples
htmlcssborderhtml-tablew3c

CSS border issue with THEAD TBODY and COLSPAN


i have an issue with css/html table:
When I use thead and tbody tags with a colspan attribute, the bottom border of the header is divided.
The gap size is dependent of the th border width.

Did you have a solution to get a continuous border on header bottom (without removing thead and tbody) ?

JSFiddle example

table {
  border-collapse: collapse;
}

th {
  border: 4px solid red;
  border-bottom: 4px solid black
}

td {
  border: 4px solid blue;
}

thead tr {
  border-bottom: 5px solid green
}

table {
  border-collapse: collapse;
}

th {
  border: 4px solid red;
  border-bottom: 4px solid black
}

td {
  border: 4px solid blue;
}

thead tr {
  border-bottom: 5px solid green
}
with THEAD and TBODY but without COLSPAN
<table>
  <thead>
    <tr>
      <th>
        Column 1
      </th>
      <th>
        Column 2
      </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>
        Content 1
      </td>
      <td>
        Content 2
      </td>
    </tr>
  </tbody>
</table>
<br /> COLSPAN with THEAD and TBODY <span style="background:yellow">(css bug in the middle of green border ?)</span>
<table>
  <thead>
    <tr>
      <th>
        Column 1
      </th>
      <th>
        Column 2
      </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td colspan="2">
        Content 1 and 2 (merged cells)
      </td>
    </tr>
  </tbody>
</table>
<br /> COLSPAN without THEAD and TBODY
<table>
  <tr>
    <th>
      Column 1
    </th>
    <th>
      Column 2
    </th>
  </tr>
  <tr>
    <td colspan="2">
      Content 1 and 2 (merged cells)
    </td>
  </tr>
</table>


Solution

  • The corner rendering between collapsed borders does not seem well-specified, so it's not clear that this is actually a bug rather than just a variance in behaviour.

    I did find a horrible workaround for Firefox, by creating a pseudo second row in the thead, and then hiding it, and also hiding the top border of the first tbody row like this:

    thead:after {
        content:'';
        display:table-row;  /* see note below */
        position:absolute;
        visibility:hidden;
    }
    
    tbody tr:first-child td {
        border-top-width:0;
    }
    

    (Note that the display:table-row is just for show. In reality, the position:absolute causes the pseudo-element to be display:block regardless of whether the display property is set to table-row or left at its default inline. The table layout of the container will then cause that block to be wrapped in anonymous table objects of table-row and table-cell to form a well structured table.)

    table {
      border-collapse: collapse;
    }
    
    th {
      border: 4px solid red;
      border-bottom: 4px solid black
    }
    
    td {
      border: 4px solid blue;
    }
    
    thead tr {
      border-bottom: 5px solid green
    }
    
    table ~ table thead:after {
        content:'';
        position:absolute;
        visibility:hidden;
    }
    table ~ table tbody tr:first-child td {
        border-top-width:0;
    }
    with THEAD and TBODY but without COLSPAN
    <table>
      <thead>
        <tr>
          <th>
            Column 1
          </th>
          <th>
            Column 2
          </th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>
            Content 1
          </td>
          <td>
            Content 2
          </td>
        </tr>
      </tbody>
    </table>
    <br /> COLSPAN with THEAD and TBODY <span style="background:yellow">(css bug in the middle of green border ?)</span>
    <table>
      <thead>
        <tr>
          <th>
            Column 1
          </th>
          <th>
            Column 2
          </th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td colspan="2">
            Content 1 and 2 (merged cells)
          </td>
        </tr>
      </tbody>
    </table>
    <br /> COLSPAN without THEAD and TBODY
    <table>
      <tr>
        <th>
          Column 1
        </th>
        <th>
          Column 2
        </th>
      </tr>
      <tr>
        <td colspan="2">
          Content 1 and 2 (merged cells)
        </td>
      </tr>
    </table>