3

Consider the following table, representing a graph, with colours to show cell areas:

<style>
   .y-axis {
       background-color: red;
       display:flex;
       flex-flow: column-reverse nowrap;
       justify-content: space-between;
   }

   .graph {
       background-color:purple;
       width:300px;
       height:300px;
       border-left:1px solid black;
       border-bottom:1px solid black;
   }

   .x-axis {
       display:flex;
       flex-flow:row nowrap;
       justify-content: space-around;
       background-color:yellow;
   }
</style>
<table style="border-collapse: collapse;">
    <tbody>
        <tr>
            <td rowspan="3" class="y-axis">
                <span>0</span>
                <span>1</span>
                <span>2</span>
                <span>3</span>
            </td>
            <td style="background-color: blue; height:5px;"></td>
        </tr>
        <tr>
            <td class="graph"></td>
        </tr>
        <tr>
            <td style="background-color: blue; height:5px;"></td>
        </tr>
        <tr>
            <td></td>
            <td class="x-axis">
                <span>1</span>
                <span>2</span>
                <span>3</span>
                <span>4</span>
                <span>5</span>
            </td>
        </tr>
    </tbody>
</table>

https://jsfiddle.net/o6x2rehy/

In both Firefox 58 and IE 12 (and presumably all other browsers), the first TD element ignores its rowspan attribute due to the presence of display:flex;.

The table is supposed to look like

<style>
   .y-axis {
       background-color: red;
       display:flex;
       flex-flow: column-reverse nowrap;
       justify-content: space-between;
   }

   .graph {
       background-color:purple;
       width:300px;
       height:300px;
       border-left:1px solid black;
       border-bottom:1px solid black;
   }

   .x-axis {
       display:flex;
       flex-flow:row nowrap;
       justify-content: space-around;
       background-color:yellow;
   }
</style>
<table style="border-collapse: collapse;">
    <tbody>
        <tr>
            <td rowspan="3">
                <div class="y-axis">
                    <span>0</span>
                    <span>1</span>
                    <span>2</span>
                    <span>3</span>
                </div>
            </td>
            <td style="background-color: blue; height:5px;"></td>
        </tr>
        <tr>
            <td class="graph"></td>
        </tr>
        <tr>
            <td style="background-color: blue; height:5px;"></td>
        </tr>
        <tr>
            <td></td>
            <td class="x-axis">
                <span>1</span>
                <span>2</span>
                <span>3</span>
                <span>4</span>
                <span>5</span>
            </td>
        </tr>
    </tbody>
</table>

https://jsfiddle.net/bpqnw3sc/1/

but with the first div swelling to consume all vertical space in the first cell.

Is the table cell ignoring its rowspan attribute expected behaviour?

If so, is there a CSS-only way to instruct the div in the latter code to swell to occupy the full vertical space in the cell? (Assume the height of the main graph area (purple), currently fixed at 300px, will be variable and unknown a priori.)

COTO
  • 163
  • 1
  • 5
  • Is there a reason you use tables? To me it seems you won't use the table structure anyway. – Dejan.S Feb 04 '18 at 14:18
  • Why don't you write your `style` as CSS? It would be much more readable – GalAbra Feb 04 '18 at 14:20
  • Why don't you write your style as CSS? It would be much more readable. BTW if I remove `display:flex;` it works as required – GalAbra Feb 04 '18 at 14:30
  • @Dejan.S: I prefer a single table to a row flex container containing multiple column flex containers, which would be required for my application. – COTO Feb 04 '18 at 14:30
  • @GalAbra: Removing "display:flex;" fixes the problem with the cell ignoring "rowspan", but then the contents of the cell aren't laid out properly. They're supposed to be stretched from bottom to top vertically in the cell. As for extracting the inline styles to a "style" element, the inline styles seemed preferable to me, but I'll pull them out if you think that will help. – COTO Feb 04 '18 at 14:35
  • I'm afraid the easiest way to implement this dynamically is using JS... – GalAbra Feb 04 '18 at 15:13
  • Considering you just mutilated your table's layout by changing parts of it to flex containers, I don't see how you could expect to reconcile those parts with any of their clearly table-layout-specific attributes. – BoltClock Feb 04 '18 at 15:15
  • @BoltClock: I suppose I was hoping that using "display:flex;" in a table cell would flag the cell as a flexbox container without screwing with its normal layout (at least as far as respecting "rowspan" is concerned). It's beyond me why the standard doesn't have a "flex-table-cell", etc. property value to allow this kind of thing. Currently I see no way of making this layout work with flexbox without either: i) fixing the width of the Y axis, ii) fixing the height of the X axis, or iii) fixing the height of the plot, none of which I want to do. – COTO Feb 04 '18 at 15:27
  • @COTO: Well, that's fair. I should remind myself that it's not immediately obvious that display: flex represents specifically a block-level flex container. As for table-cell flex containers, I agree. Even css-display continues to insist that table-cells are necessarily flow roots, with no room for compromise. – BoltClock Feb 04 '18 at 15:32

1 Answers1

1

Is it expected behaviour for a table cell with “display:flex;” to ignore the “rowspan” attribute?

Yes.

The reason is that the rowspan attribute affect the table cell <td> element, and that element only, so when one add display: flex to it, it stops being a table cell.


Is there a CSS-only way to instruct the div in the latter code to occupy the full vertical space in the cell? (Assume the height of the main graph area (purple), currently fixed at 300px, will be variable and unknown a priori.)

No

(well, maybe, if one of these workarounds is an option: Make a DIV fill an entire table cell)


I recommend to not use <table> for layout, and a similar layout using Flexbox, can be achieved, with some notable limitations, described here:

So if the cells can have fixed width's, like a table using table-layout: fixed, you can also span elements cross more than one column, similar to what rowspan does.


Here is a start using Flexbox

Fiddle demo

Stack snippet

.container {
  display: inline-block;
}

.flex {
  display: flex;
}

.flex.column {
  flex-direction: column;
}

.flex.column-reverse {
  flex-direction: column-reverse;
}

.bkg-yellow {
  background-color: yellow;
}
.bkg-yellow span {
  flex: 1;
}

.bkg-purple {
  background-color: purple;
  width: 300px;
  height: 300px;
  border-left: 1px solid black;
  border-bottom: 1px solid black;
}

.bkg-red {
  background-color: red;
}
.bkg-red span {
  flex: 1;
}

.bkg-blue {
  background-color: blue;
  height: 5px;
}
<div class="container">
  <div class="flex">
    <div class="flex column-reverse bkg-red">
      <span>0</span>
      <span>1</span>
      <span>2</span>
      <span>3</span>
    </div>

    <div class="flex column">
      <div class="bkg-blue"></div>

      <div class="bkg-purple"></div>

      <div class="bkg-blue"></div>

      <div class="flex bkg-yellow">
        <span>1</span>
        <span>2</span>
        <span>3</span>
        <span>4</span>
        <span>5</span>
      </div>

    </div>
  </div>
</div>
Asons
  • 84,923
  • 12
  • 110
  • 165
  • The relative widths of the cells will be roughly what is shown in the latter example, hence a single flexbox container won't suffice. Do you know of any way of getting the Y-axis DIV to swell to the full height of the table cell? – COTO Feb 04 '18 at 14:47
  • https://jsfiddle.net/bpqnw3sc/2/ This shows the desired layout, but it's accomplished by manually setting the height of the Y-axis DIV to 314px (= 300 + 5 + 5 + 1 + 1 + 1 + 1), and the number 300 (the height of the graph) won't be known in actual implementation. – COTO Feb 04 '18 at 14:55
  • @COTO No, there is no way doing that dynamically within a table cell, not even with absolute positioning. So why the need of ``?
    – Asons Feb 04 '18 at 15:04
  • A table was just nicer. I don't know how to accomplish the desired layout with any fewer than five separate flexbox containers. – COTO Feb 04 '18 at 15:09
  • @COTO Figured :) ... updated my answer. Let me know if neither of those workarounds is viable, and I will suggest a pure Flexbox solution. And an upvote would be appreciated :) – Asons Feb 04 '18 at 15:15
  • The layout of a is also implemented with CSS display: table-cell. The question is asking why a * with display: flex* ignores its rowspan attribute, and the reason for that is quite obvious... – BoltClock Feb 04 '18 at 15:22
  • @BoltClock Which my first part answers, and even if it is obvious I decided to add it, ... and then there is a follow up question. Is there something you think I missed? – Asons Feb 04 '18 at 15:36
  • You've got my upvote, LG, although none of the workarounds in "DIV fill an entire table cell" work here (since I can't fix the height of the table), and the limitations you mention with the flexbox-only implementation aren't acceptable. I guess it's Javascript for me. :P – COTO Feb 04 '18 at 15:40
  • I would say something like "The reason is that when you make a display: flex, it's no longer a table cell." – BoltClock Feb 04 '18 at 15:41
  • @COTO I added a Flexbox sample for you :) – Asons Feb 04 '18 at 15:47
  • The sample is great except for the fact that the 0 on the Y-axis should have its center roughly aligned with the bottom of the purple. As far as I can tell, this can't be done without fixing the height of the X-axis, correct? – COTO Feb 04 '18 at 16:01
  • @COTO Assuming the _yellow_ can have a known height, you can do something like this: https://jsfiddle.net/t8vrym3h/4/ .... or if it can't, but the _red_ can have a known width, there is a solution for that – Asons Feb 04 '18 at 16:45