4

I have a scenario which requires a complex layout within table header <th> elements. I want to approach the problem by making the <th> elements a flex container.

However, if I start with this minimal example

enter image description here

and change the <th> elements to display: inline-flex, the table becomes:

enter image description here

I.e., the column width of the header no longer matches the column width of the <td> elements.

How can I make use of flexbox inside the header without messing up column rendering?

Edit to clarify the use case: My <th> elements will eventually contain multiple elements, with left+right alignment (similar to this question). In addition I want to be able to control the stretch behavior (that's why flexbox instead of just floats).


Example jsfiddle:

<table>
  <thead>
    <tr>
      <th class="column-header">A</th>
      <th class="column-header">B</th>
      <th class="column-header">C</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Something</td>
      <td>Something</td>
      <td>Something</td>
    </tr>
  </tbody>
</table>
table, th, td {
  border: 1px solid #000;
}

.column-header {
  display: inline-flex;
}
bluenote10
  • 23,414
  • 14
  • 122
  • 178
  • Can you use a wrapper-element inside `th` that has `display: flex`? – insertusernamehere Jun 20 '19 at 11:44
  • @insertusernamehere I would have preferred to avoid a wrapper, but if that is that is the only solution it is fine as well. – bluenote10 Jun 20 '19 at 11:46
  • 2
    is this what you are looking for? - https://jsfiddle.net/mjyzs4o2/ - I am also not sure why you would want to use display flex in a table as using divs would be better – Andrew Jun 20 '19 at 11:49
  • @Andrew No that's not what I'm looking for. I don't want to make the `` a flex, but the ``. In my use case I need to align various things in each ``, multiple left aligned text elements, right aligned symbols, some of them should stretch etc. – bluenote10 Jun 20 '19 at 11:55
  • @bluenote10 you can put your `` also as `display:inline-flex` and then add a min-witdh – xmaster Jun 20 '19 at 12:06

1 Answers1

14

My elements will eventually contain multiple elements, with left+right alignment. In addition I want to be able to control the stretch behavior (that's why flexbox instead of just floats).

In that case, you need to use a div inside each th and flex that.

table,
th,
td {
  border: 1px solid #000;
}

.column-header div {
  display: flex;
  justify-content: space-between;
}
<table>
  <thead>
    <tr>
      <th class="column-header">
        <div><span>A</span><span>A</span></div>
      </th>
      <th class="column-header">
        <div><span>B</span><span>B</span></div>
      </th>
      <th class="column-header">
        <div><span>C</span><span>C</span></div>
      </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Something</td>
      <td>Something</td>
      <td>Something</td>
    </tr>
  </tbody>
</table>
Paulie_D
  • 107,962
  • 13
  • 142
  • 161
  • 2
    Would be interesting to know why that is needed, is there a rule that what can and what cannot be a flex? – bluenote10 Jun 20 '19 at 12:10
  • In tables, yes. You're breaking the layout algorithm essentially. A `div` is semantically null so it's useful as a wrapper without actually meaning anything. – Paulie_D Jun 20 '19 at 12:12
  • I'm asking because I was searching for official specs on that and couldn't find anything. There are [answers on SO](https://stackoverflow.com/a/48749336) that suggest that `display: flex` is valid for `th`. – bluenote10 Jun 20 '19 at 15:27
  • 5
    It's valid, yes, but that's not the issue. The issue is that giving a cell `display:flex` overrides the default of `display:table-cell` (set via the user agent default stylesheet). That is an essential piece of the table layout algorithm, as Paulie_D was saying. Without it, you would have to override the display property on the parent `` element and set `display:table` on the thead's sibling tbody element(s). **And** you would most likely need to set an explicit width on the cells of each column. – Kravimir Jun 21 '19 at 06:00