PDA

View Full Version : Scrollable Table



tracy78
05-05-2006, 07:46 PM
I'm trying to create a table where the head stays fixed but the body is the only part that is movable.

I found an example where it sets the CSS property in thead th to:

top: expression(document.getElementById("<id>").scrollTop);

The <id> is a <div>

however, I have two tables so I tried to put the style directly into the page but it doesn't work..

<div class="scrolled" id="data">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<thead class="tablehead" style="top: expression(document.getElementById('data').scrollTop)">
<tr>
<th>Header 1</th>
<th>Header 2</th>

</tr>
</thead>
<tbody>

....

</table>

Then right below this is another div with another table.

So two separate ID's so somehow I have to set the "top" attribute differently for each thead...


</div>

Twey
05-05-2006, 08:01 PM
Urgh, yuck. Never use expression().
<tbody style="overflow:scroll;">

tracy78
05-05-2006, 08:05 PM
Urgh, yuck. Never use expression().
<tbody style="overflow:scroll;">


But that does not work with IE.

jscheuer1
05-05-2006, 09:04 PM
expression() is good for IE only and often can be used to do things IE won't otherwise do but, it means nothing to other browsers so, a backup plan for them is required.

Your code should work but, I can't see all of it so, there could be errors you aren't telling about. When using expressions, you can only have one element with a particular id on the page, otherwise the expression doesn't knot what you want it to use.

If each item has a separate id, there is no reason that you cannot use a stylesheet for this.

tracy78
05-05-2006, 09:37 PM
expression() is good for IE only and often can be used to do things IE won't otherwise do but, it means nothing to other browsers so, a backup plan for them is required.

Your code should work but, I can't see all of it so, there could be errors you aren't telling about. When using expressions, you can only have one element with a particular id on the page, otherwise the expression doesn't knot what you want it to use.

If each item has a separate id, there is no reason that you cannot use a stylesheet for this.

I guess I'm not understanding how I can use a stylesheet for this.
top: expression(getElementById("something").scrollTop)

the "something" is the part I can't get because in the style sheet you have to specific the ID. I have about 3 tables and each has a different ID and each of the tables needs to have the header fixed.

The only way I can see is to create 3 separate Style Classes that are identical with the exception of the
top: expression.... part which will have a different ID for each table.

So I tried a different way by putting the "top" attribute in the tag itself

<thead class="myHeadClass" style="top:expression(getElementById("id").scrollTop)">
and that DOES NOT work.

jscheuer1
05-05-2006, 09:58 PM
The only way I can see is to create 3 separate Style Classes that are identical with the exception of the
top: expression.... part which will have a different ID for each table.

Would that be so bad? You can also give an element more than one class:

class="standard extra"

Example:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css">
.one {
color:red;
}
.two {
background-color:blue;
}
</style>
</head>
<body>
<div class="one two">Hi</div>
</body>
</html>

jscheuer1
05-05-2006, 10:14 PM
It also occurs to me that there is probably a good cross browser way to do what you want. However, without a visual example, I'm not sure what that is.

mwinter
05-06-2006, 10:40 AM
I'm trying to create a table where the head stays fixed but the body is the only part that is movable.The mechanism to do this is fairly trivial, but far from universally supported.



/* Do not place spaces around the child combinator (>)! */
table>tbody {
height: xem;
overflow: scroll;
}
where x is obviously the desired height of the scrolling region.


[...] I have two tables so I tried to put the style directly into the page but it doesn't work..

<div class="scrolled" id="data">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<thead class="tablehead" style="top: expression(document.getElementById('data').scrollTop)">It won't, for three reasons:


Length values must have units. At the very least, the expression should be



document.getElementById('data').scrollTop + 'px'

The top property, along with the other box offset properties, only apply to positioned elements, and there's no indication of an attempt to do that, above.
IE only permits rudimentary styling of table components.
Even if you corrected the first two problems, the third will kill any attempt you make.

I suggest that you just accept that IE is a terrible browser, do what you can for the decent ones (using the suggestion at the very beginning of this post), and move on.

Mike

jscheuer1
05-06-2006, 03:27 PM
Good suggestions/observations, Mike. Except that in IE, px is assumed in quirks mode. And since the OP claims this was working as a declaration in a stylesheet, I tend to believe that it can be done. Moreover, if it will work, it can be combined with the method(s) you and Twey outlined for other browsers, to make the page work under a wider variety of users agents.

You point out the obvious (to both of us) as regards the top property requiring that the position property be set as (in IE) to either relative or absolute. For this effect it is probably absolute. I had (perhaps erroneously) assumed that it was already set in the style section since, this had been said to be working there.

Your analysis of what the OP wants seems very likely (and shows a better grasp of the situation, in general, than I had) but, I'd still like to see an example, to be sure.

One other note at this point; expression() will not work even in IE if javascript is disabled, while the pure style settings of the other method(s) will work in all browsers that support them, with or without javascript enabled.

mwinter
05-06-2006, 11:53 PM
Good suggestions/observations, Mike. Except that in IE, px is assumed in quirks mode.I know, but you know what I think about that. :D


And since the OP claims this was working as a declaration in a stylesheet, I tend to believe that it can be done.Indeed. It seems that it can be hacked, but the suggestion that the OP seems to have found is not the way to do it; the thead and tbody elements cannot be positioned. However, the row in the table header can be to produce the same effect, despite being wholly broken.


Your analysis of what the OP wants seems very likely (and shows a better grasp of the situation, in general, than I had) but, I'd still like to see an example, to be sure.Alright then, John. Just for you (http://mwinter.webhop.info/dd/john-scheuer/scrolling-table-body.html). :p

That demonstration currently makes the assumption that the vertical scrollbar will be sixteen pixels wide, which isn't necessarily the case. There isn't much that can be done, other than to try and determine it via scripting and fix-up the style data, but that would be quite the pain in the ass.

Mike

jscheuer1
05-07-2006, 03:52 AM
Alright then, John. Just for you. (re: My request for a demo)

Thanks Mike, um, I meant a demo from the OP, a link to what they'd seen or a link to their resource for how they did this in the style section but, this will sort of do. In IE the content scrolls above as well as below the headings. There is a horizontal scrollbar in Opera and IE, haven't checked in FF yet. I wanted it from the OP to see just exactly what they were shooting for.

Speaking of shooting, while we are shooting the breeze, a subject came up in another thread that I think you might have the answer for. Twey wanted to know why this works:


window.location="http://www.google.com"

while this does not:


window.frames[0].location="http://www.google.com"

We both know that:


window.frames[0].location.href="http://www.google.com"

will do the trick, just wondering why it is OK for the window object to skip href and not for the frame object. I guessed that the window object is allowed by all browsers to use this technically illegal shorthand while other objects are not.

Later I thought, perhaps it is just some/most browsers that may allow this. Twey observed that setting an object to a string is at the heart of this but, neither of us knew why it is OK with one and not the other, care to comment/elucidate?

mwinter
05-07-2006, 10:00 AM
Thanks Mike, um, I meant a demo from the OP [...]Oops. I misunderstood. :(


In IE the content scrolls above as well as below the headings.That was a last-minute mistake. I added a margin to the table, but it should have been added to the containing div element.


There is a horizontal scrollbar in OperaYes. It was necessary to add a pixel of left padding to the table body to prevent Fx clipping cell borders. However, even if this were removed, the scrollbar arrows would still exist in Op, so I don't think the bar itself is much of a concern.


and IEReally? Not here in any IE version (4, 5, 5.5, or 6).


haven't checked in FF yet.You might find one, but notice that clicking on the arrows doesn't move the table body: it's just an artifact, probably from rounding.

I've added an extra fix to restore borders to the table heading cells using the same daft relative positioning hack.



Twey wanted to know why this works:

[location vs. location.href]

Twey observed that setting an object to a string is at the heart of this but, neither of us knew why it is OK with one and not the other, care to comment/elucidate?The answer, albeit a rather uninformative one, is that the location object is a host object, and doesn't conform to the usual rules. Host objects can act in whatever way the host wants them to, which includes translating an assignment into assignment to a particular property. That includes acting in an inconsistent manner.

You'd have to ask the browser developers why one works and the other doesn't; the decision seems arbitrary to me.

Mike

tracy78
05-07-2006, 05:36 PM
I have looked online and it seems whenever I get something to work for IE it doesn't work for Firefox, and viceversa.

I have found some solutions working for both but when I start changing it for my needs it messes things up. Like I need it to be a table that isn't a fixed pixel width...need it to be width100% and the table columns to be the size based on the data (automatic), rather than setting widths in the beginning.

jscheuer1
05-07-2006, 05:48 PM
I have looked online and it seems whenever I get something to work for IE it doesn't work for Firefox, and viceversa.

If that is the case, give us a link to an example of each. Through the use of conditional code, both should be able to appear on a single page.

tracy78
05-07-2006, 05:53 PM
Well, I don't have a link because this is not for a public website

I can show you this code though because right now I'm just trying to do a test.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>TEST SCROLLING</title>

<link rel="stylesheet" href="basic.css" type="text/css">

<style type="text/css">

.tableContainer {
position: relative; /* to capture the absolutely positioned table header */
padding-top: 19px; /* space for the column heads */
margin: 0 auto;
width: 80%;
border-bottom: 1px solid slategray
}

/* this enables the table to scroll without scrolling the page */
.innerframe {
overflow: auto;
width: auto;
height: 248px; /* height is required */
}

/* position the row of column heads above the table */
.tableContainer thead tr {
position: absolute; /* throws the header out of the table */
top: 0px;
left: 0px
}

table {
border-right: solid 1px slategray;
width: 100%;
}

thead td, thead th {
font-size: 14px;
font-weight: bold;
text-align: left;
background-color: papayawhip;
color: steelblue;
border: solid 1pt slategray;
width: 116px
}

td {
color: #000;
padding-right: 2px;
font-size: 12px;
text-align: left;
font-family: Arial,sans-serif;
border-bottom: solid 1px slategray;
border-left: solid 1px slategray;
border-right: solid 1px slategray;
width: 125px
}

</style>


</head>

<body>



<div class="tableContainer">

<div class="innerframe">
<table cellspacing="0" width=100%>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>

<tbody>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>

</tbody>
</table>

</div>
</div>

<p><p>

<div class="tableContainer">
<div class="innerframe">
<table cellspacing="0" width=100%>
<thead>
<tr>
<th>Name</th>
<th>Description</th>

</tr>
</thead>

<tbody>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>

</tbody>
</table>

</div>
</div>

</body>
</html>

tracy78
05-07-2006, 06:14 PM
I suggest that you just accept that IE is a terrible browser, do what you can for the decent ones (using the suggestion at the very beginning of this post), and move on.

Mike


Sounds like a plan... I did fine one that actually worked in both browsers and did not require the widths of the columns to be set ... it used a lot of javascript more than css. I think used javascript to set attributes of the style though.

jscheuer1
05-07-2006, 07:36 PM
This one seems to render an ordinary table in Opera but, in IE and FF, does what I think you want. No javascript is used. In FF the thead extends to the width including the scrollbar which is below it in both browsers. The two styles that begin with:


* html

are for IE only. The two that start with:


table>

are for virtually all other browsers:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>TEST SCROLLING</title>

<link rel="stylesheet" href="basic.css" type="text/css">

<style type="text/css">

.tableContainer {
position: relative; /* to capture the absolutely positioned table header */
padding-top: 19px; /* space for the column heads */
margin: 0 auto;
width: 80%;
border-bottom: 1px solid slategray
}

/* this enables the table to scroll without scrolling the page */
* html .innerframe {
overflow: auto;
width: auto;
height: 248px; /* height is required */
border-right:1px solid slategray;
}

/* position the row of column heads above the table */
* html .tableContainer thead tr {
position: absolute; /* throws the header out of the table */
top: 0px;
left: 0px;
}

table {
width: 100%;
}

thead td, thead th {
font-size: 14px;
font-weight: bold;
text-align: left;
background-color: papayawhip;
color: steelblue;
border: solid 1pt slategray;
width: 116px
}

td {
color: #000;
padding-right: 2px;
font-size: 12px;
text-align: left;
font-family: Arial,sans-serif;
border-bottom: solid 1px slategray;
border-left: solid 1px slategray;
border-right: solid 1px slategray;
width: 125px
}

table>tbody {
height: 248px;
overflow: auto;
border-right:1px solid slategray;
}
table>tbody tr {
width:98%;
overflow:hidden;
}


</style>


</head>

<body>



<div class="tableContainer">

<div class="innerframe">
<table cellspacing="0" width=100%>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>

<tbody>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>

</tbody>
</table>

</div>
</div>

<p><p>

<div class="tableContainer">
<div class="innerframe">
<table cellspacing="0" width=100%>
<thead>
<tr>
<th>Name</th>
<th>Description</th>

</tr>
</thead>

<tbody>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>
<tr>
<td>test</td>
<td>this is a test</td>

</tr>

</tbody>
</table>

</div>
</div>

</body>
</html>

mwinter
05-07-2006, 08:11 PM
I suggest that you just accept that IE is a terrible browser, do what you can for the decent ones (using the suggestion at the very beginning of this post), and move on.Sounds like a plan...Do note that I made that statement in haste (though it does often apply in other cases). I later found rather bizarre behaviour that could be used to get IE to cooperate. Did you look at the link to an example (http://mwinter.webhop.info/dd/john-scheuer/scrolling-table-body.html) that I posted previously?


I did fine one that actually worked in both browsers and did not require the widths of the columns to be set ... it used a lot of javascript more than css.And it probably breaks without that support, so it's probably not a good idea. I can understand that you don't want to have to specify the column widths, but, realistically, I don't think you have much choice.

Mike

jscheuer1
05-08-2006, 06:36 AM
Mike, your latest, as of this writing, is pretty darn good, as usual. My 'entry' at my last post, is more in line with the look and feel of the OP's example but, only works in IE and FF, not in Opera, as yours does. I've spent some time trying to wed the two but, it will take a fresh start to grasp all of what you are doing. I notice that you are using ems a lot. The OP used %. Do you think it would it be that hard to change to all % in your version? I'm not asking you to, just your opinion on its feasibility. The one thing I did have success with playing around with your version was changing overflow:scroll (both instances) to overflow:auto and then playing with the em widths a bit to get the horizontal scrollbar to go away.

mwinter
05-08-2006, 09:46 AM
I notice that you are using ems a lot. The OP used %. Do you think it would it be that hard to change to all % in your version?It's not practical. The table cells won't assume the right size when using percentages, therefore length values should be used throughout. I've yet to work out why this happens; it might be a bug (after all, tables aren't meant to undergo the changes specified in that style sheet), or I might be overlooking something.


The one thing I did have success with playing around with your version was changing overflow:scroll (both instances) to overflow:autoD'oh! Both were supposed to be auto from the outset. :(

Mike

jscheuer1
05-08-2006, 06:08 PM
I notice that you are using ems a lot. The OP used %. Do you think it would it be that hard to change to all % in your version?It's not practical. The table cells won't assume the right size when using percentages, therefore length values should be used throughout. I've yet to work out why this happens; it might be a bug (after all, tables aren't meant to undergo the changes specified in that style sheet), or I might be overlooking something.

Percentage dimensions are problematical in that when they vary depending upon the viewport, which is one of their best features, they will be different in a relative sort of way at different viewport sizes. This is due, at least in part, to the fact that percent, mathematically is really division, and that browsers work with whole units of pixels, not fractions of pixels. These differences are usually only 5 to 10 pixels at most but, in a table where some dimensions are fixed units, this can amount to big problems.

The reason I brought this up though is that the OP requested that the table's width be set as percent. My solution [link (http://home.comcast.net/~jscheuer1/side/scrolling-table-body_t1.htm)] does this well in IE and FF but, as I said, fails in Opera, rendering an ordinary table (not a horrible result). I still would be curious to know how your method succeeds in Opera and if there would be a way to adapt that to mine (which is really mostly the OP's example). There, the percents work out fine in IE and FF. I used these rules (primarily) to get the tbody scrolling and looking clean in FF:



table>tbody {
height: 248px;
overflow: auto;
border-right:1px solid slategray;
}
table>tbody tr {
width:98%;
overflow:hidden;
}

Why won't Opera respond in an at least a similar fashion, instead of with no scrolling of any kind?

mwinter
05-09-2006, 02:50 PM
Percentage dimensions are problematical in that when they vary depending upon the viewport, which is one of their best features, they will be different in a relative sort of way at different viewport sizes.I think you misunderstood what I was trying to say: with the style sheet I posted, replacing length values with percentages caused the layout to fall apart in a way that I wasn't expecting.

I soon discovered that the reason was because the table rows within the tbody element were still behaving like table rows, rather than generic block-level elements. As such, they were trying to shrink wrap around the content. Though this can be altered, it leaves the problem of mixed units, making percentage widths very fragile (in an already fragile layout).


My solution [link (http://home.comcast.net/~jscheuer1/side/scrolling-table-body_t1.htm)] does this well in IE and FF but, as I said, fails in Opera, rendering an ordinary table (not a horrible result). I still would be curious to know how your method succeeds in Opera [...]The various components of the table are still laid-out according to table, rather than block, rules. In my example, the declaration



display: block;
is applied to the majority of the table contents, making them respond more like regular block-level elements.

Mike