3

Like the title says, I want to have a HTML table that allows its columns and rows to be sized independently from the cell content. If rows aren't high enough or columns aren't wide enough to show all of the cell's content, then that content should simply disappear behind the cell.

I came up with the following solution which works fine in chrome (17) and opera (11.61), safari (5), IE (9) but not in firefox:

th, td {
    position: relative;
    overflow: hidden;
}

td > span {
    position: absolute;
    top: 0px;
}

th > div {
    position: relative;
}

(The design is such that each td only contains a span and any "real" content, like text is inside the span within the td. Also, each row has an initial th, and there is a header row containing only th's, and all these th's contain a div. By setting explicit heights and widths of the DIV's inside the th's I can set the width and height of rows.)

The following HTML illustrates the example:

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
    <title>test</title>
    <style type="text/css">
      table {
        border-width: 1px;
        border-style: none none solid solid;
      }

      th, td {
        border-width: 1px;
        border-style: solid solid none none;
      }

      th > div {
        height: 18px;
        width: 50px;
      }

      th, td {
        overflow: hidden;
        position: relative;
      }

      td > span {
        position: absolute;
        top:0px;
      }

      th > div {
        position: relative;
      }
    </style>
  </head>
  <body>
    <table
      cellspacing="0"
      cellpadding="0"
      style="font-size: 10pt"
    >
      <thead>
        <tr>
          <th><div>Header0</div></th>
          <th><div>Header1</div></th>
          <th><div style="width:25px">Header2</div></th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <th><div>Header1</div></th>
          <td
            style="
              vertical-align: bottom
            "
          >
            <span style="
              font-size:6pt;
              background-color: red;
            ">A</span>
          </td>
          <td>
            <span style="
              font-size:6pt;
              background-color: blue;
            ">B</span>
          </td>
        </tr>
        <tr>
          <th><div>Header2</div></th>
          <td>
            <span style="
              font-size:30pt;
              background-color: yellow;
              right: 0px
            ">C</span>
          </td>
          <td>
            <span style="
              font-size:30pt;
              background-color: green;
            ">D</span>
          </td>
        </tr>
        <tr>
          <th><div style="height:10px">Header2</div></th>
          <td>
            <span style="
              font-size:30pt;
              background-color: yellow;
              right: 0px
            ">E</span>
          </td>
          <td>
            <span style="
              font-size:6pt;
              background-color: blue;
            ">F</span>
          </td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

This works fine in chrome and opera, which both position the span relatively to the td (that's why I gave them position: relative). However, in firefox, the position:relative of the td's is completely ignored, and the spans are positioned relative to the first ancestor above the table's rows that have absolute or relative position. So with only the rules above, the tops of the spans are glued to the top of the document body, and if I add:

table {
    position:relative
}

the tops of the spans are glued to the top of the table. But a position:relative applied to the tr's or td's seems to be completely ignored.

Any insight into a working solution will be greatly appreciated.

UPDATE Firefox simply does not support position:relative on table cells. See https://bugzilla.mozilla.org/show_bug.cgi?id=35168#c11. IMO, this is a bug. Despite arguments that "the standard" says that the behavior of this setting is undefined, other browser seem to have zero trouble implementing this in a sensible and useful way so there really doesn't seem to be any good reason from my perspective why firefox wants to ignore this de facto behavior.

After some experimentation, I came up with two alternative solutions - neither of them perfect - which may or may not be useful to others facing this same problem.

1) Using position:static for the table cells almost solves the problem in firefox (without changing the behavior in all other mentioned browsers). Howver, if you do give position:static to the table cells, a new problem surfaces when you set text-align:right on the the table cell. Whereas this again works fine in all other mentioned browsers (they render the span to the right within the cell), firefox again shows a different behavior, and shows the span to the right outside of the cell.

2) Use table-layout:fixed on the table, and put cell content directly in the cell (not in a separate span or div). You can then explicitly set the width and height in the style of the th elements (note that it is not enough to set the width/height of a div inside the th elements - you really need to do that on the th directly. This seems the approach taken by google docs spreadsheets. This approach allows the cell contents to be wider than the cell. However, you cannot make a table row less tall than the height of the cell content.

Roland Bouman
  • 31,125
  • 6
  • 66
  • 67
  • I am getting the gist of your question but am not 100% sure about the details, specifically the part about the `span` usage. Which of your requirements are not met in this fiddle: http://jsfiddle.net/philipf/wa2vR/ – Philip Fourie Feb 25 '12 at 17:31
  • Hi Philip! Thanks for the reply. Looks promising but this requires me to explicitly set the height of the DIVs inside the cells (all of them, as opposed to only setting explicit height and width of the DIVs inside the TH's). If I don't set the height and possibly width of the DIVs inside the TD's in your solution, the row/column size is still overridden by the size of the cell content. – Roland Bouman Feb 25 '12 at 18:41

2 Answers2

1

Firefox does not support position:relative on table elements. See this answer: Does Firefox support position: relative on table elements?

A workaround is to fill all the table cells with relatively positioned divs. The problem, as you have stated, is that you'd have to size all those divs individually. You can use some tricky CSS to streamline this:

  .atable th:nth-child(3) > div,
  .atable td:nth-child(3) > div {
    width:25px;
  }

  .atable tr:nth-child(3) div {
    height:10px
  }

http://jsfiddle.net/chad/9XwyX/2/

Or, you could add classes to the divs to represent each row and column:

http://jsfiddle.net/chad/9XwyX/3/

Neither is particularly clean, but they work in Firefox.

Community
  • 1
  • 1
Chad von Nau
  • 4,316
  • 1
  • 23
  • 34
  • Thanks, this is very helpful information! It's a bit sad though that it seems it will be a lot of work just to make it work for firefox. I'm trying a few more things atm - I'm getting quite promising results by setting position: static on the td's - it's almost working, except that now text-align:right on the td places the cell content directly *outside* the cell (only on firefox, all other browsers keep working exactly as expected and intended) – Roland Bouman Feb 26 '12 at 02:07
  • Marking this as the answer. My question focussed on the position:relative for table cells bit, and this answer provides crucial information to understand why this is not working as intended. Thanks! – Roland Bouman Feb 29 '12 at 06:45
0

You might consider building custom tables from divs and images so it's fully stackable etc.

Andrew
  • 1,037
  • 9
  • 17
  • Have you ever done this? I can imagine this is possible but it seems like a lot of hard work with many unknowns. Can you post an example that demonstrates how this will solve the problem I'm experiencing? From my point of view I "just" need to find a way to make firefox behave, but I may be taking this too lightly. Please provide more detail. TIA, roland. – Roland Bouman Feb 25 '12 at 20:51
  • Yes, for a fully skinnable custom element like list of videos on schedule. – Andrew Feb 25 '12 at 22:25
  • Ok. Could you post sample code, or point me to a site where this is used? TIA – Roland Bouman Feb 26 '12 at 02:04
  • Hi. I would not because my employer would find me out, but I can tell you how I did it - I have used Microsoft Expression Web to create a HTML and then I wrote javascript object{} and I've put all functions there. Javascript object is simply resizing etc all divs which are behaving like a table. All divs are relative position to the place where it's created, it's sized to be always the same size regardless content in it. It can have background pictures, links and so on. – Andrew Feb 26 '12 at 14:54