38

I'm running into some extremely strange behaviors, and non-consistant across every browser i've tested.

I've a pretty complex layout, but the main issue lies here:

<div id="drop">
  <div id="header"></div>
</div>

#drop has position:absolute and z-index:100
#header has position:fixed; top:60px;

As I start scrolling down Chrome ignores the position:fixed rule. If I remove either of the two styles above from #drop then Chrome starts respecting the position:fixed rule.

can't get it working on Ubuntu Chrome 23.0.1271.97 and see the same behavior on Mac Chrome 25.0.1364.99. My friend uses Ubuntu Chrome 25.0.1364.68 beta and it works correctly for him. I've tested it on firefox and it kinda works (with other symptoms)

Has anyone heard of this error? or can anyone even reproduce it?

edit

I'm using openlayers map as another div with position:fixed if I delete that layer or at least change it to display:none then this weird bug goes away.

edit

Noticed that during the presence of this bug, if I change the zoom level back and forth, then the position adjusts itself to the proper behavior. To me, this indicates a webkit issue that fails to execute some internal callback function on scroll.

Another extremely strange thing is that I have a few links inside of #header and they work if I just click the expected location, even though the the div does not appear there. Overall I've noticed that it's only the rendering that's broken. If at any point of time I force the browser to re-render by resizing the window, or changing zoom, or just doing Select-All, then the header bar jumps to the proper position, but does not remain fixed.

Community
  • 1
  • 1
Mikhail
  • 8,692
  • 8
  • 56
  • 82
  • are you setting position values for your fixed element? ie top:0;left:0; ? – lukeocom Mar 01 '13 at 08:26
  • Yes, sorry not to have mentioned it. I have `top:60px;` on the fixed. Will update the OP. – Mikhail Mar 01 '13 at 17:33
  • I haven't come across this issue before, nor can I reproduce it.. http://jsfiddle.net/be53j/ – lukeocom Mar 05 '13 at 02:07
  • Couldn't reproduce it either except on my particular example and noticed a bug-dependency. Updating the OP now. – Mikhail Mar 06 '13 at 06:23
  • I've run into this bug on two separate occasions. The only solution I found was to move the `fixed` element outside the `absolute` element. – Simon Robb Apr 24 '13 at 02:35
  • @SimonRobb, that has become my conclusion so far. If I ever conclude an actual solution I'll try 'n remember to post it here. – Mikhail Apr 24 '13 at 03:47
  • I have this insane bug. insane because it defies the laws of CSS physics – vsync Jun 12 '13 at 11:24
  • 2
    Are you using css transforms in your code? Because if you are - *that's* what's causing position:fixed not to work. – Danield Dec 22 '13 at 21:37
  • @Danield, openlayers use those, as well as a couple of jquery plugins I'm using. I'll see if I can disable those and update the OP. – Mikhail Dec 28 '13 at 02:13

7 Answers7

43

You mentioned in the comments that OpenLayers uses CSS transforms. That being the case:

the element with fixed positioning will become relative to the element with the transform - not relative to the viewport

Take a look at the spec: The Transform Rendering Model

Specifying a value other than ‘none’ for the ‘transform’ property establishes a new local coordinate system at the element that it is applied to.

.wpr
{
    width: 200px;
    height:1000px;
    background: pink;
    position:relative;
    margin: 0 200px;
    -webkit-transform: translateX(0);
    transform: translateX(0);
}
.fixed
{
    width: 200px;
    height:200px;
    margin: 50px;
    position: fixed;    
    top:0;
    left:0;
    background: aqua;
}
<div class="wpr">
    <div class="fixed"></div>
</div>
jarrodwhitley
  • 826
  • 10
  • 29
Danield
  • 121,619
  • 37
  • 226
  • 255
  • 2
    You just saved me from possible worst nightmare :), I am using bootstrap affix and am also using transform on the parent container, I will get rid of transform and use jquery animate :) – ndd Apr 09 '15 at 14:54
  • 2
    thanks for this, just wanted to add that even `will-change:transform` triggers this behaviour (in latest chrome) – schellmax Sep 06 '16 at 13:05
4

As the accepted answer says, this is the intended behavior, and is spec-compliant. Another important component of this is what it means to be using CSS transforms.

In your case, it was due to OpenLayers, but this applies to anyone using will-change: transform as well (probably a lot of the people visiting this question). This has been brought up on the Chromium bug tracker here, and marked as WontFix, because (as I said) it's intended behavior. The official comment is this:

This behavior is required by the spec (http://dev.w3.org/csswg/css-will-change/): "If any non-initial value of a property would cause the element to generate a containing block for fixed-position elements, specifying that property in will-change must cause the element to generate a containing block for fixed-position elements."

The idea is that once will-change:transform is specified, you should be able to add/remove/change transforms cheaply, without needing fixed-position descendants to get re-layed-out.

Note that using other values of will-change (e.g. opacity, top) will not change the positioning of fixed-position descendants.

As far as I am aware, the only solution is to make the child of the will-change element a sibling instead, to prevent the attribute from cascading.

As a side note, in my specific case, I was able to fix it by being more specific with the will-change attribute. Instead of using it on the div containing the performance-jarring element that required GPU offloading, I used it directly on the offending element. This was due to my original bad code, though, so it won't work for most cases.

forresthopkinsa
  • 1,339
  • 1
  • 24
  • 29
1

You will have to place header outside the parent container drop to make it work.

I had slightly similar issues days back.For instance,if you set z-index of header,it will be attain the z-index of the parent dropcontainer.The z-index of header will be useless because it is already inside a container which has another z-index.

The same logic of z-index applies to position.

Rahul Shah
  • 1,387
  • 4
  • 22
  • 41
  • It kinda makes sense, but if it were as accurate as you say then OpenLayers wouldn't have any effect on this. If I remove OpenLayers (which are outside of all divs) then my `header` starts working as expected. – Mikhail Mar 07 '13 at 05:58
0

I want to add another possible solution because I was struggling with chrome ignoring position:fixed for quite some time until I finally found the culprit:

-webkit-perspective: 1000;

It was coming from a plugin I was using and causes ALL position:fixed elements to be ignored. Hope it helps someone.

parliament
  • 21,544
  • 38
  • 148
  • 238
0

I think this is impossible, i don't think if two positions can be placed at the same place without one to collapse. But i think its better to use Avail height in javascript, i mean if you wanna an outer div to hold inner div, and outer div must cover the whole screen, use Availheight in js, this will get the screen height and then apply if, thereafter set all the divs in fixed position.

0

Add this to parent:

position: fixed;

...and this to the child:

position: sticky;
Rasmus
  • 366
  • 1
  • 3
  • 19
-6

First of all, put something in your div as empty ones behave really weird. Then, what do you expect by putting a fixed into an absolute? Obviously, nobody knows what is the reference point of your fixed div. Should it be its parents position? which is not changing with scroll or the page position which changes? Try to use things that are completely meaningful and have a clear definition because if you fix it in chrome, what would happen with another browser? Do you really prefer to test is on all of them?

I suppose a small change in your divs so that pull the fixed div out of the absolute one or move the absolute div somewhere else.

Sheric
  • 416
  • 2
  • 16
  • 6
    In the OP i've only shown the DOM, not the contents. There are sub tags and text in each of the divs. `fixed` doesn't need a reference point. All specifications state that it's referenced to the browser window. Next time please use comments instead of answers when requesting additional information. – Mikhail Mar 01 '13 at 17:32