Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bootstrap 4 Table Responsive, Horizontal and Vertical Scroll

I'm using bootstrap tables with Angular 6 in a project, and I was able to create vertical scroll table-body with this code:

<table class="table table-striped table-bordered" style="margin-bottom: 0">
      <thead> <!-- Column names -->
        <tr>
          <th scope="col">#</th>
          <th scope="col">Col 1</th>
          <th scope="col">Col 2</th>
          <th scope="col">Col 3</th>
          ...
          <th scope="col">Col N</th>
        </tr>
      </thead>
      <tbody> <!-- Data -->
        <tr>
          <th scope="row">1</th>
          <td>AAAAA</td>
          <td>BBBBB</td>
          <td>CCCCC</td>
          ...
          <td>DDDDD</td>
        </tr>
        <tr>
          <th scope="row">2</th>
          <td>AAAAA</td>
          <td>BBBBB</td>
          <td>CCCCC</td>
          ...
          <td>DDDDD</td>
        </tr>
        ...
        <tr>
          <th scope="row">n</th>
          <td>AAAAA</td>
          <td>BBBBB</td>
          <td>CCCCC</td>
          ...
          <td>DDDDD</td>
        </tr>
      </tbody>
    </table>

And css:

  tbody {
      display:block;
      max-height:500px;
      overflow-y:auto;
  }
  thead, tbody tr {
      display:table;
      width:100%;
      table-layout:fixed;
  }
  thead {
      width: calc( 100% - 1em )
  } 

But now, if there are a lots of columns it doesn't look good.

// pic

So I wanted to add a horizontal scroll too, so I could scroll the full table horizontally and only the table body vertically. To do the horizontal scroll I used .table-responsive like this:

<div class="table-responsive">
    <table class="table table-striped table-bordered" style="margin-bottom: 0">
    ...
    </table>
</div>

But it only works without the vertical scroll part in the css.

enter image description here

I want to combine this two ways to scroll the table. I changed the width values on the css part, from 100% to static px values like this:

...
thead, tbody tr {
      display:table;
      width: 2000px;
      table-layout:fixed;
  }
  thead {
      width: calc( 2000px - 1em )
  } 

And it worked, but I need to set a static width and I don't know how can I do this dynamically (depending on the number of columns).

enter image description here

like image 348
JCAguilera Avatar asked Jun 05 '18 17:06

JCAguilera


People also ask

How do I make a scrollable table in bootstrap?

To enable y-scrolling simply set the scrollY parameter to be whatever you want the container wrapper's height to be (any CSS measurement is acceptable, or just a number which is treated as pixels).

How do I make my table scrollable with fixed header?

By setting postion: sticky and top: 0, we can create a fixed header on a scroll in HTML tables.


1 Answers

I fixed it this like this: First I edited the css, then I removed the thead part, and added some content in the body like this:

body {
  --table-width: 100%; /* Or any value, this will change dinamically */
}
tbody {
  display:block;
  max-height:500px;
  overflow-y:auto;
}
thead, tbody tr {
  display:table;
  width: var(--table-width);
  table-layout:fixed;
}

I also left the .table-responsive div:

<div class="table-responsive">
    <table class="table table-striped table-bordered" style="margin-bottom: 0">
    ...
    </table>
</div>

Then I calculated --table-width depending on the number of columns and length of the longest column name. I did this with Angular, in my component .ts:

calculateTableWidth() {
  // Get the table container width:
  const pageWidth = document.getElementById('tableCard').offsetWidth;
  // Get the longest column name
  const longest = this.tableColumns.sort(function (a, b) { return b.length - a.length; })[0];
  // Calculate table width
  let tableWidth = this.tableColumns.length * longest.length * 14;
  // If the width is less than the pageWidth
  if (tableWidth < (pageWidth - 10)) {
    // We set tableWidth to pageWidth - scrollbarWidth (10 in my project)
    tableWidth = pageWidth - 10;
  }
  // Then we update the --table-width variable:
  document.querySelector('body').style.cssText = '--table-width: ' + tableWidth + 'px';
}

I need to run calculateTableWidth() at the beginning in ngOnInit() (or when I have defined the tableColumns array) and then when I resize the window:

ngOnInit() {
  this.tableColumns = this.myAppService.getTableColumnsNames();
  this.calculateTableWidth();
}

@HostListener('window:resize', ['$event'])
onResize(event: any) {
  this.calculateTableWidth();
}

And that's how I fixed this. Now I have a good looking table, with vertical and horizontal scrolling.

like image 110
JCAguilera Avatar answered Oct 08 '22 17:10

JCAguilera