I am trying to create a table w/ a fixed header at the top for data from our database. When I add 'position:fixed;' to the header's css it keeps it at the top but it forces the entire header to the first column. How can I get the table header to be at the top and be correctly aligned w/ the columns? I'd prefer a css/html solution, if possible.
EDIT: I've tried quite a few of the jQuery solutions that I've found on SO and through google. Some work, some don't. Those that do work on their own tend to break when I combine it with other scripts I have running on my pages...
<style>
.dg_hdr_row{
position: fixed;
top:0;
height: 25px;
}
.dg_col1{ width:60%; border: 1px solid #000; padding: 5px;}
.dg_col2{ width:15%; border: 1px solid #000; padding: 5px;}
.dg_col3{ width:10%; border: 1px solid #000; padding: 5px;}
.dg_col4{ width:15%; border: 1px solid #000; padding: 5px;}
</style>
<table width="100%">
<thead width="100%" >
<tr width="100%" class="dg_hdr_row" >
<th width="60%">Column 1</th>
<th width="15%">Column 2</th>
<th width="10%">Column 3</th>
<th width="15%">Column 4</th>
</tr>
</thead>
<tbody>
<tr class="dg_row">
<td class="dg_col1"></td>
<td class="dg_col2"></td>
<td class="dg_col3"></td>
<td class="dg_col4"></td>
</tr>
<tr class="dg_row">
<td class="dg_col1"></td>
<td class="dg_col2"></td>
<td class="dg_col3"></td>
<td class="dg_col4"></td>
</tr>
</tbody>
</table>
So there are some subtle issues with fixed positioning that make this particularly difficult.
Fixed elements are relative to the browser viewpoint
When you declare position: fixed, any additional position rules (like left or top) will place the header relative to the viewport itself - the top left corner of the screen. You can't use any tricks to make it relative to its parent, either, since it will be in the same place whenever the page scrolls. This might not affect your web page, but it's still something to consider.
Fixed elements don't work as expected in mobile browsers
I don't know your specific use case, but it's food for thought.
Fixed positioning removes elements from normal flow
This is what's causing the problem, as far as I can tell. When position: fixed is declared, the element actually breaks out of the normal layout and position of elements of the page, and now works in its own unique block.
From the CSS2 spec (this applies to fixed positioning as well):
In the absolute positioning model, a box is explicitly offset with respect to its containing block. It is removed from the normal flow entirely (it has no impact on later siblings). An absolutely positioned box establishes a new containing block for normal flow children and absolutely (but not fixed) positioned descendants. However, the contents of an absolutely positioned element do not flow around any other boxes. They may obscure the contents of another box (or be obscured themselves), depending on the stack levels of the overlapping boxes.
This is good, since you want the header to float above the table, but also bad because in most browsers, it's laid out separately from the rest of the table.
Potential fixes
If the only thing on the page is your table, you should be able to set the header to use width: 100% and apply the same cell widths as the rest of the table. It might be hard to get the sizing to match up just right, though, especially when the window is resized.
Use some simple JavaScript to display the header. I know you want to keep this with HTML and CSS (I usually do too), but JavaScript fits well because the floating header shouldn't be an essential part of using the site. It should be available for browsers that support it, but those that don't should still be able to use the table. There's a very good technique at CSS-Tricks
(http://css-tricks.com/persistent-headers/), but you'll be able to find others by looking for "sticky table headers" on your favorite search engine.
Have you looked at DataTables yet? Here's the horizontal part, if I understand what you mean:
http://datatables.net/release-datatables/extras/FixedColumns/index.html
Here is a working HTML/CSS solution to you problem.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<style>
body{
margin: 0;
padding: 0;
font-family: sans-serif;
}
.fixed {
position: relative;
width: 100%;
top: 25px;
border: 0;
border-collapse: collapse;
}
.fixed td, .fixed th {
border: 1px solid black;
height: 25px;
}
.fixed tr:first-child {
display: table;
position: fixed;
width: 100%;
background: #FFFFFF;
}
.dg_col1{ width:60%;}
.dg_col2{ width:15%;}
.dg_col3{ width:10%;}
.dg_col4{ width:15%;}
</style>
</head>
<body>
<table class="fixed">
<tr>
<th width="60%">Header 1</th>
<th width="15%">Header 2</th>
<th width="10%">Header 2</th>
<th width="15%">Header 2</th>
</tr>
<tr>
<td class="dg_col1">Data 14</td>
<td class="dg_col2">Data 14</td>
<td class="dg_col3">Data 14</td>
<td class="dg_col4">Data 24</td>
</tr>
</table>
</body>
</html>
If you are looking for a framework independent solution try Grid: http://www.matts411.com/post/grid/
It's hosted on Github here: https://github.com/mmurph211/Grid
Not only does it support fixed headers, it also supports fixed left columns and footers, among other things. Unfortunately it does require Javascript.
Related
I tried changing the position to absolute, fixed and static. But, still get the same result.
I have also tried wrapping it in a div element, but I might've done it wrong so I would appreciate help with that. (If this is the solution)
The .table is not the only element that moves around, but I am hoping once I figure out a fix for one, it will apply to them all.
I want the elements to remain in the spot I place them in, and if anything shrink a bit.
This is the object I am trying to get to stay in one place.
This is my first time using html & css, so I would appreciate any help I could get.
Thanks for your time :)
.table {
font-family: "Fira Sans", sans-serif;
border-collapse: collapse;
overflow-y: scroll;
height: 520px;
width: 425px;
position: relative;
display: block;
z-index: 6;
left: 120rem;
bottom: 90rem;
background-color: white;
border: 4px solid black;
z-index: 5;
}
<table class="table">
<thead>
<tr>
<th>
<input type="text" class="search-input" placeholder="Abbreviation">
</th>
<th>
<input type="text" class="search-input" placeholder="Full Name">
</th>
<th>
</tr>
<tr>
<td>XXX</td>
<td>XXX, XXX, XXX</td>
</tr>
<tr>
</table>
</div>
I've taken the liberty of modifying your html. I've added some elements and reworked your css so as to help you understand how styles can affect one another. your initial .table css contained too many rules that redefined what a table element is. Hopefully my changes will help you gain some insights.
Also you should find an online resource to help with HTML and CSS.
MDN is THE source for web development.
ADDENDUM:
The nice thing about HTML and CSS is that they allow you to mix and match elements and rules. We have many tools to customize the look and feel of a page. But this is also the bane of our existence.
FWIW: Just because we can embed data collection into a table (in the header or otherwise) doesn't mean we should.
Yes, it's legal. Yes, it'll work.
But...it alters the HTML definition. Which is again perfectly legal and it'll work. Until it doesn't. Like using CSS to redefine a display:table to display:block
Then there is the matter of accessibility concerns, like screen readers finding inputs where it's expecting column headers
The various components of an element are designed to work together and should only be redefined with care. Chances are if we find ourselves trying to make one element work like another, we missed something.
.outer {
position: relative;
}
.dontmove {
position: absolute;
width: 500px;
}
.table {
font-family: "Fira Sans", sans-serif;
border-collapse: collapse;
background-color: white;
border: 4px solid black;
width: 100%
}
.table th,
.table td {
padding: 2px 6px;
}
.table th>input {
width: 100%;
}
<div class="outer">
<div class="dontmove">
<table class="table">
<thead>
<tr>
<th>
<input type="text" class="search-input" placeholder="Abbreviation">
</th>
<th>
<input type="text" class="search-input" placeholder="Full Name">
</th>
<th>
</tr>
<tr>
<td>XXX</td>
<td>XXX, XXX, XXX</td>
</tr>
<tr>
</table>
</div>
</div>
I am building an HTML table and using Internet Explorer 11. In each TR are several TD with embedded elements of varying size. I inspected the page through IE DOM Explorer and think I know what is going on. Generally the textarea is the largest element (at 167px as per the CSS) but sometimes one of the other td elements will be bigger (say td1=300px). The problem I have is that I want the text area to fill out to 300px. I can see though that the height is inheriting from td id="td3" which is still 167px. Is there a way I can get td id="td3" to get the height from the largest sibling td in a tr.
The HTML looks something like this
<thead>
...
</thead>
<tbody>
<tr>
<td id="td1">[Dynamic Text1]</td>
<td id="td2">[Dynamic Text2]</td>
<td id="td3"><textarea class="ta"></textarea></td>
</tr>
<tr>
...
</tr>
<tr>
....
</tbody>
CSS
.ta{
height: 100%;
min-height: 167px
}
One thing is I notice Chrome does what I want but I would prefer a solution that conforms with the standards
Make sure you don't have HTML errors (try validating with w3.org validator). That is often the cause of display bugs that crop up between different rendering engines. Anyway, your example seems to work fine here:
td {
min-height: 200px;
background: lightblue;
vertical-align: top;
}
textarea {
display: block;
height: 100%;
min-height: 50px;
}
http://jsfiddle.net/Kg3P5/2/
I want to make an html table with the top row frozen (so when you scroll down vertically you can always see it).
Is there a clever way to make this happen without javascript?
Note that I do NOT need the left column frozen.
I know this has several answers, but none of these really helped me. I found this article which explains why my sticky wasn't operating as expected.
Basically, you cannot use position: sticky; on <thead> or <tr> elements. However, they can be used on <th>.
The minimum code I needed to make it work is as follows:
table {
text-align: left;
position: relative;
}
th {
background: white;
position: sticky;
top: 0;
}
With the table set to relative the <th> can be set to sticky, with the top at 0
NOTE: It's necessary to wrap the table with a div with max-height:
<div id="managerTable" >
...
</div>
where:
#managerTable {
max-height: 500px;
overflow: auto;
}
This is called Fixed Header Scrolling. There are a number of documented approaches:
http://www.imaputz.com/cssStuff/bigFourVersion.html
You won't effectively pull this off without JavaScript ... especially if you want cross browser support.
There are a number of gotchyas with any approach you take, especially concerning cross browser/version support.
Edit:
Even if it's not the header you want to fix, but the first row of data, the concept is still the same. I wasn't 100% which you were referring to.
Additional thought
I was tasked by my company to research a solution for this that could function in IE7+, Firefox, and Chrome.
After many moons of searching, trying, and frustration it really boiled down to a fundamental problem. For the most part, in order to gain the fixed header, you need to implement fixed height/width columns because most solutions involve using two separate tables, one for the header which will float and stay in place over the second table that contains the data.
//float this one right over second table
<table>
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
</table>
<table>
//Data
</table>
An alternative approach some try is utilize the tbody and thead tags but that is flawed too because IE will not allow you put a scrollbar on the tbody which means you can't limit its height (so stupid IMO).
<table>
<thead style="do some stuff to fix its position">
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
</thead>
<tbody style="No scrolling allowed here!">
Data here
</tbody>
</table>
This approach has many issues such as ensures EXACT pixel widths because tables are so cute in that different browsers will allocate pixels differently based on calculations and you simply CANNOT (AFAIK) guarantee that the distribution will be perfect in all cases. It becomes glaringly obvious if you have borders within your table.
I took a different approach and said screw tables since you can't make this guarantee. I used divs to mimic tables. This also has issues of positioning the rows and columns (mainly because floating has issues, using in-line block won't work for IE7, so it really left me with using absolute positioning to put them in their proper places).
There is someone out there that made the Slick Grid which has a very similar approach to mine and you can use and a good (albeit complex) example for achieving this.
https://github.com/6pac/SlickGrid/wiki
According to Pure CSS Scrollable Table with Fixed Header , I wrote a DEMO to easily fix the header by setting overflow:auto to the tbody.
table thead tr{
display:block;
}
table th,table td{
width:100px;//fixed width
}
table tbody{
display:block;
height:200px;
overflow:auto;//set tbody to auto
}
My concern was not to have the cells with fixed width. Which seemed to be not working in any case.
I found this solution which seems to be what I need. I am posting it here for others who are searching of a way. Check out this fiddle
Working Snippet:
html, body{
margin:0;
padding:0;
height:100%;
}
section {
position: relative;
border: 1px solid #000;
padding-top: 37px;
background: #500;
}
section.positioned {
position: absolute;
top:100px;
left:100px;
width:800px;
box-shadow: 0 0 15px #333;
}
.container {
overflow-y: auto;
height: 160px;
}
table {
border-spacing: 0;
width:100%;
}
td + td {
border-left:1px solid #eee;
}
td, th {
border-bottom:1px solid #eee;
background: #ddd;
color: #000;
padding: 10px 25px;
}
th {
height: 0;
line-height: 0;
padding-top: 0;
padding-bottom: 0;
color: transparent;
border: none;
white-space: nowrap;
}
th div{
position: absolute;
background: transparent;
color: #fff;
padding: 9px 25px;
top: 0;
margin-left: -25px;
line-height: normal;
border-left: 1px solid #800;
}
th:first-child div{
border: none;
}
<section class="">
<div class="container">
<table>
<thead>
<tr class="header">
<th>
Table attribute name
<div>Table attribute name</div>
</th>
<th>
Value
<div>Value</div>
</th>
<th>
Description
<div>Description</div>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>align</td>
<td>left, center, right</td>
<td>Not supported in HTML5. Deprecated in HTML 4.01. Specifies the alignment of a table according to surrounding text</td>
</tr>
<tr>
<td>bgcolor</td>
<td>rgb(x,x,x), #xxxxxx, colorname</td>
<td>Not supported in HTML5. Deprecated in HTML 4.01. Specifies the background color for a table</td>
</tr>
<tr>
<td>border</td>
<td>1,""</td>
<td>Specifies whether the table cells should have borders or not</td>
</tr>
<tr>
<td>cellpadding</td>
<td>pixels</td>
<td>Not supported in HTML5. Specifies the space between the cell wall and the cell content</td>
</tr>
<tr>
<td>cellspacing</td>
<td>pixels</td>
<td>Not supported in HTML5. Specifies the space between cells</td>
</tr>
<tr>
<td>frame</td>
<td>void, above, below, hsides, lhs, rhs, vsides, box, border</td>
<td>Not supported in HTML5. Specifies which parts of the outside borders that should be visible</td>
</tr>
<tr>
<td>rules</td>
<td>none, groups, rows, cols, all</td>
<td>Not supported in HTML5. Specifies which parts of the inside borders that should be visible</td>
</tr>
<tr>
<td>summary</td>
<td>text</td>
<td>Not supported in HTML5. Specifies a summary of the content of a table</td>
</tr>
<tr>
<td>width</td>
<td>pixels, %</td>
<td>Not supported in HTML5. Specifies the width of a table</td>
</tr>
</tbody>
</table>
</div>
</section>
You can use CSS position: sticky; for the first row of the table
MDN ref:
.table-class tr:first-child>td{
position: sticky;
top: 0;
}
you can use two divs one for the headings and the other for the table. then use
#headings {
position: fixed;
top: 0px;
width: 960px;
}
as #ptriek said this will only work for fixed width columns.
It is possible using position:fixed on <th> (<th> being the top row).
Here's an example
The Chromatable jquery plugin allows a fixed header (or top row) with widths that allow percentages--granted, only a percentage of 100%.
http://www.chromaloop.com/posts/chromatable-jquery-plugin
I can't think of how you could do this without javascript.
update: new link -> http://www.jquery-plugins.info/chromatable-00012248.htm
I use this:
tbody{
overflow-y: auto;
height: 350px;
width: 102%;
}
thead,tbody{
display: block;
}
I define the columns width with bootstrap css col-md-xx. Without defining the columns width the auto-width of the doesn't match the . The 102% percent is because you lose some sapce with the overflow
Using css zebra styling
Copy paste this example and see the header fixed.
<style>
.zebra tr:nth-child(odd){
background:white;
color:black;
}
.zebra tr:nth-child(even){
background: grey;
color:black;
}
.zebra tr:nth-child(1) {
background:black;
color:yellow;
position: fixed;
margin:-30px 0px 0px 0px;
}
</style>
<DIV id= "stripped_div"
class= "zebra"
style = "
border:solid 1px red;
height:15px;
width:200px;
overflow-x:none;
overflow-y:scroll;
padding:30px 0px 0px 0px;"
>
<table>
<tr >
<td>Name:</td>
<td>Age:</td>
</tr>
<tr >
<td>Peter</td>
<td>10</td>
</tr>
</table>
</DIV>
Notice the top padding of of 30px in the div leaves
space that is utilized by the 1st row of stripped data
ie tr:nth-child(1) that is "fixed position"
and formatted to a margin of -30px
Is there anything I can do to make IE display table cells as actual blocks?
Given this style:
table,tbody,tr,td,div {
display: block;
border: 1px solid #0f0;
padding: 4px;
}
And this html:
<table>
<tbody>
<tr>
<td>R1C1</td>
<td>R1C2</td>
<td>R1C3</td>
</tr>
</tbody>
</table>
<div>
<div>
<div>
<div>R1C1</div>
<div>R1C2</div>
<div>R1C3</div>
</div>
</div>
</div>
The table renders exactly the same as the nested divs in both Firefox and Safari/Chrome. But in Internet Explorer (8) the property display: block has no effect. The table renders exactly as if I don't set that property.
My main problem is that the cells don't break; They all render on one line. (The tbody and tr elements don't get any borders nor padding. That is not a problem for me right now, though.)
I haven't found any information on the problem when searching. Compatibility charts on quirksmode and elsewhere states that IE supports display: block since v. 5.5. Any discussion on table display problems seems to be when doing the reverse - giving non-table elements any of the display: table-* properties.
So once again, is there anything I can do to make IE render table cells as block?
(The real table is really a table, with tabular data. I would like to keep it that way, and restyle it unobtrusively.)
I applied float: left to stuff. It kinda works.
Live Demo
The biggest problem is width: 100% combined with the padding is making things too wide.
So:
Live Demo (without the problematic padding)
That looks a bit better, but I'm not sure how you can easily add padding everywhere if you need it.
This fails --> miserably <-- in IE7 (it just won't get over the fact that it's a <table>), and even if you don't care about IE7, it will need tweaking for your use case (if it's usable at all).
IE7:
The following worked for me for IE6+:
tr {
display: block;
position: relative
}
td.col1 {
display: block;
left: 0;
top: 0;
height: 90px;
}
td.col2 {
display: block;
position: absolute;
left: 0;
top: 30px;
}
td.col3 {
display: block;
position: absolute;
left: 0;
top: 60px;
}
Assumptions:
cell height 30px
Drawbacks:
Fixed cell height
Cumbersome specification of top property (maybe generate)
Only works when HTML provides classes for columns
Advantage:
Works in all browsers.
When to use:
When you have no control over HTML, but have control over CSS. Some hosted payment solutions come to mind that display in an IFRAME and offer a custom style sheet.
Just figured it out with a collegue of mine.
ALTHOUGH I STRONGLY RECOMMEND TO NOT SUPPORT IE8 AT ALL ANYMORE!
Since you are facilitating the use of an unsupported and currently unsafe product that is not up to par with current standards and techniques. It would be way better to tell your users to upgrade and give them some browser downloadlinks to choose from.
That being said. The CSS below is the minimum css you need to fix it in Internet Explorer 8.
table {
width: 100%;
}
td {
float: left;
width: 100%;
}
<table>
<tbody>
<tr>
<td>cell-1</td>
<td>cell-2</td>
</tr>
</tbody>
</table>
add this code:
<!DOCTYPE html>
我这里是这么解决的,加上上面那条声明语句,display:block对td就会有效。
you need add this code in the top.
<!DOCTYPE html>
<html>
<head>
<style>
td {
display: block;
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<td>First Name</td>
<td>Last Name</td>
<td>Job Title</td>
</tr>
</thead>
<tbody>
<tr>
<td><div>James</div></td>
<td><div>Matman</div></td>
<td><div>Chief Sandwich Eater</div></td>
</tr>
<tr>
<td><div>The</div></td>
<td><div>Tick</div></td>
<td><div>Crimefighter Sorta</div></td>
</tr>
</tbody>
</table>
</body>
</html>
Add this line of code in the top, but use 'float' and 'width' is very good.
sorry, my english so poor.
make it display:table-row; instead of display:block
It will work like it is supposed to
I have an html table within a div of a specific size. I want the table to apply margin collapse and be 100% wide. Here is my code. It renders how I want it to in IE8 and incorrectly in Firefox. Firefox may be doing the spec correctly, but whatever. How do I fix my css to work in both browsers?
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>Untitled 1</title>
<style type="text/css">
table
{
border-collapse: collapse;
border-spacing: 0;
}
table
{
margin: 10px 0;
width: 100%;
display: block;
}
p
{
margin: 10px 0;
}
td, th
{
border: 1px solid #000000;
}
</style>
</head>
<body>
<div style="width: 600px; border: 1px purple solid;">
<p>Some text at the top. Notice that the margin collapse does not work unless display:block.</p>
<table>
<tr>
<th></th>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
</tr>
<tr>
<td>Label 1</td>
<td>1.A</td>
<td>1.B</td>
<td>1.c</td>
</tr>
<tr>
<td>Label 2</td>
<td>2.A</td>
<td>2.B</td>
<td>2.c</td>
</tr>
</table>
<p>Some text at the bottom. Notice that the margin collapse does not work unless display:block. Its stupid.</p>
</div>
</body>
</html>
I need the display:block for margin collapsing to work in Firefox. If you remove the display:block, you should notice that the spacing between the <p> tags widens from 10px to 20px.
This is also an edit to this question that I posted earlier, but it won't let me edit for some reason. I've been messing around with my internet cache so I probably messed up a cookie.
You need to add table-layout: fixed to the style assigned to the table, that's all.
Use display: table and your problem will be solved.
just remove the display: block;, the border-collapse works fine
remove
display: block;
change this
table
{
margin: 10px 0;
width: 100%;
display: block;
}
to
table
{
margin: 10px 0;
width: 100%;
}
for live demo
http://jsfiddle.net/dN5DM/1/
Margin collapsing is only defined for block elements.
Tables are special. In the CSS specs, they're not quite block elements - special rules apply to size and position, both of their children (obviously), and of the table element itself.
check links
http://www.w3.org/TR/CSS21/box.html#collapsing-margins
http://www.w3.org/TR/CSS21/visuren.html#block-box
Solution to margin collapsing is
You could use a 1-pixel top padding or border to avoid margins from collapsing.
Okay, this is my first post on Stack Overflow, and I believe I have solved your issue. All I did was change the line "display: block;" to "position: relative;" and that seemed to have fixed the "stretching" issue.
I am using Chromium and I understood what you mean when the tables weren't stretching out as they were in Internet Explorer. I know Chromium and Firefox handle pages pretty similar, so that might have resolved your issue.
I'm just wondering.. If you're specifying div width="600" and then require the table to fit 100%.. Why not put a width on the table instead of the containing div.
don't mind me, Just curious to know what specifically you're trying to achieve other than the border-collapse.
You need to define the parent elements as 100% too, so the table knows what it is a percentage of.
You can fix any width trouble simply by adding a short JScritp ... first add this to your BODY tag: onload="autoadjustw"; and this little script in the head tag:
function autoadjustw(){
AN=document.getElementById("parent_object").offsetWidth;
document.getElementById("Table_Id").style.width=AN+"px";
}
if removing display: block breaks in IE use '\9' to target IE only like:
table
{
margin: 10px 0;
width: 100%;
display: block\9; /*for ie only"*/
}
Tables do not use display: block; Simple width: 100%; should do the display: block; trick.
Never have, never will!