Page 1 of 3 123 LastLast
Results 1 to 10 of 22

Thread: [CSS] Fixed position crossbrowser

  1. #1
    Join Date
    Sep 2007
    Location
    The Netherlands
    Posts
    1,881
    Thanks
    49
    Thanked 266 Times in 258 Posts
    Blog Entries
    56

    Default [CSS] Fixed position crossbrowser

    1) CODE TITLE: Fixed position crossbrowser

    2) AUTHOR NAME/NOTES: Arie Molendijk

    3) DESCRIPTION: This fixes 'position:fixed' for IE<7. There are already many fixes available on the Internet, so why producing yet another fix? The reason is that many of the fixes don't support non-quirks mode for IE, or disable the standard use of 'position: absolute', or produce unpredictable results when the doctype is changed (jdenny's fix at http://dev.jdenny.co.uk/css/ie_fixed.html), or produce flickering divs when the page is scrolled. This fix does not have any of these disadvantages. Greatly indebted to Anne van Kesteren and, more so, to jscheuer1 (see posts below).
    Note: it's only after I posted this that I found that at least two sites offer solutions for 'position: fixed' that are very similar to page 1 of the URL TO CODE: http://www.gunlaug.no/contents/wd_additions_15.html and http://www.webmasterworld.com/css/3308239.htm. My apologies to the authors of these sites for what might be seen as (but what was NOT) 'copying work of others'. Anyway, pages 3 - 5 are 'new' (pages 3-4: thanks to John Scheuer, who made the scripts).

    4) URL TO CODE: http://molendijk.110mb.com/position_...nonquirks.html
    Last edited by molendijk; 04-23-2008 at 10:34 PM. Reason: Adding information

  2. #2
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    Seems to work fine in IE 5.5 and 6. I'm just wondering, is eval truly needed? In my experience, an external function can take care of this without eval:

    Code:
    function fixIEtop(num){
    return document.compatMode && document.compatMode=='CSS1Compat'? documentElement.scrollTop+num+'px' : document.body.scrollTop+num+'px';
    }
    ('px' should be added for standards compliance) could be on or linked to the page, then the expression could be:

    Code:
    top:expression(fixIEtop(200));
    And a similar setup could be used for the left property, both of which functions would make using it several times on a site or page much easier.

    In any case, this will fail if IE has javascript and/or (perhaps) Active X disabled. Other solutions that require only pure css will not have this problem, but (as you point out) could have other issues.

    Also, loading a non-existent image for background might not be as good as using a transparent .gif.
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  3. #3
    Join Date
    Sep 2007
    Location
    The Netherlands
    Posts
    1,881
    Thanks
    49
    Thanked 266 Times in 258 Posts
    Blog Entries
    56

    Default

    John,
    You are right about the eval. Instead of
    Code:
    top:expression(eval(document.compatMode && document.compatMode=='CSS1Compat') ? documentElement.scrollTop+200 : document.body.scrollTop+200); left: expression(eval(document.compatMode && document.compatMode=='CSS1Compat') ? documentElement.scrollLeft+5 : document.body.scrollLeft+5)
    you can have this:
    Code:
    top:expression(document.compatMode &&
    document.compatMode=='CSS1Compat' ?
    documentElement.scrollTop+200 : document.body.scrollTop+200);left: expression(document.compatMode &&
    document.compatMode=='CSS1Compat' ?
    documentElement.scrollLeft+5 : document.body.scrollLeft+5)
    A step further, then, would be to take out 'expression' and to put that into a function, as you indicated.
    But for some reason, I don't manage to get the function right. Any help on this would be greatly appreciated.
    ----
    Arie.

  4. #4
    Join Date
    Sep 2007
    Location
    The Netherlands
    Posts
    1,881
    Thanks
    49
    Thanked 266 Times in 258 Posts
    Blog Entries
    56

    Default

    Something like this works
    Code:
    <script type="text/javascript">
    function fixIEtop(){
    var pos = document.compatMode && document.compatMode=='CSS1Compat' ? 
    document.documentElement.scrollTop : document.body.scrollTop; 
    document.getElementById("side").style.position = "absolute"; 
    document.getElementById("side").style.top = parseInt(pos + 125) + "px";
    }
    window.onscroll=fixIEtop;
    </script>
    but now the div flickers when the page is scrolled, and that is exactly wjat I wanted to avoid.
    ---
    Arie.

  5. #5
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    The beauty of the expression is that it acts very much like pure css. But the expressions can become unwieldy at times, especially if they must be repeated several times. That is where a function comes in, like:

    Code:
    function fixedIE(tl, n){
    var sc='scroll'+tl, d=document, c='compatMode';
    return d[c] && d[c]=='CSS1Compat'? d.documentElement[sc]+n+'px' : d.body[sc]+n+'px';
    }
    Then the css could be:

    Code:
    #someid{
    position:absolute;
    top:expression(fixedIE('Top',200));
    left:expression(fixedIE('Left',5));
    }
    However, this assumes that IE will continue updating the position when it is setup this way. If not, another way must be found, or the eval will still need to be used. To do this entirely in a function, with no expression, will almost certainly cause flickers and/or jumpiness, unless you use the function to assign the expression as style, rather than as a direct style update via javascript alone.

    In any case, you are still depending upon javascript, perhaps Active X as well.
    Last edited by jscheuer1; 04-20-2008 at 10:23 PM. Reason: fix typo
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  6. The Following User Says Thank You to jscheuer1 For This Useful Post:

    molendijk (04-20-2008)

  7. #6
    Join Date
    Sep 2007
    Location
    The Netherlands
    Posts
    1,881
    Thanks
    49
    Thanked 266 Times in 258 Posts
    Blog Entries
    56

    Default

    John, thanks very much for your last post. After having made some minor changes in your function, I was glad to see that things started to work.
    As soon as I have the time, I'll work everything out and show you the result.
    Thanks again,
    Arie.
    Last edited by molendijk; 04-20-2008 at 07:50 PM.

  8. #7
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    Actually what I had works 'as is', except for a typo that I just fixed. Here is a full demo:

    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
    "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <title></title>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    <style type="text/css">
    #someid {
    position:fixed;
    top:200px;
    left:5px;
    width:75px;
    height:75px;
    border:1px solid gray;
    color:#ccc;
    background-color:#666;
    }
    </style>
    <!--[if lte IE 6]>
    <script type="text/javascript">
    function fixedIE(tl, n){
    var sc='scroll'+tl, d=document, c='compatMode';
    return d[c] && d[c]=='CSS1Compat'? d.documentElement[sc]+n+'px' : d.body[sc]+n+'px';
    }
    </script>
    <style type="text/css">
    body {
    background:url(foo) fixed;
    }
    #someid {
    position:absolute;
    top:expression(fixedIE('Top',200));
    left:expression(fixedIE('Left',5));
    }
    </style>
    <![endif]-->
    </head>
    <body>
    <div id="someid">
    I'm Fixed
    </div>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    <p>Other Content</p>
    </body>
    </html>
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  9. #8
    Join Date
    Sep 2007
    Location
    The Netherlands
    Posts
    1,881
    Thanks
    49
    Thanked 266 Times in 258 Posts
    Blog Entries
    56

    Default

    John,
    Before I read your last post, I produced this (inspired by your script). It's very similar to the code that you sent in your last post.
    Thank you very much for your help.
    ---
    Arie.

  10. #9
    Join Date
    Sep 2007
    Location
    The Netherlands
    Posts
    1,881
    Thanks
    49
    Thanked 266 Times in 258 Posts
    Blog Entries
    56

    Default

    Added 2 pages explaining (i) how to do it without 'eval'; (ii) how to do it with javascript.
    I honestly think that the end-result (page 3) is better than the IE-emulations for 'position: fixed' presented before this (thanks to John Scheuer for the great help).
    ---
    Arie.
    Last edited by molendijk; 04-21-2008 at 01:17 PM.

  11. #10
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    Well, if one is going to go the function route, and this actually makes quite a bit of sense if the content to be positioned fixed is script generated, one may as well use a function that will make the css part as simple as possible.

    Now, this could perhaps be made more verbose, or even refined more to make the css even simpler, but this (includes error checking which returns 0 if the arguments are not as expected) is what I have so far for the function:

    Code:
    function fixedIE(tl, n, el){
    var sc = 'scroll'+tl, d = document, c = 'compatMode',
    b = d[c]&&d[c]=='CSS1Compat'? d.documentElement : d.body;
    n = n-0; if(typeof n!='number')return 0;
    if(/^(Top|Left)$/.test(tl))
    return b[sc]+n+'px';
    if(/^(Bottom|Right)$/.test(tl)&&typeof el=='object'){
    tl = tl=='Right'? 'Left' : 'Top', sc = 'scroll'+tl;
    var dim = 'client' + (tl=='Top'? 'Height' : 'Width');
    return b[sc]+b[dim]-el[dim]-n+'px';
    }
    return 0;
    }
    The css may now be:

    Code:
    #someid {
    position:absolute;
    top:expression(fixedIE('Bottom',100,this));
    left:expression(fixedIE('Right',15,this));
    }
    or as before for Top and Left:

    Code:
    #someid {
    position:absolute;
    top:expression(fixedIE('Top',100));
    left:expression(fixedIE('Left',15));
    }
    The this keyword can be used with Top and Left, it won't hurt anything. One can use a Top and a Right or a Bottom and a Left if desired.
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  12. The Following User Says Thank You to jscheuer1 For This Useful Post:

    molendijk (04-22-2008)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •