Forum Moderators: not2easy

Message Too Old, No Replies

Cross-browser FIXED positioning?

A navbar/logo that is always at the top/bottom of screen

         

fside

6:02 am on Feb 21, 2008 (gmt 0)

10+ Year Member



I wanted the logo banner and navigation links to be at the top of the screen, all the time, even if the page had to be scrolled down. I suppose one could use a DIV the size of the client window, and resize it onresize. Inside the DIV one could float a div or use a high z-index. I think it would also produce a second scrollbar on the right.

Or one might just fix a division at the top and forget it. I can do that in Firefox and Opera. I can barely do it in IE 6 (in this case, haven't tried in 7 or 8). So in Firefox and Opera:

#navBlock {
position: fixed;
width: 99.8%;
margin: 0px 0px 0px -.4em;
}

But in IE, I found this, instead:

@media screen {
#navBlock {
position: fixed;
}

* html {
overflow-y: auto;
overflow-x: hidden;
}

* html body {
overflow-y: auto;
overflow-x: auto;
height: 100%;
}

* html #navBlock {
position: absolute;
padding: 0;
margin: -1em -.8em 0px -.8em;
width: 99.5%;
}
}

It works - mostly. And other times it forces the horizontal scroll to appear. Sometimes, the 'navBlock' disappears entirely, but it's rare.

Has anyone a method that has worked better than this, above, in IE 6. Will this work in IE 7, etc?

SuzyUK

3:43 pm on Feb 21, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



that should work, but as I've never done anything which relies on tweaking scrollbars.. can't say for sure

some observations,
what's your Doctype? (that could be causing quirky rendering, in quirks mode IE doesn't recognise the HTML element)

I think you have the x and y the wrong way around..
you shouldn't need the @media {} bit, the

* html
is feeding the rule to only IE6 and below, and you could put it into a conditional comment if you want it out of the main stylesheet

IMHO, for best stability a div like this should be 100% wide (which means no padding, border), but that means it would go over the "body" scrollbar on the right so I would nest a div inside the fixed bar and add any padding required to it then you can offset the main div left by approx -17px so it looks like it fits.. then add 17px left padding to the pad div to bring the content back into line.. (you can give IE 5/6 different padding than your other browsers to allow for any negative offset that it gets.)


* html {
overflow-x: auto;
overflow-y: hidden;
}

* html body {
overflow-x: auto;
overflow-y: auto;
height: 100%; /* required */
}

* html #navBlock {
position: absolute;
left: -17px;
}

* html #navBlock .pad {padding-left: 20px;}

Again I'm not sure of the stability so letting us know your test results would be a good way to hear how the idea bears up, I think it used to cause problems in IE5Win/Mac.. but that's possibly not a major concern anymore?

-Suzy

[edited to add]

Will this work in IE 7, etc

No this should only work for IE6 and below (the

* html
bit is an IE hack/filter which IE7 ignores), but IE7 supports
position: fixed;
IIRC so it should work with proper position: fixed; i.e. it should get the same CSS as the other browsers get

[edited by: SuzyUK at 3:47 pm (utc) on Feb. 21, 2008]

fside

7:33 pm on Feb 21, 2008 (gmt 0)

10+ Year Member



DOCTYPE:

My first line is - <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">

This 'IE fix' stylesheet loads, in IE, by the conditional, <!--[if IE 6]> . So it won't hit either IE 5 or 7.

As I said, this 'fixed hack' MOST of the time works in IE 6. But sometimes it doesn't. I mentioned my results. Sometimes, the header just disappears entirely - rarely though. Other times, a second scroll bar becomes visible on the right, depending on the window size, etc.

As for the div-in-div, I haven't had any problems in Firefox or Opera. What would be the advantage of fixing one outer div and then placing the content/padding etc in a second, inner div?

fside

10:05 pm on Feb 21, 2008 (gmt 0)

10+ Year Member



I did change the width to 100%, by the way. It was suggested to me that I consider scripting the CSS with expression, pinning the block to the top by matching scrollheight. But I wonder how frequently that would be called? In the past, I did pin bars to the top using javascript, and could poll only a couple of times a second, and onscroll, and that was it. And this expression() method stills jiggles like the script method. So no difference there. At least * html thing didn't jiggle around, and behaved more like FIXED ought to behave.

Achernar

1:56 pm on Feb 22, 2008 (gmt 0)

10+ Year Member Top Contributors Of The Month



Personally, since IE7 supports position:fixed, I wouldn't bother too much to build a page that works in IE6 without expression(). If a standard page can work in IE6 with only a little IE6fix.css setting up expression(), why not use this method ?

edit: typo

[edited by: Achernar at 1:56 pm (utc) on Feb. 22, 2008]

SuzyUK

3:06 pm on Feb 22, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I think the script methods of doing this used to cause the fixed bar to jitter or move ever so slightly when scrolling, but that could be outdated news.

If you're already feeding the CSS to IE via a conditional comment like you say you should not need the * html bit in the selectors

Your doctype is a "quirky" one and that could be why the instability in IE6? perhaps try a strict rendering one that should also make IE6 use the standard Box Model and would avoid you needing more filters for widths etc.

Achernar

4:55 pm on Feb 22, 2008 (gmt 0)

10+ Year Member Top Contributors Of The Month



I've devised a method (CSS file with expression()) to automatically prevent jittering in such situation. The page doesn't need to be touched.
It is based on a behavior of IE6 (pure CSS), that forces it to recalculate the fixed position (and so the pseudo-fixed element) before displaying it. Scrolling is less smooth (like when you have a fixed background attached to the body element) but still usable (testing on a computer running at 450Mhz).
Preventing jittering can be done without expression(). What my expression() script does, is modify the CSS based on the CSS of the elements of the current document.
It works perfectly in standard mode, and only in a particular case in quirks mode (IE6 ignores some CSS elements).

fside

5:14 pm on Feb 22, 2008 (gmt 0)

10+ Year Member



"quirky" one

Only in IE Mac, for which I can't test. IE8 might actually be the first version of IE that is standards compliant. But it's as easy for me to include the system identifier (doctype-system in my xslt). So, thanks for the reminder.

fside

5:17 pm on Feb 22, 2008 (gmt 0)

10+ Year Member



[IE6] automatically prevent jittering

Do you have an example?

Achernar

6:20 pm on Feb 22, 2008 (gmt 0)

10+ Year Member Top Contributors Of The Month



Yes, see PM

I'm planning to write a page explaining the trick, and how I've written the javascript expression. With some remarks on how IE works depending on the combination of elements and styles. And why this fails when the document is rendered in quirks mode (IE diregards some styles).

[edited by: Achernar at 6:25 pm (utc) on Feb. 22, 2008]

SuzyUK

6:24 pm on Feb 22, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Achernar, care to share it here? please :)

Stomme_poes

1:11 pm on Feb 24, 2008 (gmt 0)

10+ Year Member



I can't visualise this from code, but the idea of a header div always at the top seems simple enough. I did it a few times with a footer. The trick is to not use position:fixed but position: absolute on a wrapper div that otherwise emcompasses the whole page. This gets around IE6 pretty well. A vertical scrollbar can be forced on the "content" part if you want with overflow: auto.

Or, you set the header div as a direct child of the body, set the body height to 100%, position it (header div) absolute top:0, and then set a wrapper for everything else underneath.. the wrapper and the header being direct children to the body and wrapper having top margin or padding...

Or the header thing is only a logo or something in which case it can be fixed position on the body even with IE6 and a wrapper around the rest of the page with a top padding and wrapper set to 100% height (body too).
But I'm be misunderstanding. Why do we need to tell IE6 how wide/large the page is with expressions? Is this flex-width page?

[edited by: Stomme_poes at 1:16 pm (utc) on Feb. 24, 2008]

SuzyUK

2:03 pm on Feb 24, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



>>Why do we need to tell IE6 how wide/large the page is with expressions?

because IE doesn't understand position: fixed; if you absolute it to the top it will attach to the <body> element and scroll out of view, the idea is to fix it at the top of the screen.

the question here is how to "fix" a navbar to the top of the screen.

Archernar's script (which he's working on posting and explaining for neeps like me;)) like other "fixed" scripts needs to know where the top of the viewport is all time in order to tell the div to be positioned to it and not the canvas.. at least that's my basic understanding

>>visualising the code at the top
paste it into favourite editor and try it, just do what it says and set up a navblock div as a child of the body.

what it's doing is taking the vertical scroll bar off the <html> canvas and making the <body> element responsible for the scroll instead.. the body element is the master containing block on a page. Then when you absolutely position the navblock element for IE it then gets attached to its containing block (the body), the body element is no longer moving, it's scrolling so the navblock stays put while content scrolls

hth

fside

11:41 pm on Feb 26, 2008 (gmt 0)

10+ Year Member



>>least that's my basic understanding<<

It's taking the old-style floating navbar out of the javascript file, and putting it inline in the css. Normally, you'd need either/both a timeout and onscroll listener in the script, pointing to a function which would readjust the bar to be at the top of the page, plus whatever v-scroll. Goes way back. I think I had the first one of mine in the mid-90s. But it does jitter when operated with the scroll bar.

I've read that some people have problems with IE expression in SP2. Some even report crashes? I don't know. It was apparently something of a stop-gap by IE that could compensate for the lack of things like, fixed, like, min/max-width, etc.

It's a more convenient shorthand than setting up a scroller in script. But if the script is safer . . . ? And again, this is just IE 6. Some of those css expression crashes may be IE7, instead?

Achernar

1:45 am on Feb 27, 2008 (gmt 0)

10+ Year Member Top Contributors Of The Month



No timeout or event listener. Only a css capability set up by an expression in the CSS file.
The interest of this expression, is that you don't have to bother too much. You only have to create the expressions (one for "top:", one for "left:") that keeps the element (pseudo)fixed in IE6 (with jittering) ; and add this special expression to "fix" the CSS (pure CSS, no javascript) of some elements.
The other advantage is that, since the trick is self-contained in a CSS style declaration, you can keep it in an external IE6fix file. And you don't need to link to js scripts.

I've finished the last draft of a complete explanation of the trick. I'll probably post it tomorrow.

fside

1:49 pm on Mar 4, 2008 (gmt 0)

10+ Year Member



> No timeout or event listener. <

I had a great deal of difficulty scripting onscroll in IE6 with attachEvent, even surprisingly with the famous alternatives of Dean Edwards and Zijdel's modifications. Those worked fine for mouseovers and out, but not for scroll. And this is only an IE 5/6 problem. IE6 is still 20-30% of the browsers in use going into mid-2008.

If scripting is switched off, the css expressions won't work, either. Some have suggested problems with css expressions, crashes, and also with the amount of 'polling' they produce. They seem to be called frequently, rapidly, scroll or no, every second.

I figured that if scripting were needed, that one could just revert to the old floater scripts from NN4 and IE5 days. I suggest a single scroll handler for all elements, one event 'stack' for all elements, in a thread over in the javascript area. It differs from the Edwards/Zijdel method in that these build stacks of event calls for each element. But it's not css any longer. So I wouldn't post it, here.

fside

11:38 pm on Mar 5, 2008 (gmt 0)

10+ Year Member



I came across this simple solution, as well. It uses css expressions. But perhaps IE 6 deserves to be 'punished', I don't know, for not supporting fixed as it should. Ironically, fixed, actually is used.

So in the BODY:

background: url("https://") fixed;

And in the style for the top bar:

top: expression( (( t=document.documentElement.scrollTop) ? t: document.body.scrollTop) +'px');

And that's it. Fixed at the top. And no jitters.

There might be other divs tacked on to the top bar, or placed 'fixed' off the side underneath, etc. Menus, news scrollers, what have you. And I've found that the script module I provided does a better job of maintaining those relative distances with the main nav bar than styles, alone. Zoom in, for example, and the other 'floaters' can end up in weird positions. But if using the script so that they don't, then those will 'jitter' when moving the scroll bar. Trade-off. So for at least the main top bar, itself, the above solves that problem.

Stomme_poes

12:56 pm on Mar 7, 2008 (gmt 0)

10+ Year Member



>Suzy>just paste it into favourite editor and try it...

Not that easy for me for technical reasons : )

>suzy>because IE doesn't understand position: fixed; if you absolute it to the top it will attach to the <body> element and scroll out of view, the idea is to fix it at the top of the screen.

I still don't get it. How does an expression change this?


<html...etc...>
<body>
<header></header>
<wrap>
rest of page
</wrap>
</body>
</html>


html, body {
height: 100%;
overflow: hidden;
}
#header {
position: absolute;
top: 0;
left: 0;
height: whatever so long as it's fixed or in percentages;
width: 100%;
}
#wrap {
position: absolute;
top: (place here the height of the header);
left: 0;
overflow: auto;
other stuff;
}

When Stu Nichols does this, he puts IE6 and below into quirks mode so that he can use huge invisible sandwiches-- er, borders and so then he places the #wrap at 0, 0 instead. I've been playing with fake frams on my own site, in preparation for a kids site which will have foreground and background stuff that doesn't move (fixed) while the "middle" layer gets scrolls from side to side. I'm not sure if I can fully get away with it, but I'm close. I try no to use Javascript because then I'm cutting and pasting something I don't understand in my code... so then when something breaks it's my own dang fault. : ) tho I've managed to use it a big for min-max width... but because I don't understand, I still can't figure out to use just min or just max... doesn't seem to work.

Someday I'll learn Javascript.... someday...

[edited by: Stomme_poes at 1:02 pm (utc) on Mar. 7, 2008]