John Coleman
John Coleman

Reputation: 93

How to retain the width of table columns when hiding columns?

I have a table that has six columns, five of which can be hidden based on user selection(s). The issue that I'm having is that when a column is hidden all other columns expand to fill the space that the hidden column occupied. What I would like to occur instead is for the column to just hide and the remaining columns shift to the left while retaining the widths that they were given. None of the answers that I have found on here seem to address this particular issue.

Below is snips of both my js and css along with screen grabs.

js:

      <table className="hours table table-bordered table-sm" table-layout="fixed">
        <thead>
          <tr>
            <th scope="col"
              colSpan="3"
              className="row-dow"
            >
              Hours
            </th>
            <th
              scope="col"
              colSpan="2"
              align="center"
              hidden={this.state.kitchenHoursSame}
              className="row-16"
            >
              Kitchen Hours
            </th>
            <th
              scope="col"
              colSpan="2"
              align="center"
              hidden={!this.state.breakfast}
              className="row-16"
            >
              Breakfast Special
            </th>
            ...
          </tr>
          <tr>
            <th
              scope="col"
            // className="row-8 "
            >
              Day
            </th>
            <th
              scope="col"
              className="row-8"
            >
              Open
            </th>
            <th
              scope="col"
              className="row-8"
            >
              Close
            </th>
            <th
              scope="col"
              hidden={this.state.kitchenHoursSame}
              className="row-8"
            >
              Open
            </th>
            <th
              scope="col"
              hidden={this.state.kitchenHoursSame}
              className="row-8"
            >
              Close
            </th>
            <th
              scope="col"
              hidden={!this.state.breakfast}
              className="row-8"
            >
              1234567890123
            </th>
            <th
              scope="col"
              hidden={!this.state.breakfast}
              className="row-8"
            >
              End
            </th>
            ...
          </tr>
        </thead>
        <tbody>
          {this.state.DOW.map((dowList, i) =>
            <tr>
              <th scope="row" key={dowList.i}>{dowList.long}</th>
              <td>
                <select name="timeofday"
                  value={this.state.timeofday}
                  onChange={this.handleInputChange}>
                  <option>
                    (open)
                  </option>
                </select>
              </td>
              ...
            </tr>
          )}
        </tbody>
      </table>

css:

.hours {
    table-layout: fixed;
    /* width: 90%; */
    width: 1500px;
    white-space: nowrap;
  }
  .hours td {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }


.row-dow {
    width: 20px;
  }
.row-16 {
  width: 16px;
}
.row-8 {
  width: 8px;
}

All columns selected

Kitchen column hidden

Any help would be appreciated even if it is being told that I shouldn't be using tables and should be using something else.

Upvotes: 0

Views: 3824

Answers (2)

Abhishek Kumar
Abhishek Kumar

Reputation: 2539

If you have no problem rendering table content everytime, this can be handled using css property visibility: hidden; which hides the element with space occupied in the dom.
See for : visibilty hidden

Approach :

  • Instead of using hidden attribute on th or td, i have used class = hideColumn which is defined to hide the element.
  • Next border: none to remove the border from the element.

    In your case, you can also use 'class' attribute to achieve this.

    If this is not helpful please let me know in the comments,
    or if anything can be done to take this near to required solution.

table {
    font-family: arial, sans-serif;
    border-collapse: collapse;
    width: 100%;
    font-size: 10px;
}

.hideColumn {
    visibility: hidden;
    border: none;
}

h2 { 
    font-size: 12px;
}

td, th {
    border: 1px solid #dddddd;
    text-align: left;
    padding: 8px;
}
<h2>Visible All Column Table</h2>

<table>
  <tr>
    <th >Company</th>
    <th>Contact</th>
    <th>Country</th>
  </tr>
  <tr >
    <td >Alfreds Futterkiste</td>
    <td>Maria Anders</td>
    <td>Germany</td>
  </tr>
  <tr>
    <td>Centro comercial Moctezuma</td>
    <td>Francisco Chang</td>
    <td>Mexico</td>
  </tr>
</table>
<br>
<h2>Hidden 1st Column Table</h2>

<table>
  <tr>
    <th class='hideColumn'>Company</th>
    <th>Contact</th>
    <th>Country</th>
  </tr>
  <tr >
    <td class='hideColumn'>Alfreds Futterkiste</td>
    <td>Maria Anders</td>
    <td>Germany</td>
  </tr>
  <tr>
    <td class='hideColumn'>Centro comercial Moctezuma</td>
    <td>Francisco Chang</td>
    <td>Mexico</td>
  </tr>
</table>
<br>
<h2>Hidden 2nd Column Table</h2>

<table>
  <tr>
    <th >Company</th>
    <th class='hideColumn'>Contact</th>
    <th>Country</th>
  </tr>
  <tr >
    <td >Alfreds Futterkiste</td>
    <td class='hideColumn'>Maria Anders</td>
    <td>Germany</td>
  </tr>
  <tr>
    <td >Centro comercial Moctezuma</td>
    <td class='hideColumn'>Francisco Chang</td>
    <td>Mexico</td>
  </tr>
</table>

Approach 2:

  • Just make the text transparent.

.otherDiv table {
    font-family: arial, sans-serif;
    border-collapse: collapse;
    width: 100%;
    font-size: 10px;
    border: 1px solid #dddddd;
}

.otherDiv .hideColumn {
    color: transparent;
}

h2 { 
    font-size: 12px;
}

.otherDiv td, th {
    border-top: 1px solid #dddddd;
    border-bottom: 1px solid #dddddd;
    text-align: left;
    padding: 8px;
}
<div class='otherDiv'>
<h2>Visible All Column Table</h2>

<table>
  <tr>
    <th >Company</th>
    <th>Contact</th>
    <th>Country</th>
  </tr>
  <tr >
    <td >Alfreds Futterkiste</td>
    <td>Maria Anders</td>
    <td>Germany</td>
  </tr>
  <tr>
    <td>Centro comercial Moctezuma</td>
    <td>Francisco Chang</td>
    <td>Mexico</td>
  </tr>
</table>
<br>
<h2>Hidden 1st Column Table</h2>

<table>
  <tr>
    <th class='hideColumn'>Company</th>
    <th>Contact</th>
    <th>Country</th>
  </tr>
  <tr >
    <td class='hideColumn'>Alfreds Futterkiste</td>
    <td>Maria Anders</td>
    <td>Germany</td>
  </tr>
  <tr>
    <td class='hideColumn'>Centro comercial Moctezuma</td>
    <td>Francisco Chang</td>
    <td>Mexico</td>
  </tr>
</table>
<br>
<h2>Hidden 2nd Column Table</h2>

<table>
  <tr>
    <th >Company</th>
    <th class='hideColumn'>Contact</th>
    <th>Country</th>
  </tr>
  <tr >
    <td >Alfreds Futterkiste</td>
    <td class='hideColumn'>Maria Anders</td>
    <td>Germany</td>
  </tr>
  <tr>
    <td >Centro comercial Moctezuma</td>
    <td class='hideColumn'>Francisco Chang</td>
    <td>Mexico</td>
  </tr>
</table>

</div>

Upvotes: 2

Ivan Burnaev
Ivan Burnaev

Reputation: 2730

The snippet below shows you how different width defined tables behave when a column is going to be deleted.

window.addEventListener("load", () => {
  const firstTDs = Array.from(
    document.querySelectorAll("td:nth-child(3)")
  ).concat(Array.from(document.querySelectorAll("th:nth-child(3)")));

  document.querySelector(".remove").addEventListener(
    "click",
    () => {
      firstTDs.forEach(td => {
        td.parentNode.removeChild(td);
      });
    },
    { once: true }
  );
});
.full-width {
  width: 100%;
}

.fixed-width {
  width: 600px;
}
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link rel="stylesheet" href="https://code.getmdl.io/1.3.0/material.indigo-pink.min.css">


<h5>Auto width</h5>
<table class="tbl mdl-data-table mdl-shadow--2dp">
	<thead>
		<tr>
			<th class="mdl-data-table__cell--non-numeric">Material</th>
			<th>Unit price</th>
			<th>Quantity</th>
			<th>Unit price</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td class="mdl-data-table__cell--non-numeric">Acrylic (Transparent)</td>
			<td>$2.90</td>
			<td>25</td>
			<td>$2.90</td>
		</tr>
		<tr>
			<td class="mdl-data-table__cell--non-numeric">Plywood (Birch)</td>
			<td>$1.25</td>
			<td>50</td>
			<td>$1.25</td>
		</tr>
		<tr>
			<td class="mdl-data-table__cell--non-numeric">Laminate (Gold on Blue)</td>
			<td>$2.35</td>
			<td>10</td>
			<td>$2.35</td>
		</tr>
	</tbody>
</table>


<h5>Full width</h5>
<table class="full-width mdl-data-table mdl-shadow--2dp">
	<thead>
		<tr>
			<th class="mdl-data-table__cell--non-numeric">Material</th>
			<th>Unit price</th>
			<th>Quantity</th>
			<th>Unit price</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td class="mdl-data-table__cell--non-numeric">Acrylic (Transparent)</td>
			<td>$2.90</td>
			<td>25</td>
			<td>$2.90</td>
		</tr>
		<tr>
			<td class="mdl-data-table__cell--non-numeric">Plywood (Birch)</td>
			<td>$1.25</td>
			<td>50</td>
			<td>$1.25</td>
		</tr>
		<tr>
			<td class="mdl-data-table__cell--non-numeric">Laminate (Gold on Blue)</td>
			<td>$2.35</td>
			<td>10</td>
			<td>$2.35</td>
		</tr>
	</tbody>
</table>

<h5>Fixed width</h5>
<table class="fixed-width mdl-data-table mdl-shadow--2dp">
	<thead>
		<tr>
			<th class="mdl-data-table__cell--non-numeric">Material</th>
			<th>Unit price</th>
			<th>Quantity</th>
			<th>Unit price</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td class="mdl-data-table__cell--non-numeric">Acrylic (Transparent)</td>
			<td>$2.90</td>
			<td>25</td>
			<td>$2.90</td>
		</tr>
		<tr>
			<td class="mdl-data-table__cell--non-numeric">Plywood (Birch)</td>
			<td>$1.25</td>
			<td>50</td>
			<td>$1.25</td>
		</tr>
		<tr>
			<td class="mdl-data-table__cell--non-numeric">Laminate (Gold on Blue)</td>
			<td>$2.35</td>
			<td>10</td>
			<td>$2.35</td>
		</tr>
	</tbody>
</table>

<h5>Actions</h5>

<button class="remove mdl-button mdl-button--raised">Remove Quantity</button>

Upvotes: 2

Related Questions