HTML, CSS: Make table vertically scrollable - html

I have a table that is dynamically created after an AJAX request (using vue.js). The number of columns and width of each column is calculated.
My problem is, that there should be a vertical scrollbar when theres not enough space in the table, but even when setting style="width: 600px; overflow-x: scroll" no scrollbar shows up and the header elements gets shrinked together to the width of the wrapper div and the table rows get clipped.
Heres my relevant code (using bootstrap and vue.js 2):
<div class="panel-body" id="datatable">
<table class="table data-table" id="datatable-content">
<thead class="datatable-head" id="datatable-head">
<tr>
<th v-for="value in tableHeader" v-text="value"></th>
</tr>
</thead>
<tbody class="datatable-body" id="datatable-body">
<tr v-for="row in tableRows">
<td v-for="key in tableHeader" v-html="highlightFilterString(row[key])"></td>
</tr>
</tbody>
</table>
</div>
and the css:
.data-table {
overflow-x: scroll;
display: block;
width: 100%;
}
.datatable-body {
display:block;
height: calc(100vh - 118px);/
overflow-y: scroll;
overflow-x: hidden;
}
.datatable-head {
display:block;
overflow-x: scroll;
}
.datatable-head, .datatable-body tr {
min-width: 100px;
text-align: center;
}
.datatable-body td {
min-width: 100px;
text-align: center;
}
.datatable-head th {
min-width: 100px;
text-align: center;
}
What is the problem here?

I commented out the overflow-x element and it seems to be working fine now. Made fiddle with static html content
https://jsfiddle.net/v7qpot2b/
.datatable-body {
display:block;
height: calc(100vh - 118px);/
overflow-y: scroll;
/* overflow-x: hidden; */
}

Related

Display table with 'display: block;' at the center of a page

I have a very large table that doesn't fit a page and I added horizontal scrollbar like this:
.table-x-scroll {
display: block;
overflow-x: auto;
white-space: nowrap;
}
And <table class="table-x-scroll">...</table>
But I also want my table to be in the center of a page. I used to use align="center" but now, when I added display: block it doesn't work. Table is always at the left. How can I do these two things at the same time?
Would be better to use a wrapper for the table and add overflow to that wrapper not the table it self. This way you can control the behavior better.
And also use margin:0 auto on table to center it horizontally. No need for display:block
See below or better in jsFIddle
table {
border: 2px solid red;
width: 300px;
margin: 0 auto;
}
td {
border: 1px solid red;
}
.wrapper {
width: 100%;
overflow-x: auto;
}
<div class="wrapper">
<table>
<tr>
<td>a</td>
<td>a</td>
</tr>
<tr>
<td>a</td>
<td>a</td>
</tr>
<tr>
<td>a</td>
<td>a</td>
</tr>
</table>
</div>
Try to add margin-left:auto; margin-right:auto; in your style and specify the width
.table-x-scroll {
display: block;
overflow-x: auto;
white-space: nowrap;
margin-left:auto;
margin-right:auto;
width:50%;
}
<table class="table-x-scroll" border="1">
<tbody>
<row>
<td>AA</td>
<td>BB</td>
</row>
</tbody>
</table>
Try adding Margin : 0 auto
.table-x-scroll {
display: block;
overflow-x: auto;
white-space: nowrap;
margin : 0 auto
}
I can see that others have answered the aligning problem. But i couldn't see the "Doesn't fit to page" error so here is a solution for that:
In the css you specified overflow-x: auto;
If you change that to overflow-x scroll; it will make it scale to whatever size you choose to specify. and make it scrollable. The scrollbar within is possible to edit/remove, but it will still scroll ^^
I personally recommend the vw,vh values
example:
.bunnydiv {font-size: 1vw, 1vh;} This will make it scale to 1% of the width and of the height of the monitor. This can be specified with either vh, vw, vh and vw. Not both paramaters are needed, and it will scale accordingly :-)
I found some code I made myself some time ago, use this as a reference :-)
.div_scroll
{overflow-y: scroll;
display: block;
top:0px;
right: 0px;
position: absolute;
transform: translate(-23.6vw, 15vh);
border: 3px solid #dddddd;
max-height: 75vh;
width: 76vw;
margin: 0px;
background-color: white;}
It's copy-pasted, and setup this way for readability. Don't format you code like this unless it works better for you :-)

Table cell break word won't shrink

I often use this HTML/CSS structure to create a mobile-friendly table (It changes layout on narrow (mobile) screens; something very lacking in CSS frameworks) and it has been quite reliable for me. In my main project I have several tables with lots of data and varying widths.
If you open this codepen and change the view to 'debug' you can shrink the page width. Past 500px the table layout will change. The thead is hidden, secondary labels are shown and the tds are set to display: flex. (I like to use the responsive device toolbar in the inspector).
Under the table is a more simple set of divs, that behaves the way I want the divs inside the TD to work, but for some reason, the second div inside the td stops shrinking at a certain point. I have tried different combinations of word-wrap and white space but so far no luck. Seems the difference has to do with these divs being inside a table...
Is this just a limitation of tables or is there a way I can make the right div shrink like the second example?
Thanks!
https://codepen.io/sinrise/pen/qoypYJ
<table cellpadding="0" cellspacing="0">
<thead>
<tr>
<th>number</th>
<th>content</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div class="td-label">number</div>
<div>this is the first one</div>
</td>
<td>
<div class="td-label">number</div>
<div>this is the second one</div>
</td>
</tr>
</tbody>
</table>
<div class="cont">
<div class="in1">oneoneone oneone one oneoneoneoneoneon</div>
<div class="in2">two two twotwotwo twotwotwotwo</div>
</div>
table { width: 100%; table-layout: fixed; margin: 0 0 10px; }
th { padding: 10px 10px 0; text-align: left; }
td { padding: 10px; border: 1px solid #ccc; }
.td-label {
display: none;
min-width: 100px;
max-width: 100px;
font-weight: bold;
}
#media(max-width: 500px) {
thead { display: none; }
td {
display: flex;
margin: 0 0 10px;
> div:not(.td-label) {
word-wrap: break-word;
min-width: 1px;
}
}
.td-label {
display: table;
}
}
.cont {
display: flex;
border: 1px solid black;
> div {
&:first-of-type {
min-width: 100px;
max-width: 50px;
}
min-width: 1px;
border: 1px solid #aaa;
word-wrap: break-word;
}
}
The trick is to set the table width to 100%, add a min-width to the second div, and set display: table on the second div. I updated the pen and code above to reflect.

Table row doesn’t have full height

I’ve tried to create a layout with a topbar and under it a split layout. The problem I had is that the width and height should automatically fit to the browser size.
So I tried it with a table:
body {
margin: 0;
padding: 0;
min-height: 500px;
min-width: 600px;
}
table {
border-collapse: collapse;
}
.topbar {
height: 50px;
position: relative;
background: grey;
}
.layout_table {
height: 100%;
width: 100%;
}
<body>
<table class="layout_table">
<tr>
<td class="topbar">
hallo
</td>
</tr>
<tr>
<table width="100%">
<td width="20%" style="background: blue;">
</td>
<td width="80%" style="background: yellow;">
</td>
</table>
</tr>
</table>
</body>
JSFiddle
Now the result is mostly correct. The problem is that the second row of the first table doesn’t have a full height.
How can I fix this?
Instead of using <table> elements for layout, which is not recommended as the element should only be used for tabulated content, you should try using modern alternatives. What you are trying to do can be achieved with a combination of calc() and float or flex specifications. The float property is better supported by older browsers, but flex (from the CSS3 Flexbox specification) offers more layout possibilities.
In my example below I have used the flexbox specification for both (1) vertically aligning your topcontent text and (2) for distributing space between the blue and yellow columns under it. The latter of which can be easily achieved by float, but the reason of avoiding it is because of the need to clear floats properly.
body {
margin: 0;
padding: 0;
min-height: 500px;
min-width: 600px;
}
.topbar {
display: flex;
align-items: center;
height: 50px;
background-color: grey;
}
.content {
display: flex;
height: calc(100vh - 50px);
min-height: 450px; /* minimum parent height minus topbar height */
}
.content .c1 {
width: 20%;
height: 100%;
background-color: blue;
}
.content .c2 {
width: 80%;
height: 100%;
background-color: yellow;
}
<div class="topbar">
<span>Hello</span>
</div>
<div class="content">
<div class="c1"></div>
<div class="c2"></div>
</div>

div overflow issue when nested in table cell (firefox)

THIS IS THE FIDDLE
HTML:
<input id="APP" type="button" value="Append"/>
<div id="wrapper">
<table cellpadding="0" cellspacing="0">
<tr>
<td style="width: 100%; height: 30px; background-color: rgb(230,230,230)">
</td>
</tr>
<tr>
<td style="height: 100%;" align="center">
<div id="ContentWrapper">
</div>
</td>
</tr>
</table>
</div>
CSS:
#wrapper{
width: 80%;
height: 300px;
background-color: rgb(25,25,25);
}
#wrapper table{
width: 100%;
height: 100%;
}
#wrapper table td{
vertical-align: middle;
}
#ContentWrapper{
width: 98%;
height: 95%;
border: 1px solid blue;
color: rgb(255,255,255);
text-align: left;
overflow-y: auto;
}
jQuery:
$("#APP").on("click",function(){
$("#ContentWrapper").append("Test<br/>Test<br/>Test<br/>Test<br/>Test<br/>Test<br/>Test<br/>Test<br/>Test<br/>Test<br/>");
});
If you test this in Chrome or any other browser you'll see that it works as it should. But in Firefox, if you keep pressing the "Append" button, the div's height will change with the content despite of the fact that the div's overflow is set to auto.
I know this would work if I would set the div's dimensions in px instead of percentage, but I don't want to do that. I made that fiddle as an example to pinpoint the issue but in my original code the wrapper that holds the table is responsive and I have to keep the dimensions in percentage.
Interesting find. It smacks of a bug in Firefox.
However, there is a workaround: assign an explicit height to the tbody in the table as well.
#wrapper table, #wrapper tbody {
width: 100%; height:100%;
}
See updated fiddle. Note that I also changed some other properties, because the browsers got confused by the top td being 30px high and the bottom one 100%. I changed that to 10% and 90%; you may have to use other values in your situation. (Maybe use calc(...) for one of them.)

Fixed height of table row in html

I have a table hosted in a div. Neither the table nor the hosting div has a height specified.
After the table header row, each subsequent row looks like this:
<tr class="movie-info-row">
<td>
<div class="movie-cover">
<img class="movie-image" src="" />
<a class="movie-link" href="" target="_blank">IMDb</a>
</div>
</td>
<td colspan=5>
<div class="movie-details">
<p class="movie-file"></p>
<div class="movie-div-left">
<p class="movie-category"></p>
<p class="movie-director"></p>
<p class="movie-insertdate"></p>
</div>
<div class="movie-description-container">
<p class="movie-description"></p>
</div>
</div>
</td>
</tr>
I want each table row (except for the header) to have the same fixed height but I just can't get it to work after hours of trying all kinds of approaches (and of course searching on stackoverflow and elsewhere).
My css (in less syntax) looks like this:
.movie-info-row {
height: 240px;
p {
margin-top: 2px;
margin-bottom: 2px;
}
td {
height: 100%;
overflow: hidden;
}
}
.movie-cover {
border: 1px solid black;
width: 130px;
height: 100%;
overflow: hidden;
}
.movie-details {
border: 1px solid black;
height: 100%;
overflow: hidden;
}
.movie-file {
font-size:larger;
}
.movie-div-left {
float: left;
width: 40%;
vertical-align: top;
display: inline-block;
}
.movie-description-container {
display: inline-block;
float: right;
width: 60%;
overflow: hidden;
vertical-align: top;
}
.movie-description {
overflow: hidden;
}
As you can see I have fixed the height of the row to 240px and for good measure have each td height set to 100% with overflow hidden.
The trouble maker is the description text, which can be quite long and it messes with the table row height. As you can see I have set overflow to hidden in many places (which is probably overkill).
Note: This is not browser specific. I am not even using IE. I am testing it with firefox and chrome (both latest versions).
I am really at a loss. What am I doing wrong? Any help would be greatly appreciated.
ETA:
Here's a picture of a table row as it looks now: SampleRow
As you can see the description text takes the row height with it. I want it limited to a fixed height - basically the hight of the title image. And yes, I want all the information (with more to come) in there. So that is non-negotiable.
Too many hiddens and floats and whatnot. Simplify and conquer. Also you have nested selectors inside of another selector (p{} and td{})
Demo Fiddle
CSS:
.movie-info-row {
height: 240px;
}
p {
margin-top: 2px;
margin-bottom: 2px;
}
td {
border: 1px solid black;
height: 100%;
}
div, p {
display: table-cell;
}
.movie-cover {
width: 130px;
overflow: hidden;
}
.movie-details {
height: 100%;
width: 100%;
}
.movie-file {
font-size:larger;
}
.movie-div-left {
width: 35%;
vertical-align: top;
display: inline-block;
}
.movie-description-container {
display: inline-block;
width: 55%;
vertical-align: top;
}
.movie-description {
overflow: hidden;
}
By the looks of your HTML all of your data will go into one table cell is this how you want it?
Why not structure it like using individual tags for the headers with a colspan of what ever and then do a new for each row you need along with its data like this?
<tr>
<th colspan=2>Header</th>
</tr>
<tr>
<td>cell 1 data</td>
<td>cell 2 data</td>
<tr>
Then you can do this in the css, which would give you this same fixed height for all the rows:
tr {
height: 240px;
}
That way you can just use the table headers to describe each column and use a lot less code to make it work properly. Or from what I understand you are trying to do.