Search code examples
javascripthtmlcellscrollable

Scrollable table cells within a 100% height and 100% width table


I need to create a full screen calendar display with seven columns (for the days of the week) and five rows (for the weeks in the month). I need the display to adapt to the overall size of the screen but where all the cells remain the same size as each other. So I have created a table with style height and width each set to 100% and with the tableLayout set to "fixed". Also the row style heights are each set as percentages totalling 100%.

Within each cell I need to be able to display a table of event data specific to that day and to do this I create a container div inside each cell and a table within that container div. The container div style height and widths are each set to 100% and overflow is set to "hidden".

This works fine provided the data in each cell does not exceed the basic size available. See image 1 below

Data not exceeding cell size

However when the data in each cell does exceed the basic size available, the table increases in size (as it should) but for some reason the overflow setting does not come into play. See image 2 below.

Data exceeding cell size

I think the issue is that the container div style height and width settings of 100% are being ignored and the table child is allowed to grow unconstrained.

My question is how do I force the container divs to stay within the limits of the main table cells.

I have tried setting the style position om the container div to "absolute", "relative" and "fixed" and neither of these settings appear to do the trick.

My code so far is :

MainTable.style.height = "calc(100% - 36px)" ; // 36px for the footer
MainTable.style.tableLayout = "fixed" ;
var DayOfWeekTextBig = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]; // 0-6

// set up header row to show days of week
var headerRow = AddRowToTable (MainTable);
    headerRow.style.height = "5%" ; // see comment below on weekRow height
    
for (var day = 0 ; day < 7 ; day++) // Monday to Sunday
    {
    var headerCell = AddCellToRow (headerRow);
    headerCell.style.borderWidth = "0.5px" ;
    headerCell.style.borderStyle = "solid" ;
    headerCell.style.borderColor = "black"; 
    headerCell.style.textAlign = "center" ;
    headerCell.style.color = "black";
    AddTextToCell (headerCell, DayOfWeekTextBig [(day + 1) % 7]); // convert Monday to Sunday -> Sunday to Saturday
    };
    
for (var week = 0 ; week < 5 ; week++)
    {
    var weekRow = AddRowToTable (MainTable);
    weekRow.style.height = "19%" ; // 5*19% = 95% + 5% for the header row = 100% 
    for (day = 0 ; day < 7 ; day++) // Monday to Sunday
        {
        var dayCell = AddCellToRow (weekRow);
        dayCell.style.borderWidth = "0.5px" ;
        dayCell.style.borderStyle = "solid" ;
        dayCell.style.borderColor = "black"; 
        var dayDiv = AddDivToCell (dayCell);
        dayDiv.style.width  =
        dayDiv.style.height = "100%" ;
        dayDiv.style.overflowY = 
        dayDiv.style.overflowX = "hidden" ;
        var dayTable = AddTableToPage (dayDiv);
        for (var item = 0 ; item < 20 ; item++)
            {
            var itemRow  = AddRowToTable (dayTable);
            var itemCell = AddCellToRow (itemRow);
            AddTextToCell (itemCell, "Row " + item);
            };
        };
    };


function AddTableToPage  (page)         { var table = document.createElement ("table"); page.appendChild   (table);     return table };
function AddRowToTable   (tabl)         { var row   = document.createElement ("tr");    tabl.appendChild   (row);       return row   }; 
function AddCellToRow    (row)          { var cell  = document.createElement ("td");    row.appendChild    (cell);      return cell  }; 
function AddTextToCell   (cell,text)    { var node  = document.createTextNode (text);   
function AddDivToCell    (cell)         { var div   = document.createElement ("div");   cell.appendChild   (div);       return div   }; 

Please can someone advise me on how to do this


Solution

  • You will either need the content to scroll overflow: scroll, or be hidden overflow: hidden.

    But first you need to make a container inside your table cell that has position absolute, you can then position it left:0;top:0;right:0;bottom:0 to take the container size, this prevent's the TD expanding the cell. Also make sure the TD is set to position relative, as absolute position will then be relative to the TD.

    example below..

    const tds = document.querySelectorAll('td div');
    
    tds[0].innerText = '123';
    tds[1].innerText = JSON.stringify(document, null, '  ');
    tds[2].innerHTML = '<b>Hello</b><p>There</p>';
    tds[3].innerText = JSON.stringify(
      new Array(100).fill(0)
    ,null, '  ');
    body {
      margin: 0;
      padding: 0;
    }
    table {
      width: 100%;
      height: 100vh;
    }
    td {
      position: relative;
      border: 2px solid black;
    }
    div {
      white-space: pre;
      position: absolute;
      background-color: lightgreen;
      top: 0; left: 0; bottom: 0; right: 0;
      overflow: auto;
    }
    <table>
       <tr>
         <td><div></div></td>
         <td><div style="overflow:hidden"></div></td>
       </tr>
       <tr>
         <td><div></div></td>
         <td><div></div></td>
       </tr>
    </table>