How to change a transposed table to make it horizontally scrollable? - html

I am making a table for products comparison. It's a table with vertical rows, a header at the left side and two or more product descriptions in vertical rows inside table body. It should be horizontally scrollable in case if user chooses a lot of products.
I have used CSS from this answer to transpose a table (i.e. make vertical rows). And now I can't manage to add a horizontal scrollbar inside tbody in case if table exceeds the predefined width. I am looking for something similar to this question but applied to my transposed table.
Here's what I have now: JSFiddle and here's what happens when I limit the table width to 200px:

Try the combination of inline-blocks and nowrap:
table { border-collapse: collapse; white-space: nowrap; }
tr { display: block; float: left; }
th, td { display: block; border: 1px solid black; }
tbody, thead { display: inline-block; }
tbody {
width: 300px;
overflow-y: hidden;
overflow-x: auto;
}
<table>
<thead>
<tr>
<th>name</th>
<th>number</th>
</tr>
</thead>
<tbody>
<tr>
<td>James Bond</td>
<td>007</td>
</tr>
<tr>
<td>Lucipher</td>
<td>666</td>
</tr>
<tr>
<td>Jon Snow</td>
<td>998</td>
</tr>
</tbody>
</table>
table shouldn't be displayed as block, if it not necessary for your other layout
I've added white-space: nowrap to prevent line wrapping
I've displayed tbody and thead as inline-block so now you can manage them like inline elements.
If you would like to scroll the tbody only without thead, it might looks like this:
table { border-collapse: collapse; white-space: nowrap; }
tr { display: inline-block; }
th, td { display: block; border: 1px solid black; }
tbody, thead { display: inline-block; vertical-align: top; }
tbody {
width: 150px;
overflow-y: hidden;
overflow-x: auto;
white-space: nowrap;
}
tbody tr { margin-right: -5px;}
<table>
<thead>
<tr>
<th>name</th>
<th>number</th>
</tr>
</thead>
<tbody>
<tr>
<td>James Bond</td>
<td>007</td>
</tr>
<tr>
<td>Lucipher</td>
<td>666</td>
</tr>
<tr>
<td>Jon Snow</td>
<td>998</td>
</tr>
</tbody>
</table>
You can think about blocks layout instead. In fact you've already implemented itexcept the HTML what is a bad pattern.

This won't be valid HTML, but you could wrap tbody with a div, then give the div the width and overflow-x property.

Related

HTML table widths set proportionally

I have a fixed-layout table, with two columns. If I set the width of just one column, things are as expected ( at least how I expected them to be).
However, if I specify the widths of both the columns, cells start dividing themselves proportionally.
table {
table-layout: fixed;
width: 120px;
border-collapse: collapse;
}
td {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
padding: 0;
}
td:first-child {
width: 5%;
}
td:nth-child(2) {
width: 2%;
}
<table>
<tr>
<td>Ed</td>
<td>Wood</td>
</tr>
<tr>
<td>Albert</td>
<td>Schweitzer</td>
</tr>
<tr>
<td>Jane</td>
<td>Fonda</td>
</tr>
<tr>
<td>William</td>
<td>Shakespeare</td>
</tr>
</table>
What I intended was for the first column to take 5% of the row width ( 120 px ) and the second column to take 2% of the row width. However, the first one takes 5/7 of the row width and the second one takes 2/7 of the row width.
Is there some spec that details this behavior?
As mentioned by Itay, the total width has to match the width of the table. When you set the width of one column the only thing that happens is that first column takes 5% and the other ones take remaining 95%, if you add width to all, they split the space piece by piece until they reach 100%.
One way you could get what you're trying to achieve is have an empty column like this
table {
table-layout: fixed;
width: 120px;
border-collapse: collapse;
background: whitesmoke;
}
td {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
padding: 0;
}
td:first-child {
width: 5%;
}
td:nth-child(2) {
width: 2%;
}
td:last-child {
width: auto;
}
<table>
<tr>
<td>Ed</td>
<td>Wood</td>
<td></td>
</tr>
<tr>
<td>Albert</td>
<td>Schweitzer</td>
<td></td>
</tr>
<tr>
<td>Jane</td>
<td>Fonda</td>
<td></td>
</tr>
<tr>
<td>William</td>
<td>Shakespeare</td>
<td></td>
</tr>
</table>
That way, the empty column will be taking that remaining space and let your other columns have the width you specified. And if you do decide that you want the rows to span the full width of the table, width: auto will be 0 and shouldn't cause you any problems.

How to work with HTML table and make multiple rows with only one <tr>?

I need to change an html <table> in order to make it responsive,
But I want to work only with css
table{
width:100px;
height:100px;
background:green;
}
.a{
width:100% !important;
background-color:Red;
}
<table>
<tbody>
<tr>
<td class="a">AAA</td>
<td class="b">BBB</td>
<td class="c">CCC</td>
</tr>
</tbody>
</table>
What I want :
Without changing HTML, I want to have the AAA for the 100% width of the screen, and "BBB" + "CCC" below (under the AAA line with BBB : 50% width, and the "CCC" too in width)
I'm trying with no success, any help please ?
Are you against changing the default display: table; of the table ?
If no, you can do like this
.a{
width:100%;
background-color:Red;
}
.b, .c { width: 49%; display: inline-block }
table, tbody, tr, td { display: block; }
Fiddle
You can use float but that sort of negates the point of using a table in the first place.
If this isn't tabular data (and the layout suggests it's not) then you really should be looking for an alternative HTML structure.
* {
box-sizing: border-box;
}
table {
table-layout: fixed;
width: 100%;
}
td {
width: 110px;
float: left;
width: 50%;
border: 1px solid grey;
}
td.a {
width: 100%;
}
<table>
<tbody>
<tr>
<td class="a">AAA</td>
<td class="b">BBB</td>
<td class="c">CCC</td>
</tr>
</tbody>
</table>

HTML table scrollbar issue

In the following code I tried to make a long table scrollable ( with <thead> fixed ).
But the columns are not filling the table's width anymore, and thead columns are even not aligned with tbodys ones.
How to solve this ? is there another way to do the trick.
The code is here
<table>
<thead>
<tr>
<th>ROW 01</th>
<th>ROW 02</th>
</tr>
</thead>
<tbody>
<tr><td>LINE 01</td><td><img src="http://placehold.it/90x90"/></td></tr>
<tr><td>LINE 02</td><td><img src="http://placehold.it/90x90"/></td></tr>
<tr><td>LINE 03</td><td><img src="http://placehold.it/90x90"/></td></tr>
</tbody>
</table>
CSS here
table{width: 100%; background: #efefef; border-collapse: collapse }
thead, tbody{display: block}
thead{background: #555; color: white;}
tbody{height: 120px; overflow: auto}
td, th{ border: 1px solid red; }
You can try to turn your <tr> in display:table;+table-layout:fixed; It will help but columns may break from a row to another unless you set a fixed width to one or the other cell.
DEMO
Your CSS turns like:
table {
width: 100%;
background: #efefef;
border-collapse: collapse
}
thead, tbody {
display: block
}
thead {
background: #555;
color: white;
padding-right:1em;/* average width of the scroll bar of tbody */
}
tbody {
height: 120px;
overflow: auto
}
tr {/* here make those the table */
display:table;
table-layout:fixed;
width:100%;
}
td, th {/* set a width to go along with table-layout */
border: 1px solid red;
}
add this to your CSS
td:nth-child(1), th:nth-child(1) { min-width: 200px; } /* or the width you need, you may use percentages */
td:nth-child(2), th:nth-child(2) { min-width: 200px; }
since the browser adds a scrollbar, it needs to add the space for that element, thus, the misalignment will ALWAYS happen. The good news is that, in fact, you need to declare only the first column, so if you plan to use only 1 columns, just use something like this:
td:nth-child(1), th:nth-child(1) { width:20%; min-width: 200px; }
and it will be enough.
There's no way that I know to do this without declaring the width for AT LEAST the first column
try
thead, tbody{display:auto}

HTML CSS Table displays rows at bottom instead of the top of the table

I am trying to finish formatting a table that is built dynamically. On the last page, when the table is sparse because there are fewer than the rows needed to fill the table, the rows are displayed at the bottom of the table space instead of the top. I've tried to correct this unsuccessfully. How can I display these rows at the top?
It doesn't seem to matter, but the table is built by the will_paginate Ruby gem. I say it doesn't matter because when I look at the HTML, it's just a table. There is nothing in there that is making this happen. The table size is formatted to display 10 rows. If there are only 3, they are just listed as 3 rows as you would expect. So, I think it is just an HTML/CSS formatting question.
The Table as it displays:
The SCSS:
.feeds {
list-style: none;
margin: 0;
text-align: left;
table-layout: fixed;
width: 700px;
height: 250px;
overflow: auto;
vertical-align: top;
li {
overflow: auto;
padding: 10px 0;
border-top: 1px solid $grayLighter;
&:last-child {
border-bottom: 1px solid $grayLighter;
}
}
table, thead, th, tr, tbody, tfoot {
vertical-align: top;
}
td {
vertical-align:top;
height: 1ex;
overflow-x: auto
}
}
The HTML:
<table class="feeds">
<tbody><tr>
<th id="url_cell"><a class="sortfield asc" href="/feeds?commit=Search&direction=desc&search=&sort=feed_url&utf8=%E2%9C%93">URL</a></th>
<th>Etag</th>
<th>Update date</th>
</tr>
<tr>
<td id="url_cell">http://www.skalith.net/rss</td>
<td id="etag_cell">RZWAFDMVHPXHWECK</td>
<td id="update_cell">August 5, 2013</td>
</tr>
<tr>
<td id="url_cell">http://www.viva.name/rss</td>
<td id="etag_cell">KFIEQYAUWMUHUJNY</td>
<td id="update_cell">August 5, 2013</td>
</tr>
</tbody></table>
The header row is filling out the space vertically (this is what it should do because of your table-layout. If you wrap it with <thead> and then only wrap the body of the table with <tbody> it will align it correctly. However, because you have table-layout: fixed, with height: 250px, the remaining rows will grow to make up the difference.
See: http://codepen.io/chrisrockwell/pen/gGmFq
Can you add a class to the table if it doesn't have a full set of rows? This way you could remove the height declaration.
Other options:
I'm guessing you need to have a set height but, if not, you could remove it.
Wrap the table in a <div> and assign your height and overflow to the div:
<div class="wrap">
<table class="feeds"></table>
</div>
.wrap {
height: 250px;
overflow: auto;
}
table {
/* just remove the height and overflow */
}
Here is an example of Option 2: http://codepen.io/chrisrockwell/pen/wpyfI

CSS table td width - fixed, not flexible

I have a table and I want to set a fixed width of 30px on the td's. the problem is that when the text in the td is too long, the td is stretched out wider than 30px. Overflow:hidden doesn't work either on the td's, I need some way of hiding the overflowing text and keeping the td width 30px.
<table cellpadding="0" cellspacing="0">
<tr>
<td>first</td><td>second</td><td>third</td><td>forth</td>
</tr>
<tr>
<td>first</td><td>this is really long</td><td>third</td><td>forth</td>
</tr>
</table>
It's not the prettiest CSS, but I got this to work:
table td {
width: 30px;
overflow: hidden;
display: inline-block;
white-space: nowrap;
}
Examples, with and without ellipses:
body {
font-size: 12px;
font-family: Tahoma, Helvetica, sans-serif;
}
table {
border: 1px solid #555;
border-width: 0 0 1px 1px;
}
table td {
border: 1px solid #555;
border-width: 1px 1px 0 0;
}
/* What you need: */
table td {
width: 30px;
overflow: hidden;
display: inline-block;
white-space: nowrap;
}
table.with-ellipsis td {
text-overflow: ellipsis;
}
<table cellpadding="2" cellspacing="0">
<tr>
<td>first</td><td>second</td><td>third</td><td>forth</td>
</tr>
<tr>
<td>first</td><td>this is really long</td><td>third</td><td>forth</td>
</tr>
</table>
<br />
<table class="with-ellipsis" cellpadding="2" cellspacing="0">
<tr>
<td>first</td><td>second</td><td>third</td><td>forth</td>
</tr>
<tr>
<td>first</td><td>this is really long</td><td>third</td><td>forth</td>
</tr>
</table>
you also can try to use that:
table {
table-layout:fixed;
}
table td {
width: 30px;
overflow: hidden;
text-overflow: ellipsis;
}
http://www.w3schools.com/cssref/pr_tab_table-layout.asp
It is not only the table cell which is growing, the table itself can grow, too.
To avoid this you can assign a fixed width to the table which in return forces the cell width to be respected:
table {
table-layout: fixed;
width: 120px; /* Important */
}
td {
width: 30px;
}
(Using overflow: hidden and/or text-overflow: ellipsis is optional but highly recommended for a better visual experience)
So if your situation allows you to assign a fixed width to your table, this solution might be a better alternative to the other given answers (which do work with or without a fixed width)
The above suggestions trashed the layout of my table so I ended up using:
td {
min-width: 30px;
max-width: 30px;
overflow: hidden;
}
This is horrible to maintain but was easier than re-doing all the existing css for the site. Hope it helps someone else.
This workaround worked for me...
<td style="white-space: normal; width:300px;">
Put a div inside td and give following style width:50px;overflow: hidden; to the div
Jsfiddle link
<td>
<div style="width:50px;overflow: hidden;">
<span>A long string more than 50px wide</span>
</div>
</td>
Chrome 37.
for non fixed table:
td {
width: 30px;
max-width: 30px;
overflow: hidden;
}
first two important! else - its flow away!
Just divide the number of td to 100%. Example, you have 4 td's:
<html>
<table>
<tr>
<td style="width:25%">This is a text</td>
<td style="width:25%">This is some text, this is some text</td>
<td style="width:25%">This is another text, this is another text</td>
<td style="width:25%">This is the last text, this is the last text</td>
</tr>
</table>
</html>
We use 25% in each td to maximize the 100% space of the entire table