html-tablecolumn-width

Two Rows in thead, Can't Set Column Widths in Second


I have a table with two rows of headings. I want to set the widths of some of the columns in the second row. I set up a Codepen to test it out. I find that if I remove the first row of headings, it takes the column widths I've specified without a problem. But with the first row of headings, it ignores the widths of the columns in the second row. :(

Please note that I have div's within the th's so I can style the borders.

Here's the Code:

body {
  padding: 10px;
}

.data-table {
  width: 100%;
  border-spacing: 0 4px;
  border-collapse: separate;
  table-layout: fixed;
}/* Remove For SCSS*/
  .title-11, .title-21 {
    width: 40px;
  }
  .title-22 {
    width: 100px;
  }
  .title-24 {
    width: 100px;
  }

  thead tr th {
    border-collapse: separate; 
    border-spacing: 0 5px;
  }
   .title {
     /*
     background: linear-gradient(to right, transparent 0%, #bbb 0%,
       #bbb calc(100% - 10px), 
       transparent calc(100% - 10px)) 0 99% / 100% 1px 
       no-repeat; 
     */
     text-align: left; 
     padding-right: 10px;
  }

  .div-title {
    border-bottom: 1px solid #bbb;
  }
  .hdr-field {
    width: 150px;
  }
  tr .title:last-child {
    padding-right: 0;
  }
  .side-title {
    transform: rotate(-90deg);
    width: 25px;
  }
  .fieldname {
    width: 130px;
  }
  .fieldvalue.dest-data input[type=text] {
    width: 100%;
  }
  .bodySection {
    border-bottom: 10px solid #bbb;
    margin-bottom: 10px;
  }
  tr {
    // border-bottom: 10px solid #bbb;
  }
/*}*//* For SCSS*/
<table class="data-table">
  <thead>
    <tr>
      <th class="title-11"></th>
      <th colSpan="2" class="title title-12">
        <div class="div-title">Source</div>
      </th>
      <th colSpan="2" class="title title-13">
        <div class="div-title">Destination</div>
      </th>
    </tr>
    <tr>
      <th class="title-21"></th>
      <th colSpan="1" class="fieldname title title-22">
        <div class="div-title hdr-field">Field</div>
      </th>
      <th colSpan="1" class="title title-23">
        <div class="div-title">Value</div>
      </th>
      <th colSpan="1" class="fieldname title title-24">
        <div class="div-title hdr-field">Field</div>
      </th>
      <th colSpan="1" class="title title-25">
        <div class="div-title">Value</div>
      </th>
    </tr>
  </thead>
  <tbody class="bodySection">
    <tr>
      <td rowSpan="2" class="side-title">Name</td>
      <td class="fieldname src-data">Short Name</td>
      <td class="fieldvalue src-data"My Store/td>
      <td class="fieldname dest-data">Short Name</td>
      <td class="fieldvalue dest-data"><input type="text" value="My Store" /></td>
    </tr>
    <tr>
      <td class="fieldname src-data">Long Name</td>
      <td class="fieldvalue src-data"My Store/td>
      <td class="fieldname dest-data">Long Name</td>
      <td class="fieldvalue dest-data"><input type="text" value="My Store" /></td>
    </tr>
  </tbody>
  <tbody class="bodySection">
    <tr>
      <td rowSpan="2" class="side-title">Name2</td>
      <td class="fieldname src-data">Short Name2</td>
      <td class="fieldvalue src-data"My Store/td>
      <td class="fieldname dest-data">Short Name2</td>
      <td class="fieldvalue dest-data"><input type="text" value="My Store2" /></td>
    </tr>
    <tr>
      <td class="fieldname src-data">Long Name2</td>
      <td class="fieldvalue src-data"My Store/td>
      <td class="fieldname dest-data">Long Name2</td>
      <td class="fieldvalue dest-data"><input type="text" value="My Store2" /></td>
    </tr>
  </tbody>
</table>

So just to clarify: the question is how to make the Field columns fixed width, while leaving the Value columns to find their own level.

Thank you.


Solution

  • I can't quite understand why and how table lay-outs are calculated, because the algorythm seems pretty complex.

    However, you can achieve the desired lay-out by using a good ol' <colgroup>. There's some not-too-hard to digest info about how to use them in the HTML4 spec | Calculating column width. Note that this also holds true for the new spec (col and colgroup are not deprecated).

    Stick this in between <table> and <thead> in your fiddle:

    <colgroup>
      <col>
      <col width="150">
      <col>
      <col width="150">
      <col>
    </colgroup>
    

    DEMO working:

    body {
      padding: 10px;
    }
    
    .data-table {
      width: 100%;
      border-spacing: 0 4px;
      border-collapse: separate;
      table-layout: fixed;
    }/* Remove For SCSS*/
      .title-11, .title-21 {
        width: 40px; /* Wont be applied */
      }
      .title-22 {
        width: 100px; /* Wont be applied */
      }
      .title-24 {
        width: 100px; /* Wont be applied */
      }
    
      thead tr th {
        border-collapse: separate; 
        border-spacing: 0 5px;
      }
       .title {
         /*
         background: linear-gradient(to right, transparent 0%, #bbb 0%,
           #bbb calc(100% - 10px), 
           transparent calc(100% - 10px)) 0 99% / 100% 1px 
           no-repeat; 
         */
         text-align: left; 
         padding-right: 10px;
      }
    
      .div-title {
        border-bottom: 1px solid #bbb;
      }
      .hdr-field {
        width: 150px;
      }
      tr .title:last-child {
        padding-right: 0;
      }
      .side-title {
        transform: rotate(-90deg);
        width: 25px;
      }
      .fieldname {
        width: 130px;
      }
      .fieldvalue.dest-data input[type=text] {
        width: 100%;
      }
      .bodySection {
        border-bottom: 10px solid #bbb;
        margin-bottom: 10px;
      }
      tr {
        // border-bottom: 10px solid #bbb;
      }
    /*}*//* For SCSS*/
    <table class="data-table">
      <colgroup>
        <col width="40">
        <col width="100">
        <col>
        <col width="100">
        <col>
      </colgroup>
      <thead>
        <tr>
          <th class="title-11"></th>
          <th colSpan="2" class="title title-12">
            <div class="div-title">Source</div>
          </th>
          <th colSpan="2" class="title title-13">
            <div class="div-title">Destination</div>
          </th>
        </tr>
        <tr>
          <th class="title-21"></th>
          <th class="fieldname title title-22">
            <div class="div-title hdr-field">Field</div>
          </th>
          <th class="title title-23">
            <div class="div-title">Value</div>
          </th>
          <th class="fieldname title title-24">
            <div class="div-title hdr-field">Field</div>
          </th>
          <th class="title title-25">
            <div class="div-title">Value</div>
          </th>
        </tr>
      </thead>
      <tbody class="bodySection">
        <tr>
          <td rowSpan="2" class="side-title">Name</td>
          <td class="fieldname src-data">Short Name</td>
          <td class="fieldvalue src-data"My Store/td>
          <td class="fieldname dest-data">Short Name</td>
          <td class="fieldvalue dest-data"><input type="text" value="My Store" /></td>
        </tr>
        <tr>
          <td class="fieldname src-data">Long Name</td>
          <td class="fieldvalue src-data"My Store/td>
          <td class="fieldname dest-data">Long Name</td>
          <td class="fieldvalue dest-data"><input type="text" value="My Store" /></td>
        </tr>
      </tbody>
      <tbody class="bodySection">
        <tr>
          <td rowSpan="2" class="side-title">Name2</td>
          <td class="fieldname src-data">Short Name2</td>
          <td class="fieldvalue src-data"My Store/td>
          <td class="fieldname dest-data">Short Name2</td>
          <td class="fieldvalue dest-data"><input type="text" value="My Store2" /></td>
        </tr>
        <tr>
          <td class="fieldname src-data">Long Name2</td>
          <td class="fieldvalue src-data"My Store/td>
          <td class="fieldname dest-data">Long Name2</td>
          <td class="fieldvalue dest-data"><input type="text" value="My Store2" /></td>
        </tr>
      </tbody>
    </table>