I've looked around a bit and can't seem to find a decent solution, that doesn't require some crazy JavaScript, to the following problem.
There are two separate tables in the example. The first one is just for the headers. The second is for the body. We need two tables because the requirement for this feature is that the body table be locally scrollable, meaning the headers need to remain visible as the table body scrolls. We cannot use any new fancy HTML 5 pivot tables because we have to support IE.
Is there a way to accomplish this with pure CSS? It doesn't have to be perfect, just as long as it looks decent that's all I need.
This is a sample of the concept, using Jquery. (You can do it vanilla, but requires more code)
<table id="tb1" border="1">
<tr>
<td>Title 1</td>
<td>Title 2</td>
<td>Title 3</td>
<td>Title 4</td>
</tr>
</table>
<table id="tb2" border="1">
<tr>
<td>Content 00001</td>
<td>Content 02</td>
<td>Content 0000000000003</td>
<td>Content 000000000000000000004</td>
</tr>
</table>
JS:
function SetSize() {
var i = 0;
$("#tb2 tr").first().find("td").each(function() {
$($("#tb1 tr").first().find("td")[i]).width(
$(this).width()
);
i++;
});
}
$(window).resize(SetSize);
SetSize();
No "crazy javascript" :D
Here's a working fiddle, with a few css to make it look better: http://jsfiddle.net/5mfVT/
Definitely doable in just CSS. Just set widths on both tables, trs, and tds, apply word-wrapping, and setting table-layout to fixed. This last setting makes it use the defined column widths, rather than be determined by the cell content's width.
#tb1 { width: 80%; }
#tb2 { width: 80%; }
#tb1 tr { width: 100%; }
#tb2 tr { width: 100%; }
.col1 { width: 35%; }
.col2 { width: 35%; }
.col3 { width: 20%; }
.col4 { width: 10%; }
#tb1, #tb2 { table-layout: fixed; }
#tb1 td, #tb2 td { word-wrap: break-word; }
<table id="tb1" border="1">
<tr>
<td class="col1">Title 1</td>
<td class="col2">Title 2</td>
<td class="col3">Title 3</td>
<td class="col4">Title 4</td>
</tr>
</table>
<table id="tb2" border="1">
<tr>
<td class="col1">Content 00001</td>
<td class="col2">Content 02</td>
<td class="col3">Content 0000000000003</td>
<td class="col4">Content 000000000000000000004</td>
</tr>
</table>
Tables resize to as small as possible. Your headers' table has narrower content and can therefore resize to smaller widths before seizing to resize.
A non-Javascript solution is to either define widths for all of your columns or to define a min-width property your tables that fits the larger of the two minimal widths.
Related
I have a table with a thead and tbody sections. I have applied a slideToggle on this successfully, but the animation is broken.
When a user clicks on the thead, I want the contents of the tbody to slide up. Currently what happens is the section simply disappears, without any animation.
Here is the table
<table>
<thead>
<tr>
<td colspan="3">TABLE HEADING</td>
</tr>
</thead>
<tbody>
<tr>
<td class="first" colspan="1">Cell Contents</td>
<td colspan="1">Cell Contents</td>
<td colspan="1">Cell Contents</td>
</tr>
</tbody>
</table>
And here is the jQuery I am using:
<script type="text/javascript" language="javascript">
$(document).ready(function () {
$("thead").click(function () {
$(this).next("tbody").slideToggle("slow");
}
)
});
</script>
It disappears because <tbody> normally will get no shorter than the tallest td, no matter what you set its height to with CSS.
This is why the natural-height tbody just seems to disappear, while the one with artificial extra-height appears to run until the tr reached its natural height.
You can kludge around this with tbody {display:block;}. See the kludge at jsFiddle.
But, notice the effect that has when a table height is set.
Probably, the best way is to wrap the whole table in a div and slideToggle that, like so:
<table class="AbbyNormal">
<thead><tr><td colspan="3">TABLE HEADING</td></tr></thead>
</table>
<div class="tableWrap">
<table class="AbbyNormal">
<tbody>
<tr>
<td class="first" colspan="1">Cell Contents</td>
<td colspan="1">Cell Contents</td>
<td colspan="1">Cell Contents</td>
</tr>
</tbody>
</table>
</div>
Just be sure and fix the table widths the same.
See it in action at jsFiddle.
I think you should set an height to the tbody to make it work, look at this fiddle: http://jsfiddle.net/nicolapeluchetti/AsDvb/
css:
tbody{
height: 1000px;
background-color: yellow;
}
I'm encountering the strangest thing. I'm using a simple jquery script to make a thead stay in place while the tbody scrolls. It works really well, except for some strange behavior with the border. Check out the Pen, and you can see the red border at the bottom of each th. I've tried putting it on the thead and the tr of the thead but it always behaves the same. It disappears under... itself? I'm not even sure.
http://codepen.io/sinrise/pen/NrxgWG
I'm using bootstrap and SCSS.
My solution for now is to add a :before to the ths that is just an abs pos box the height of the width of the border I want. It works fine but I'd really like to use an actual border, if possible. Thanks!
HTML
<div class="container">
<div class="table-fixedheader" style="height: 200px; overflow-y: auto;">
<table class="table table-striped">
<thead>
<tr>
<th>One</th>
<th>Two</th>
<th>Three</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="text" value="#1" /></td>
<td>Thing</td>
<td>This is a long desctiption of some thing.</td>
</tr>
<tr>
<td>#2</td>
<td>Thing</td>
<td>This is a long desctiption of some thing.</td>
</tr>
<tr>
<td>#3</td>
<td>Thing</td>
<td>This is a long desctiption of some thing.</td>
</tr>
<tr>
<td>#4</td>
<td>Thing</td>
<td>This is a long desctiption of some thing.</td>
</tr>
<tr>
<td>#5</td>
<td>Thing</td>
<td>This is a long desctiption of some thing.</td>
</tr>
<tr>
<td>#6</td>
<td>Thing</td>
<td>This is a long desctiption of some thing.</td>
</tr>
<tr>
<td>#7</td>
<td>Thing</td>
<td>This is a long desctiption of some thing.</td>
</tr>
<tr>
<td>#8</td>
<td>Thing</td>
<td>This is a long desctiption of some thing.</td>
</tr>
</tbody>
</table>
</div>
</div>
CSS
.container { padding: 30px; }
.table-fixedheader table thead tr th {
border-bottom: 5px solid red;
position: relative;
}
.table-fixedheader thead {
background-color: #cccccc;
}
JQ
$(".table-fixedheader").scroll(function() {
$(this).find("thead").css("transform", "translate(0," + this.scrollTop + "px)");
});
It is because of the translate property. Try to fix the thead using position property. Here is your codepen for answer:
$(".table-fixedheader").scroll(function() {
$(this).find("thead").css({'position':'absolute', 'width': $('.table').width() });
});
http://codepen.io/SESN/pen/BzKepx
So far there are no solutions that don't involve changing the layout of the table with a fixed or absolutely positioned thead. The best solution is my own, but it involves not actually using a border. I just add:
&:before {
border: 0;
content: "";
position: absolute;
left: 0; bottom: -2px;
width: 100%; height: 2px;
background-color: red;
}
to the th of the thead and that works quite well. I suppose this is as good as it gets. The JS is minimal and otherwise reliable, and won't break the functionality of other scripts acting on tables, or mess with my layout. I hope this helps someone else, too! :)
I'm looking for a quick way to get a responsive html table for a huge set of data (more than 500 row with 15 columns by row).
I tried many javascript solutions like footable but it's really too slow.
The footable render is perfect but I would like to find a similar solution with only css tricks.
The main goal is to have a normal table for desktop and a partial table with only some columns displayed in mobile version and a click action that expand the rest of the columns Under the current table row like footable.
html example
<table class="f-tab">
<thead>
<tr>
<th>name</th>
<th>d1</th>
<th>d2</th>
<th>d3</th>
<th>d4</th>
<th>d5</th>
<th>d6</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name">item 1</td>
<td class="d1">val 1</td>
<td class="d2">val 2</td>
<td class="d3">val 3</td>
<td class="d4">val 4</td>
<td class="d5">val 5</td>
<td class="d6">val 6</td>
</tr>
...
</tbody>
</table>
css example
.f-tab {
min-width: 320px;
}
.f-tab th, .f-tab td {
display: none;
}
.f-tab tr.visible td {
display: block;
}
.f-tab td.name, .f-tab td.d1, .f-tab td.d3 {
display: inline-block;
}
#media (min-width: 480px) {
.f-tab th, .f-tab td {
display: table-cell;
}
}
.f-tab {
overflow: hidden;
}
js example
$(".f-tab tr").click(function () {
$(this).toggleClass("visible");
});
in my example, I want to display the column "name", "d1" and "d3" as table columns and have the other columns in display block Under the current row when I click on a tr.
___________________
name | d1 | d3
d2
d4
d5
d6
___________________
I tried at first with nested ul/li but I couldn't get something good.
For example I have this code:
<table>
<caption>Test</caption>
<tr>
<th>Values</th>
<td>$100</td>
</tr>
<tr>
<th>Initial value</th>
<td class="results"></td>
</tr>
</table>
Is there a way to hide the cells that are equal to $0 using HTML/CSS only?
Let's say instead of $0 I have a variable called fee that can be a variety of values: $0, $20, $100, etc.
For example:
<script>
var fees = ["$0", "$20", "$100"];
document.querySelector('.results').innerHTML = fees[1];
</script>
Is there a way to check what value it is and if it is found to be $0 can I then hide it?
My CSS is:
table{
border-width: 1px;
border-style: solid;
border-collapse: separate;
width: 400px;
}
#test{
empty-cells: show;
margin-bottom: 20px;
}
tr, th, td{
border-width:1px;
border-style: solid;
}
.results {
display: none; // I want this to only display none when fees = $0
}
TL;DR: It's possible. Look for the last solution in my answer, or check this blog:
Conditional formatting with pure css
I am assuming you do not want to hide the cell, but only its value. Hiding a cell does not make sense in a table since it would potentially change the layout, also any cell borders etc would also be hidden - probably not what you want.
Now CSS does not have any selectors based on element text content. But it does support attribute value selectors. So, you could change your code to be:
<table>
<caption>Test</caption>
<tr>
<th>Values</th>
<td><input value="$100"/></td>
</tr>
<tr>
<th>Initial value</th>
<td><input value="$0"/></td>
</tr>
</table>
And use a rule like
input[value="$0"] {
display: none;
}
You could even make the inputs not behave like inputs by adding a disabled attribute so they aren't editable.
If you don't want to use input elements, you could consider using spans instead and use a "data-value" attribute, and try if browsers respect that:
<table>
<caption>Test</caption>
<tr>
<th>Values</th>
<td><span data-value="$100">$100</span></td>
</tr>
<tr>
<th>Initial value</th>
<td ><span data-value="$0">$0</span></td>
</tr>
</table>
The css woudl be:
td > span[data-value="$0"] {
display: none;
}
Of course the drawback of this is that you would have to add the value twice (once as text content, once as attribute), and you need to generate an inner span element which feels a bit ugly.
Alternatively you could try to add a class attribute that includes the value and create a class selector:
<table>
<caption>Test</caption>
<tr>
<th>Values</th>
<td ><span class="value100">$100</span></td>
</tr>
<tr>
<th>Initial value</th>
<td ><span class="value0">$0</span></td>
</tr>
</table>
and the css would be:
td span.value0 {
display: none;
}
Of course the drawbacks are the same as with the previous method - you have to generate the value twice, once as text content and once as classname, and you need to add the inner span.
EDIT: dollar char is not valid in css classnames, so I removed it.
EDIT2: It turns out there is a way to do it without duplicating the value as both text and attribute. As a bonus, it turns out you don't need the inner span either if we rely on the :after pseudoclass (since it is that class that gets hidden, not the cell itself):
<table border="1">
<caption>Test</caption>
<tr>
<th>Values</th>
<td data-value="$100"></td>
</tr>
<tr>
<th>Initial value</th>
<td data-value="$0"></td>
</tr>
</table>
Using this css:
td:after {
content: attr(data-value);
}
td[data-value="$0"]:after {
content: "";
}
I want to draw a image like below.
http://enterprise-now.com/wp-content/uploads/2011/02/ValueChain.png
My database has followed a record.
1, Inbound Logistics, Operations, Outbound Logistics, Marketing & Sales, Service
And I try to show as HTML document like this.
<table>
<tr>
<td background="arrow.gif">Inbound Logistics</td>
<td background="arrow.gif">Operations</td>
<td background="arrow.gif">Outbound Logistics</td>
<td background="arrow.gif">Marketing & Sales</td>
<td background="arrow.gif">Service</td>
</tr>
</table>
However, each lengths of innerText are different, so I want to fix the size of images automatically but I don't know how. It seems that the background option doesn't have image-fixed function. (Do I need to use JavaScript in order to get the size of innerText?)
Any help will be appreciated. Thanks.
I would style the table using CSS.
I have not tested this code, but you could do something like this:
<script>
.arrow {
background-image: 'path/to/your/pic/arrow.gif';
width: 100px;
height: 70px;
}
</script>
<table>
<tr>
<td class="arrow">Inbound Logistics</td>
<td class="arrow">Operations</td>
<td class="arrow">Outbound Logistics</td>
<td class="arrow">Marketing & Sales</td>
<td class="arrow">Service</td>
<td class="vertical" rowspan="5">Margin</td>
</tr>
<tr><td colspan="5">Infrastructure</td></tr>
<tr><td colspan="5">Human Resource Management</td></tr>
<tr><td colspan="5">Information Technology</td></tr>
<tr><td colspan="5">Procurement</td></tr>
</table>
And adjust the width and height parameters properly to achieve the size you want. For the vertical text of the word margin, you could do something like what they suggest in this article or in this one
Good luck!
You need to specify a width on the td's so that they remain a constant width.
http://jsfiddle.net/4g8jX/
table { width: 80%; }
/* 5 tabs, so 20 percent width */
td { width: 20%; text-align: center; }