Vincent
Vincent

Reputation: 1730

Table TD (rowspan) content hidden with TR visibility set to "collapse"

I have built an HTML table which intermediate rows are hidden with CSS using visibility:collapse

Only the first and last rows of the table are visible by default.

In this table, there is a column on the right that was set using rowspan. This column can contain multiple lines of text.

My problem is that the whole content put in this column seems to be truncated if its height is bigger than the combined height of the table rows that are displayed by default (the first one and the last one).

.hide {
  visibility: collapse
}

body {
  padding: 2rem;
}
<table border="1">
  <tr>
    <td>A1</td>
    <td>A2</td>
    <td rowspan="3">Text 1<br>Text 2<br>Text 3<br>Text 4<br>Text 5<br>Text 6</td>
  </tr>
  <tr class="hide">
    <td>B1</td>
    <td>B2</td>
  </tr>
  <tr>
    <td>C1</td>
    <td>C2</td>
  </tr>
</table>

What should I change in the CSS to get all the lines of "Text" of the rowspan cell displayed instead of being truncated? JavaScript cannot be used.

Upvotes: 6

Views: 1693

Answers (7)

Sowaiba9801
Sowaiba9801

Reputation: 81

.hide {
  position: absolute;
  left: -999em;
}

body {
  padding: 2rem;
}
<table border="1">
  <tr>
    <td>A1</td>
    <td>A2</td>
    <td rowspan="3">Text 1<br>Text 2<br>Text 3<br>Text 4<br>Text 5<br>Text 6</td>
  </tr>
  <tr class="hide">
    <td>B1</td>
    <td>B2</td>
  </tr>
  <tr>
    <td>C1</td>
    <td>C2</td>
  </tr>
</table>

display: none; Element is removed from the normal flow and hidden; the space it occupied is collapsed. Content is ignored by screen readers. So, if you want to hide it but make it visible for screen readers you can use the above code in my opinion.


Upvotes: 2

Rene van der Lende
Rene van der Lende

Reputation: 5281

Digging into this problem it became clear that the problem description and the way the <td rowspan="3"> is constructed in the example puts everyone off track. Including me...

The answer, after some utter frustrating hours, is actually quite simple: the OP is trying to force 6 rows of text into a 3 rows space because of the 5 <br>s. There is just not room enough for the content, so the cell overflows. The rowspan should not read 3, but 6!

Once the room issue has been revealed, one solution is to create more table rows to accommodate for the 6 rows and make arrangements for using a scrollbar, while clipping the overflowing cell when there are less than 6 rows available in the table.

On page table: The Table element: Displaying large tables in small spaces MDN defines a table as table { display: block; overflow: auto } and introduces tbody { white-space: nowrap } to enable scrolling of table content.

I created some commented code showing the original and solution 1 with simple toggles for class .hide and additional rows.

Do I like it? No, far from, but this is how the table mechanism appears to work. I don't think it is a bug, just something we need to work around...

UPDATE

In reply to @MaxiGui's fair point below, me not honoring the OPs "What should I change in the CSS to get all the lines of "Text" of the rowspan cell displayed instead of being truncated" question, I added another solution.

Added solution 2 shows the OP original code, but simply toggles class .hide between display: none/table-row instead of visibility: collapse/visible.

Because if all size properties of an element have to be set to 0 (zero, nullified) to mimick display: none, it is far less complicated to use the display property instead of visibility to hide a table row.

FYI, the OP did not explicitely mention the requirement to retain visibility...

/* original code */
body    { padding: 2rem }
.hide   { visibility: collapse }

/* solution 1 */
.solution {
    display: inline-block;
    overflow: auto; /* to show scrollbars when required */
}

/*
    MDN excerpt
    (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table#displaying_large_tables_in_small_spaces)

    When looking at these styles you'll notice that table's display property
    has been set to block. While this allows scrolling, the table loses some
    of its integrity, and table cells try to become as small as possible.
    To mitigate this issue white-space has been set to nowrap on the <tbody>.
*/

.solution tbody { white-space: nowrap }

.solution td {
    overflow: hidden;    /* clips excess content */
    vertical-align: top; /* moves content to top of cell */
}

#tgl-line ~ .solution {
    min-width: calc(6.75rem + 17px); /* create some room for content and scrollbar */
    /* just for demo, change to max-width when .solution { display: block } */
}

#tgl-line:checked ~ table .hide     { visibility: visible } /* both tables */
#tgl-line:checked ~ .solution       { min-width: 6.75rem  } /* solution only */

#tgl-rows         ~ .solution .rows { display: none }       /* additional rows hidden */
#tgl-rows:checked ~ .solution .rows { display: table-row }  /* in view... */

/* solution 2 */
.hide-d                             { display: none } /* alt classname for solution 2 */
#tgl-line:checked ~ table .hide-d   { display: table-row }

/* eye-candy */
h2 { margin-top: 4rem }
<input id ="tgl-line" type="checkbox">
<label for="tgl-line">toggle .hide (all examples)</label>

<h2>original: toggle 'visibility' (rowspan=3)</h2>
<table border="1">
  <tr>
    <td>A1</td>
    <td>A2</td>
    <td rowspan="3">Text 1<br>Text 2<br>Text 3<br>Text 4<br>Text 5<br>Text 6</td>
  </tr>
  <tr class="hide">
    <td>B1</td>
    <td>B2</td>
  </tr>
  <tr>
    <td>C1</td>
    <td>C2</td>
  </tr>
</table>

<h2>solution 1: toggle 'visibility' (rowspan=6)</h2>

<input id ="tgl-rows" type="checkbox">
<label for="tgl-rows">toggle rows</label>
<br><br>
<table class="solution" border="1">
    <tbody>
        <tr>
            <td>A1</td>
            <td>A2</td>
            <td rowspan="6" class="special">Text 1<br>Text 2<br>Text 3<br>Text 4<br>Text 5<br>Text 6</td>
        </tr>
        <tr class="hide">
            <td>B1</td>
            <td>B2</td>
        </tr>
        <tr>
            <td>C1</td>
            <td>C2</td>
        </tr>
        <tr class="rows">
            <td>D1</td>
            <td>D2</td>
        </tr>
        <tr class="rows">
            <td>E1</td>
            <td>E2</td>
        </tr>
        <tr class="rows">
            <td>F1</td>
            <td>F2</td>
        </tr>
    </tbody>
</table>

<h2>solution 2: toggle 'display' (rowspan=3)</h2>
<table border="1">
  <tr>
    <td>A1</td>
    <td>A2</td>
    <td rowspan="3">Text 1<br>Text 2<br>Text 3<br>Text 4<br>Text 5<br>Text 6</td>
  </tr>
  <tr class="hide-d">
    <td>B1</td>
    <td>B2</td>
  </tr>
  <tr>
    <td>C1</td>
    <td>C2</td>
  </tr>
</table>

.

Upvotes: 3

Mubeen Ahmad
Mubeen Ahmad

Reputation: 438

You can scroll your table data, Look at the following code:

.hide {
  visibility: collapse
}

body {
  padding: 2rem;
}

.table-data {
  overflow-y: auto;
}
.table-data::-webkit-scrollbar {
    display: none;
}
<table border="1">
  <tr>
    <td>A1</td>
    <td>A2</td>
    <td rowspan="3" class="table-data">Text 1<br>Text 2<br>Text 3<br>Text 4<br>Text 5<br>Text 6</td>
  </tr>
  <tr class="hide">
    <td>B1</td>
    <td>B2</td>
  </tr>
  <tr>
    <td>C1</td>
    <td>C2</td>
  </tr>
</table>

Upvotes: 0

iqbal hossain
iqbal hossain

Reputation: 133

Hello if you need display your content properly, you should to add a class and make this class width: auto; overflow: auto; height: auto; I recommend to you apply this ->

.hide {
  visibility: collapse
}

body {
  padding: 2rem;
}

.meta {
  width: auto;
  overflow: auto;
  height: auto;
}
<table border="1">
  <tr>
    <td>A1</td>
    <td>A2</td>
    <td class="meta" rowspan="3">Text 1<br>Text 2<br>Text 3<br>Text 4<br>Text 5<br>Text 6</td>
  </tr>
  <tr class="hide">
    <td>B1</td>
    <td>B2</td>
  </tr>
  <tr>
    <td>C1</td>
    <td>C2</td>
  </tr>
</table>

but it would depend what you are trying to do.

Upvotes: 0

Rohit Tingare
Rohit Tingare

Reputation: 21

You can use position: absolute and top: -1000000px By using this code you can achieve your required output.

.hide {
  position: absolute;
  top: -100000px;
}

body {
  padding: 2rem;
}
<table border="1">
  <tr>
    <td>A1</td>
    <td>A2</td>
    <td rowspan="3">Text 1<br>Text 2<br>Text 3<br>Text 4<br>Text 5<br>Text 6<br>Text 7<br>Text 8<br>Text 9</td>
  </tr>
  <tr class="hide">
    <td>B1</td>
    <td>B2</td>
  </tr>
  <tr>
    <td>C1</td>
    <td>C2</td>
  </tr>
</table>

I hope this will resolve your issue.

Upvotes: 0

MaxiGui
MaxiGui

Reputation: 6358

If you really need, you can always add line-height: 0; to .hide as below:

.hide {
  visibility: collapse;
  line-height: 0; 
}

This solution has been given here: CSS: "visibility: collapse" still takes up space

I would still recommend to apply the visibility:collapse on the td as it would let more space to the rowspan cell as you can see the diff between the 2 tables.

I still prefer the use of display:none; but it would depend what you are trying to do.

DEMO

#hide .hide {
  visibility: collapse;
  line-height: 0; 
}

body {
  padding: 2rem;
}
/* SECOND table - collapse on td */
#td-hide .hide > td{
  visibility: collapse;
  line-height: 0;
  height:0;
  border: 0;
  padding:0;
  margin:0;
}
.container{
  display:flex;
}
.container > div{
  margin:0 auto;
}
<div class="container">
  <div>
    <h3>visibility: collapse on tr</h3>
    <table id="hide" border="1">
      <tr>
        <td>A1</td>
        <td>A2</td>
        <td rowspan="3">Text 1<br>Text 2<br>Text 3<br>Text 4<br>Text 5<br>Text 6</td>
      </tr>
      <tr class="hide">
        <td>B1</td>
        <td>B2</td>
      </tr>
      <tr>
        <td>C1</td>
        <td>C2</td>
      </tr>
    </table>
  </div>
    <!-- Second table with collapse on td -->
  <div>
    <h3>visibility: collapse on td</h3>
    <table id="td-hide" border="1">
      <tr>
        <td>A1</td>
        <td>A2</td>
        <td rowspan="3">Text 1<br>Text 2<br>Text 3<br>Text 4<br>Text 5<br>Text 6</td>
      </tr>
      <tr class="hide">
        <td>B1</td>
        <td>B2</td>
      </tr>
      <tr>
        <td>C1</td>
        <td>C2</td>
      </tr>
    </table>
  </div>
</div>

Upvotes: 1

Faridullah Khorshid
Faridullah Khorshid

Reputation: 61

I think it's better to use display:none; or visibility:hidden;. Or use overflow:auto; on TD, but then you will get a scrollbar jsfiddle

About visibility:collapse; check out this post from css-tricks

.hide{

  /* Using this, will mess up everything */
  /* visibility:collapse; */
  
  /* Using this, will give you something where the middle row is hidden */
  /* visibility:hidden; */
  
  /* display none works the best */
  display: none;
}
<table border="1">
<tbody>
   <tr>
      <td>A1</td>
      <td>A2</td>
      <td rowspan="3">Text 1<br>Text 2<br>Text 3<br>Text 4<br>Text 5<br>Text 6</td>
   </tr>
   <tr class="hide">
      <td>B1</td>
      <td>B2</td>
   </tr>
   <tr>
      <td>C1</td>
      <td>C2</td>
   </tr>
</tbody>
</table>

Upvotes: 6

Related Questions