What happens when nesting elements with position: fixed inside each other?
Asked Answered
S

6

70

Okay, I've noticed something, but couldn't find it in the CSS spec. Styling an element with position: fixed will position it absolutely, with respect to the browser viewport. What happens if you place a fixed-position element inside another?

Example CSS along the lines of:

.fixed {
  position: fixed;
  width: 100px;
  height: 100px;
  background: red;
}

#parent {
  right 100px;
  padding: 40px;
}

.fixed .fixed {
  background: blue;
}
<div id="parent" class="fixed">
  <div class="fixed"> </div>
</div>

As far as I can tell, the element is fixed-positioned with respect to its nearest parent that's also fixed-positioned. Is this observable in all browsers; also, is it a bug, or intentional behaviour?

So far I've not found anything on this topic, just 'fixed position makes it stick to the page'.

Speedometer answered 6/9, 2009 at 0:42 Comment(1)
I know this is an old topic, but I recently ran into a related issue. The behavior of a fixed element inside another fixed element varies between browsers. See this Codepen as an example. In IE, the blue square on the right is inside the red square, whereas in Chrome it is not. I also had another problem removing the child element from the DOM in IE, where the element would be removed but it was still showing on the screen. If I can duplicate this behavior I'll make sure to add it to this comment. Anyway, nesting fixed elements is a bad idea.Munda
W
44

The fixing and the positioning are two separate things. They're positioned the same as absolutely positioned elements: relative to their containing block. But in contrast with absolutely positioned elements, they remain fixed to that position with respect to the viewport (i.e. they don't move when scrolling):

http://www.w3.org/TR/CSS2/visuren.html#propdef-position

The box's position is calculated according to the 'absolute' model, but in addition, the box is fixed with respect to some reference.

Positioning

The definition of containing block says:

If the element has 'position: fixed', the containing block is established by the viewport in the case of continuous media (...)

and

If the element has 'position: absolute', the containing block is established by the nearest ancestor with a 'position' of 'absolute', 'relative' or 'fixed' (...)

which suggests that while their positioning algorithm is the same (they're both positioned relative to their containing block), the containing block for fixed elements is always the viewport, in contrast with absolutely positioned elements, so they should be positioned relative to that and not to any absolutely or fixed-positioned elements.

And as a matter of fact, that is indeed the case. For example, if you add top: 20px to .fixed, both divs will be positioned 20 pixels from the top of the viewport. The nested fixed div does not get positioned 20 pixels down from the top of its parent.

The reason you're not seeing that in this case is because you're not actually setting any of the left/top/right/bottom properties, so their positions are determined by the position they would have in the flow (their "static position"), which as my first quote said, is done according to the absolute model.

Windfall answered 6/9, 2009 at 1:20 Comment(4)
I read that and thought that too (ALWAYS fixed to viewport), however... see noveltybeard.co.cc/tempcssfixed There's two divs, each with fixed position. On FF3.5 Mac, I can get the child to remain 'fixed' to the parent's top left corner as long as I don't specify a top/left/right/bottom value.Speedometer
I updated my post in the mean time. They're two different things. Their "static position" (which you get when you don't specify a left/top/right/bottom) is determined as with absolutely positioned elements. They are fixed to the viewport, but their position is determined by their place in the flow if you don't do any explicit positioning.Windfall
So that's like me calculating x/y values for the element's 'ordinary' position and applying those co-ordinates under top:/left: with position: /fixed too?Speedometer
Quick note about the fixed positioning being determined by their place in the flow if you don't provide explicit top/left/bottom/right values: This does not hold true for ie7 (big surprise).Muss
C
13

First element

position: fixed;

And the insider element must be:

position: sticky;

Castrate answered 10/5, 2020 at 20:52 Comment(3)
Worth to note only that the support for position: sticky; is not yet full. caniuse.com/css-stickyIllfavored
Great. This should be the accepted answer!Pruitt
A whole year later in Feb 2022, sticky now has full support of all main browsers. See the link in @HrvojeGolcic comment above.Outsmart
P
10

This only occurs when one of the ancestors of an element that uses position: fixed has defined (with a value different that none) any of the following styling rules: filter, transform, perspective, where, in this case, the closest ancestor that matches this condition will be used as the reference for the coordinates of the element instead of the viewport.

From MDN

fixed

The element is removed from the normal document flow, and no space is created for the element in the page layout. It is positioned relative to the initial containing block established by the viewport, except when one of its ancestors has a transform, perspective, or filter property set to something other than none (see the CSS Transforms Spec), in which case that ancestor behaves as the containing block. (Note that there are browser inconsistencies with perspective and filter contributing to containing block formation.) Its final position is determined by the values of top, right, bottom, and left.

This value always creates a new stacking context. In printed documents, the element is placed in the same position on every page.

Pike answered 24/11, 2020 at 3:24 Comment(0)
C
2

I don't think this is really the intent. Things with fixed positioning are all positioned in relation to the window, if you have a fixed a child of another fixed, what do you want to happen? You can easily duplicate the behavior by not just position both of the fixed elements separately, or using other position to alter the child's position within the fixed element. :D

Creekmore answered 6/9, 2009 at 0:48 Comment(1)
Persnally, I would expect that a fixed-within-fixed element would behave like any other fixed element: absolutely located at left/top/right/bottom coords. When you scroll the page fixed elements don't move. Likewise, the f-within-f element wouldn't move when you scrolling its parent. I can get firefox (3.5, mac) to do this, but it's not without bugs, so perhaps there's a reason I can't find anything on this! :PSpeedometer
T
2

I dont think there is anything more to this then what w3c say there is:

Generates an absolutely positioned element, positioned relative to the browser window. The element's position is specified with the "left", "top", "right", and "bottom" properties

So if you get rid of that "padding: 40px;" you will get 2 elements - 1 over another.

Same effect like if you positioned both elements absolutely to top:0 left:0 with same parent(body).

Tighe answered 6/9, 2009 at 1:11 Comment(1)
So did I, friend! See my comment on mercator's answer for what I found.Speedometer
P
2

Short Answer:

if you have a scrollable element with fixed position (a modal for example), and you want to make one of the childs fixed also(modal close button for example), here is the solution: you can make your element non-scrollable, and instead create a child inside of it and make it scrollable(modal content for example). this way , you can apply position: absolute to the child you want it to be fixed (modal close button for example), instead of position: fixed.

Long Answer:

In my case, i had a display: fixed Modal and applied the overflow: auto to it to make it scrollable. then i wanted to make the close button display: fixed.

Nesting display: fixed worked on chrome, but not in Firefox. so i changed my structure, i removed the overflow: auto from Modal to make it non-scrollable, and instead made the modal content scrollable. and also added position: absolute to close button.

Powel answered 18/10, 2019 at 18:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.