Can I position an element fixed relative to parent?

CssDom

Css Problem Overview


I find that when I position an element fixed, it doesn't matter if the parent is positioned relative or not, it will position fixed, relative to the window?

#wrapper {
  width: 300px;
  background: orange;
  margin: 0 auto;
  position: relative;
}

#feedback {
  position: fixed;
  right: 0;
  top: 120px;
}

<div id="wrapper">
    ...
    <a id="feedback" href="#">Feedback</a>
</div>

http://jsbin.com/ibesa3

Css Solutions


Solution 1 - Css

The CSS specification requires that position:fixed be anchored to the viewport, not the containing positioned element.

If you must specify your coordinates relative to a parent, you will have to use JavaScript to find the parent's position relative to the viewport first, then set the child (fixed) element's position accordingly.

ALTERNATIVE: Some browsers have sticky CSS support which limits an element to be positioned within both its container and the viewport. Per the commit message:

> sticky ... constrains an element to be positioned inside the intersection of its container box, and the viewport. > > A stickily positioned element behaves like position:relative (space is > reserved for it in-flow), but with an offset that is determined by the > sticky position. Changed isInFlowPositioned() to cover relative and > sticky.

Depending on your design goals, this behavior may be helpful in some cases. It is currently a working draft, and has decent support, aside from table elements. position: sticky still needs a -webkit prefix in Safari.

See caniuse for up-to-date stats on browser support.

Solution 2 - Css

Let me provide answers to both possible questions. Note that your existing title (and original post) ask a question different than what you seek in your edit and subsequent comment.


To position an element "fixed" relative to a parent element, you want position:absolute on the child element, and any position mode other than the default or static on your parent element.

For example:

#parentDiv { position:relative; }
#childDiv { position:absolute; left:50px; top:20px; }

This will position childDiv element 50 pixels left and 20 pixels down relative to parentDiv's position.


To position an element "fixed" relative to the window, you want position:fixed, and can use top:, left:, right:, and bottom: to position as you see fit.

For example:

#yourDiv { position:fixed; bottom:40px; right:40px; }

This will position yourDiv fixed relative to the web browser window, 40 pixels from the bottom edge and 40 pixels from the right edge.

Solution 3 - Css

2016 Update

It's now possible in modern browsers to position an element fixed relative to its container. An element that has a transform property acts as the viewport for any of its fixed position child elements.

Or as the CSS Transforms Module puts it: > For elements whose layout is governed by the CSS box model, any value other than none for the transform property also causes the element to establish a containing block for all descendants. Its padding box will be used to layout for all of its absolute-position descendants, fixed-position descendants, and descendant fixed background attachments.

.context {
  width: 300px;
  height: 250px;
  margin: 100px;
  transform: translateZ(0);
}
.viewport {
  width: 100%;
  height: 100%;
  border: 1px solid black;
  overflow: scroll;
}
.centered {
  position: fixed;
  left: 50%;
  bottom: 15px;
  transform: translateX(-50%);
}

<div class="context">
  <div class="viewport">
    <div class="canvas">

      <table>
        <tr>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
        </tr>
        <tr>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
        </tr>

        <tr>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
        </tr>

        <tr>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
          <td>stuff</td>
        </tr>
      </table>

      <button class="centered">OK</button>

    </div>
  </div>
</div>

Solution 4 - Css

first, set position: fixed and left: 50%, and second — now your start is a center and you can set new position with margin.

Solution 5 - Css

This solution works for me! Reference to the original detailed answer: https://stackoverflow.com/a/11833892/5385623

css:

.level1 {
    position: relative;
}


.level2 {
    position: absolute;
}


.level3 {
    position: fixed;
    /* Do not set top / left! */
}

html:

<div class='level1'>
    <div class='level2'>
        <div class='level3'>
            Content
        </div>
    </div>
</div>

Solution 6 - Css

I know this is super old but after not finding the (pure CSS) answer I was looking for I came up with this solution (partially abstracted from medium.com) and thought it might help others looking to do the same thing.

If you combine @DuckMaestro's answers you can position an element fixed relative to a parent (actually grandparent). Use position: absolute; to position an element inside a parent with position: relative; and then position: fixed; on an element inside the absolute positioned element like so:

HTML

<div class="relative">
  <div class="absolute">
    <a class="fixed-feedback">This element will be fixed</a>
  </div>
</div>

CSS

.relative {
  margin: 0 auto;
  position: relative;
  width: 300px;
}

.absolute {
  position: absolute;
  right: 0;
  top: 0;
  width: 50px;
}

.fixed-feedback {
  position: fixed;
  top: 120px;
  width: 50px;
}

EXAMPLE

Like @JonAdams said, the definition of position: fixed requires the element to be positioned relative to the viewport but you can get around the horizontal aspect of that using this solution.

Note: This is different than just setting a right or left value on the fixed element because that would cause it to move horizontally when a window is resized.

Solution 7 - Css

Here is an example of Jon Adams suggestion above in order to fix a div (toolbar) to the right hand side of your page element using jQuery. The idea is to find the distance from the right hand side of the viewport to the right hand side of the page element and to keep the right hand side of the toolbar there!

HTML

<div id="pageElement"></div>
<div id="toolbar"></div>

CSS

#toolbar {
    position: fixed;
}
....

jQuery

function placeOnRightHandEdgeOfElement(toolbar, pageElement) {
    $(toolbar).css("right", $(window).scrollLeft() + $(window).width()
    - $(pageElement).offset().left
    - parseInt($(pageElement).css("borderLeftWidth"),10)
    - $(pageElement).width() + "px");
}
$(document).ready(function() {
    $(window).resize(function() {
        placeOnRightHandEdgeOfElement("#toolbar", "#pageElement");
    });
    $(window).scroll(function () { 
        placeOnRightHandEdgeOfElement("#toolbar", "#pageElement");
    });
    $("#toolbar").resize();
});

Solution 8 - Css

It's an old post but i'll leave here my javascript solution just in case someone need it.


// you only need this function
function sticky( _el ){
  _el.parentElement.addEventListener("scroll", function(){
    _el.style.transform = "translateY("+this.scrollTop+"px)";
  });
}


// how to make it work:
// get the element you want to be sticky
var el = document.querySelector("#blbl > div");
// give the element as argument, done.
sticky(el);

#blbl{
  position:relative;
  height:200px;  
  overflow: auto;
  background: #eee;
}

#blbl > div{
  position:absolute; 
  padding:50px; 
  top:10px; 
  left:10px; 
  background: #f00
}

<div id="blbl" >
    <div><!-- sticky div --></div> 

    <br><br><br><br><br><br><br><br><br><br><br><br><br>
    <br><br><br><br><br><br><br><br><br><br><br><br><br>
    <br><br><br><br><br><br><br><br><br><br><br><br><br>
    <br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>


Notes

  1. I used transform: translateY(@px) because it should be lightweight to compute, high-performance-animations

  2. I only tried this function with modern browsers, it won't work for old browsers where vendors are required (and IE of course)

Solution 9 - Css

I know this is an older post, but I think a good example of what Jiew Meng was trying to do can already be found on this site. Check out the side menu located here: https://stackoverflow.com/faq#questions. Looking at it without getting into it too deep, I can tell javascript attaches a fixed position once the scrolling hits below the anchor tag and removes the fixed positioning if the scrolling goes above that same anchor tag. Hopefully, that will get someone started in the right direction.

Solution 10 - Css

With multiple divs I managed to get a fixed-y and absolute-x divs. In my case I needed a div on left and right sides, aligned to a centered 1180px width div.

	<div class="parentdiv" style="
		background: transparent;
		margin: auto;
		width: 100%;
		max-width: 1220px;
		height: 10px;
		text-align: center;">
		<div style="
			position: fixed;
			width: 100%;
			max-width: 1220px;">
			<div style="
				position: absolute;
				background: black;
				height: 20px;
				width: 20px;
				left: 0;">
			</div>
			<div style="
				width: 20px;
				height: 20px;
				background: blue;
				position: absolute;											  
				right: 0;">
			</div>
		</div>
	</div>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJiew MengView Question on Stackoverflow
Solution 1 - CssJon AdamsView Answer on Stackoverflow
Solution 2 - CssDuckMaestroView Answer on Stackoverflow
Solution 3 - CssPatrick McElhaneyView Answer on Stackoverflow
Solution 4 - CssДаниил ПронинView Answer on Stackoverflow
Solution 5 - CssEd KolosovskyView Answer on Stackoverflow
Solution 6 - CssLifehackView Answer on Stackoverflow
Solution 7 - CssKXLView Answer on Stackoverflow
Solution 8 - CssSabazView Answer on Stackoverflow
Solution 9 - CssillinoistimView Answer on Stackoverflow
Solution 10 - CsssajtdavidView Answer on Stackoverflow