Fixed position but relative to container
Asked Answered
W

33

832

I am trying to fix a div so it always sticks to the top of the screen, using:

position: fixed;
top: 0px;
right: 0px;

However, the div is inside a centered container. When I use position:fixed it fixes the div relative to the browser window, such as it's up against the right side of the browser. Instead, it should be fixed relative to the container.

I know that position:absolute can be used to fix an element relative to the div, but when you scroll down the page the element vanishes and doesn't stick to the top as with position:fixed.

Is there a hack or workaround to achieve this?

Wigwam answered 22/7, 2011 at 17:47 Comment(1)
"Tether is a low-level UI library that can be used to position any element on a page next to any other element." github.com/shipshapecode/tether + Demos/Docs at tether.ioNighttime
H
503

Short answer: no. (It is now possible with CSS transform. See the edit below)

Long answer: The problem with using "fixed" positioning is that it takes the element out of flow. thus it can't be re-positioned relative to its parent because it's as if it didn't have one. If, however, the container is of a fixed, known width, you can use something like:

#fixedContainer {
  position: fixed;
  width: 600px;
  height: 200px;
  left: 50%;
  top: 0%;
  margin-left: -300px; /*half the width*/
}

http://jsfiddle.net/HFjU6/1/

Edit (03/2015):

This is outdated information. It is now possible to center content of an dynamic size (horizontally and vertically) with the help of the magic of CSS3 transform. The same principle applies, but instead of using margin to offset your container, you can use translateX(-50%). This doesn't work with the above margin trick because you don't know how much to offset it unless the width is fixed and you can't use relative values (like 50%) because it will be relative to the parent and not the element it's applied to. transform behaves differently. Its values are relative to the element they are applied to. Thus, 50% for transform means half the width of the element, while 50% for margin is half of the parent's width. This is an IE9+ solution

Using similar code to the above example, I recreated the same scenario using completely dynamic width and height:

.fixedContainer {
    background-color:#ddd;
    position: fixed;
    padding: 2em;
    left: 50%;
    top: 0%;
    transform: translateX(-50%);
}

If you want it to be centered, you can do that too:

.fixedContainer {
    background-color:#ddd;
    position: fixed;
    padding: 2em;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
}

Demos:

jsFiddle: Centered horizontally only
jsFiddle: Centered both horizontally and vertically
Original credit goes to user aaronk6 for pointing it out to me in this answer

Haik answered 22/7, 2011 at 17:55 Comment(10)
Worked beautifully for me. Although I needed mine to the left of and already centered, unfixed div, so just had to decrease the left margin until it was aligned. No stays aligned no matter what the width of the windows. Thanks. +1Ixia
@Joseph any idea why position:fixed without specifying top or left sometimes works? Some browsers appear to default the element to where it would normally be, if it had normal positioning. #8712547Loar
what about without fixed height and width ? In my case I haven't given any signal width to any container even up to body tag. What solution you will say me to do.Breechcloth
@Breechcloth Unfortunately, this method won't work at all without a known height and width. What you go with will largely depend on what you are trying to center. If it's an image, just use it as a background of a 100% x 100% container. If it's an actual element that is completely dynamic, you will probably have to explore using a javascript solution to get the dimensions.Haik
@JosephMarikle I guess you should give a try to my answer below, and perhaps update the "short answer", because this little hack is working perfectly fine for webkit, and many times it's all one needs.Castellany
@FrancescoFrapporti That's a nice CSS hack but I think I'll keep my answer as is for a couple of reasons. For one, transform is not w3c standard (draft only) and thus subject to change. With behavior being undefined and this being (as far as I can see) a side effect of the intended style, this has potential to break at some point. The second reason is that this is a webkit only solution. Thank you for adding your answer though. plurality of solutions is what makes these kind of questions so useful to future developers trying to find a solution to their current bugs and development issues.Haik
I have found that adding left:inherit to the fixed position element can force the browser to respect the parent's offset.Evenfall
@Evenfall fascinating! I'd very much like to see a working example. Do you have fiddle set up demonstrating that method?Haik
I still have the problem of my width collapsing when I give an element a position:fixed;. Without giving a hard width of 1140px; (which works, but if screen is resized, width is too long), how can I set the original width (1140px) back to my fixed element and still retain responsive width?Gemmation
not sure why is this accepted answer, but it does not work!Ramonramona
I
238

Actually this is possible and the accepted answer only deals with centralising, which is straightforward enough. Also you really don't need to use JavaScript.

This will let you deal with any scenario:

Set everything up as you would if you want to position: absolute inside a position: relative container, and then create a new fixed position div inside the div with position: absolute, but do not set its top and left properties. It will then be fixed wherever you want it, relative to the container.

For example:

/* Main site body */
.wrapper {
    width: 940px;
    margin: 0 auto;
    position: relative; /* Ensure absolute positioned child elements are relative to this*/
}

/* Absolute positioned wrapper for the element you want to fix position */
.fixed-wrapper {
    width: 220px;
    position: absolute;
    top: 0;
    left: -240px; /* Move this out to the left of the site body, leaving a 20px gutter */
}

/* The element you want to fix the position of */
.fixed {
    width: 220px;
    position: fixed;
    /* Do not set top / left! */
}
<div class="wrapper">
    <div class="fixed-wrapper">
        <div class="fixed">
            Content in here will be fixed position, but 240px to the left of the site body.
        </div>
    </div>
</div>

Sadly, I was hoping this thread might solve my issue with Android's WebKit rendering box-shadow blur pixels as margins on fixed position elements, but it seems it's a bug.

Irrecoverable answered 6/8, 2012 at 18:34 Comment(10)
Not quite ANY scenario but it's a good start. If there's a lot of space below .wrapper then your .fixed-wrapper will end at the bottom of the parent but your .fixed element will continue to flow out of both containers and into any content below. Like I said, it's a good start, not perfect, but I don't see how this can be accomplished without some js.Particular
This doesn't play well with fluid design, however.Pandorapandour
i tried to do this, but as and when i scroll down, the header which i had applied fixed(with parent absolute to which parent was relative) didn't move as i scroll.Trench
This worked for me with a top-right div in Chromium and Firefox, except that the vertical positions of the fixed div were different (on Chromium it was on top of the parent div, on Firefox it was inside).Absolution
By accident, I wrapped the <div> with position:absolute inside the <div> with position:fixed instead, and that works perfectly well, even when resizing the window, etc., at least in Chrome and IE. So it's: <div style="position:relative"> <div style="position:fixed"> <div style="position:absolute;top:0px;"></div> </div> </div>Vantage
But by setting all these hard widths, don't we lose the responsiveness? Is there a way to implement a responsive-width fixed div? Using percentages hasn't worked for me, since width:100% means 100% of the viewport width, not the width of my bootstrap container that my fixed element is a child of.Gemmation
How does this work as according to w3c An element with position: fixed; is positioned relative to the viewport? Please enlighten me.Longitude
Don't understand what is the point of position:fixed here. Only position: absolute is needed to achieve the same.Canaan
@Longitude it is still relative to the viewport. It's just that without specifying top and left, it's positioned based on parent's position by default.Canaan
this does not work at allRamonramona
C
183

Yes, according to the specs, there is a way.

While I agree that Graeme Blackwood's should be the accepted answer, because it practically solves the issue, it should be noted that a fixed element can be positioned relatively to its container.

I noticed by accident that when applying

-webkit-transform: translateZ(0);

to the body, it made a fixed child relative to it (instead of the viewport). So my fixed elements left and top properties were now relative to the container.

So I did some research, and found that the issue was already been covered by Eric Meyer and even if it felt like a "trick", turns out that this is part of the specifications:

For elements whose layout is governed by the CSS box model, any value other than none for the transform results in the creation of both a stacking context and a containing block. The object acts as a containing block for fixed positioned descendants.

http://www.w3.org/TR/css3-transforms/

So, if you apply any transformation to a parent element, it will become the containing block.

But...

The problem is that the implementation seems buggy/creative, because the elements also stop behaving as fixed (even if this bit doesn't seem to be part of specification).

The same behavior will be found in Safari, Chrome and Firefox, but not in IE11 (where the fixed element will still remain fixed).

Another interesting (undocumented) thing is that when a fixed element is contained inside a transformed element, while its top and left properties will now be related to the container, respecting the box-sizing property, its scrolling context will extend over the border of the element, as if box-sizing was set to border-box. For some creative out there, this could possibly become a plaything :)

TEST

Castellany answered 8/4, 2013 at 17:42 Comment(8)
This enabled me to create a table with fixed headers inside of a containerBatrachian
Nice, this works for me in Chrome. Any ideas on how to achieve the same in IE? I've tried using translateZ but it didn't in any version of IE.Firer
Same.. does anyone know how to do this in IE? its kind of a pain to detect browser, then systematically show or not show left: (considering that messes it up)Ics
I just meet the opposite condition which I need fixed in relative container but changed by transform property. Your answer is very helpful, thank you!Receptive
@Francesco Frapporti seems this no longer works... in the latest version of Chrome anyway (Version 42.0.2311.90) :(Disini
Perfect fit, thank you! For anyone wondering: works for Chrome 84.0.4147.89 and Firefox 78.0.2 and Edge 44.18362.449.0Deedeeann
You can also achieve this with applying will-changeCindelyn
FF 81 let header scroll up and dessapear, but sticky do work fine.Caliche
R
86

The answer is yes, as long as you don't set left: 0 or right: 0 after you set the div position to fixed.

http://jsfiddle.net/T2PL5/85/

Checkout the sidebar div. It is fixed, but related to the parent, not to the window view point.

body {
  background: #ccc;
}

.wrapper {
  margin: 0 auto;
  height: 1400px;
  width: 650px;
  background: green;
}

.sidebar {
  background-color: #ddd;
  float: left;
  width: 300px;
  height: 100px;
  position: fixed;
}

.main {
  float: right;
  background-color: yellow;
  width: 300px;
  height: 1400px;
}
<div class="wrapper">wrapper
  <div class="sidebar">sidebar</div>
  <div class="main">main</div>
</div>
Roos answered 21/3, 2013 at 22:39 Comment(8)
Any reason why this doesn't get more upvotes? Seems the most obvious solution to me.Excellence
What about cross browser compatibility. Did any of you checked this?Existentialism
This is correct but only for the 'positioning' of the fixed element. It will not respect the container width or resize in any way. For example, If you have a fluid wrapper with max-width:1000px; margin:auto; this will not work. If everything can be a fixed width, then yes this will solve your problem.Obedience
@AlexandreBourlier Yes, this worked well for me for a fixed element in Chrome, Firefox, and IE11 at least.Madelina
Worked perfectly. Had to add margin-left:X% to bring the element to the right of the containerThemistocles
Totally wrong. Sidebar is positioned to the window view point and not the parent view point. Try this with a smaller wrapper in height. jsfiddle.net/xf0jygczAzurite
I would add to this - if your not sure whether left/top are being set use style="left:unset;right:unset;top:unset;bottom:unset;"Cimah
This actually worked for me too! Because what I am working with is anchored to the far right side of the page-wrapper, I just added a transform: translateX(-300px); (width of the element I needed fixed) in order to get it where I needed. I'm truly surprised this works, but happy to have found it!Donell
S
72

position: sticky that is a new way to position elements that is conceptually similar to position: fixed. The difference is that an element with position: sticky behaves like position: relative within its parent, until a given offset threshold is met in the viewport.

In Chrome 56 (currently beta as of December 2016, stable in Jan 2017) position: sticky is now back.

https://developers.google.com/web/updates/2016/12/position-sticky

More details are in Stick your landings! position: sticky lands in WebKit.

Sukkah answered 19/4, 2013 at 8:41 Comment(7)
This makes life so much easier, the only issue is that sticky is not supported in Internet Explorer or Edge 15 and earlier versions.Thirst
position:sticky is great. Supported by all browsers except IE caniuse.com/#feat=css-stickyDzerzhinsk
lol, so old api, and you save my day... im' using it for fixed columns for flex tables.Francesfrancesca
"within its parent" - is it possible to stay sticky element at top, either if parent scrolled up became invisible?To
sticky is much better because that also allows to set width: 100%, relative to the containing div, which the previous solutions (fixed with no left or right) do not allow.Georgettageorgette
position: sticky is one of the most useless things ever one parent has overflow:hidden and it stops workingRamonramona
I logged in just to upvote your answer. Thank you!Librate
J
59

2019 SOLUTION: You can use position: sticky property.

Here is an example CODEPEN demonstrating the usage and also how it differs from position: fixed.

How it behaves is explained below:

  1. An element with sticky position is positioned based on the user's scroll position. It basically acts like position: relative until an element is scrolled beyond a specific offset, in which case it turns into position: fixed. When it is scrolled back it gets back to its previous (relative) position.

  2. It effects the flow of other elements in the page ie occupies a specific space on the page(just like position: relative).

  3. If it is defined inside some container, it is positioned with respect to that container. If the container has some overflow(scroll), depending on the scroll offset it turns into position:fixed.

So if you want to achieve the fixed functionality but inside a container, use sticky.

Jhvh answered 20/1, 2018 at 10:51 Comment(5)
Nice solution. I didn't know about position: sticky yet. Helped a lot, thanks!Excommunicatory
I was just about to post this. Good answer! sticky is the way.Urita
If you increase the output window size in Codepen, the fixed element is not fixed but moves up. Not good. A better solution keeps it anchored to the bottom of the viewport.Sideman
@AndroidDev Only the top element is defined to be fixed for the entire page. It is being rendered as desired. The other elements are explanatory examples for different cases.Jhvh
It's important to keep in mind that position: sticky won't work if any of the parent elements uses the overflow: hidden property.Keloid
M
56

It is possible to position an element with fixed position relative to its container if the container is using certain containment rules.

<div class='parent'>
  <div class='child'></div>
</div>
.parent {
  contain: content;
}

.child {
  position: fixed;
  top: 0;
  left: 0;
}
Mou answered 31/5, 2021 at 15:33 Comment(4)
this doesn't work if I need to position the child out of parent on the left side of parent using left:-100pxEjaculate
@Ejaculate The documentation for this containment rule is very clear: "Nothing can visibly overflow".Mou
also works for me with "position: sticky" in relative blockZakarias
The browser compatibility is not good, but thank you for your answer.Vanderhoek
P
22

Just take the top and left styles out of the fixed position div. Here's an example

<div id='body' style='height:200%; position: absolute; width: 100%; '>
    <div id='parent' style='display: block; margin: 0px auto; width: 200px;'>
        <div id='content' style='position: fixed;'>content</div>
    </div>
</div> 

The #content div will be sit wherever the parent div sits, but will be fixed there.

Pterodactyl answered 28/3, 2012 at 14:23 Comment(1)
Why the minus? This works perfectly for fixing an element wherever you want in the flow of the DOM. deadlykitten.com/tests/fixedPositionTest.phpPterodactyl
G
20

I have created this jQuery plugin to solve a similar issue I was having where I had a centered container (tabular data), and I wanted the header to fix to the top of the page when the list was scrolled, yet I wanted it anchored to the tabular data so it would be wherever I put the container (centered, left, right) and also allow it to move left and right with the page when scrolled horizontally.

Here is the link to this jQuery plugin that may solve this problem:

https://github.com/bigspotteddog/ScrollToFixed

The description of this plugin is as follows:

This plugin is used to fix elements to the top of the page, if the element would have scrolled out of view, vertically; however, it does allow the element to continue to move left or right with the horizontal scroll.

Given an option marginTop, the element will stop moving vertically upward once the vertical scroll has reached the target position; but, the element will still move horizontally as the page is scrolled left or right. Once the page has been scrolled back down passed the target position, the element will be restored to its original position on the page.

This plugin has been tested in Firefox 3/4, Google Chrome 10/11, Safari 5, and Internet Explorer 8/9.

Usage for your particular case:

<script src="scripts/jquery-1.4.2.min.js" type="text/javascript"></script>
<script src="scripts/jquery-scrolltofixed-min.js" type="text/javascript"></script>

$(document).ready(function() {
    $('#mydiv').scrollToFixed();
});
Genuine answered 29/8, 2011 at 17:25 Comment(0)
B
16

I had to do this with an advertisement that my client wanted to sit outside of the content area. I simply did the following and it worked like a charm!

<div id="content" style="position:relative; width:750px; margin:0 auto;">
  <div id="leftOutsideAd" style="position:absolute; top:0; left:-150px;">
    <a href="#" style="position:fixed;"><img src="###" /></a>
  </div>
</div>
Bachman answered 30/4, 2012 at 13:55 Comment(3)
My ad was 140px wide, so I moved it 150px to the left to give it a little bit of right margin against the edge of the website frame.Bachman
what kind of hackery is that?? it totally works! You can use it with click passthrough when you want the absolute div to be invisible (#3680929)Hasty
@Hasty I love that this is still helping people over 10 years later. #proudProgrammerMomentBachman
C
16

You have a solution if you change position: fixed; to position: sticky;

So your code should be:

position: sticky;
top: 0;
right: 0;

now other divs will not slip underneath.

Clergyman answered 13/8, 2021 at 22:56 Comment(0)
D
9

Two HTML elements and pure CSS (modern browsers)

See this jsFiddle example. Resize and see how the fixed elements even move with the floated elements they are in. Use the inner-most scroll bar to see how the scroll would work on a site (fixed elements staying fixed).

As many here have stated, one key is not setting any positional settings on the fixed element (no top, right, bottom, or left values).

Rather, we put all the fixed elements (note how the last box has four of them) first in the box they are to be positioned off of, like so:

<div class="reference">
  <div class="fixed">Test</div>
  Some other content in.
</div>

Then we use margin-top and margin-left to "move" them in relation to their container, something like as this CSS does:

.fixed {
    position: fixed;
    margin-top: 200px; /* Push/pull it up/down */
    margin-left: 200px; /* Push/pull it right/left */
}

Note that because fixed elements ignore all other layout elements, the final container in our fiddle can have multiple fixed elements, and still have all those elements related to the top left corner. But this is only true if they are all placed first in the container, as this comparison fiddle shows that if dispersed within the container content, positioning becomes unreliable.

Whether the wrapper is static, relative, or absolute in positioning, it does not matter.

Depersonalization answered 12/12, 2013 at 18:39 Comment(0)
F
8

Disclaimer:

This answers just the title: Fixed position but relative to container. For the actual use case the user is asking for position: sticky is the way to go.


https://developer.mozilla.org/en-US/docs/Web/CSS/position

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

You just need to add a transform to the container and the position of the fixed element will be relative to the container. I think a transform: translateX(0); should be enough.

Foretell answered 1/11, 2020 at 10:29 Comment(2)
@NikitasIO, your comment is vague and can become obsolete. Better to comment on other answers to explain why they're not valid.Doggo
For me, transform: translateX(0); did the tricks excently, thanks!Ejaculate
G
4

You can give a try to my jQuery plugin, FixTo.

Usage:

$('#mydiv').fixTo('#centeredContainer');
Grayback answered 10/8, 2012 at 22:12 Comment(0)
M
4

With pure CSS you can't manage to do it; at least I haven't. However you can do it with jQuery very simply. I'll explain my problem, and with a little change you can use it.

So for a start, I wanted my element to have a fixed top (from top of the window), and a left component to inherit from the parent element (because the parent element is centered). To set the left component, just put your element into the parent and set position:relative for the parent element.

Then you need to know how much from the top your element is when the a scroll bar is on top (y zero scrolled); there are two options again. First is that is static (some number) or you have to read it from the parent element.

In my case it's 150 pixels from top static. So when you see 150 it's how much is the element from the top when we haven't scrolled.

CSS

#parent-element{position:relative;}
#promo{position:absolute;}

jQuery

$(document).ready(function() { //This check window scroll bar location on start
    wtop=parseInt($(window).scrollTop());
    $("#promo").css('top',150+wtop+'px');

});
$(window).scroll(function () { //This is when the window is scrolling
    wtop=parseInt($(window).scrollTop());
    $("#promo").css('top',150+wtop+'px');
});
Midden answered 23/5, 2013 at 13:44 Comment(5)
Problem is that the div in question flickers when scrolling.Staghound
Probably because scrolling is refreshing too much or too fast. I didn't have that problem tbh, but I can suggest you try with using global "blocker" which would be refreshed for example every 10ms or some time, and set to blocking value every time you make some height change. Of course you have to add if condition to .scroll event that is checking if in this period (10ms) you already scrolled div. I repeat I haven't tried but I believe it could work :) On this way you could stop div from changing it's position too much so that computer can't actually follow, and enough so human eye see's it.Midden
I already gave your answer +1 mate ;) The pain with attaching a global looping method is really performance. To get something like that to work nicely in older pc's and tablets is painful. Many a time a junior dev at work has written a 'var x' inside such a method resulting in needless memory leaks if the page is left open too long :P But yea your suggestion seems like the only real option.Staghound
You got point with global loops; isn't good, I agree. I just like to think about this kind of problems, that's why I wrote another suggestion :) Tbh, now looking it little better, I would avoid it xD I got another solution now. What you say about setting setTimeout() on scroll event which calls func. that makes div movement..also you use global blocker which is set to true while waiting for timeout and when timeout is called you return blocker to false which enables another call after some time...on this way you wouldn't use global loop but still have control on frequency of div movement.Midden
It's more elegant but I find it hard to accept. This is the sort of thing I expect the html and css specs to handle tbh. Hate the fact that js is involved in the first place!Staghound
C
3

Another weird solution to achieve a relative fixed position is converting your container into an iframe, that way your fixed element can be fixed to it's container's viewport and not the entire page.

Camembert answered 24/7, 2012 at 21:46 Comment(0)
T
3

I have the same issue, one of our team members gives me a solution. To allowed the div fix position and relative to other div, our solution is to use a parent container wrap the fix div and scroll div.

.container {
  position: relative;
  flex:1;
  display:flex;
}

.fix {
  position:absolute;
}
<div class="container">
  <div class="scroll"></div>
  <div class="fix"></div>
</div>
Treehopper answered 21/2, 2017 at 21:52 Comment(0)
T
3

Yes it is possible as long as you don't set the position (top or left, etc.) of your fixed element (you can still use margin to set a relative position, though). Simon Bos posted about this a while ago.

However don't expect fixed element to scroll with non-fixed relatives.

See a demo here.

Thrave answered 28/2, 2020 at 9:24 Comment(0)
S
2

This is easy (as per HTML below)

The trick is to NOT use top or left on the element (div) with "position: fixed;". If these are not specified, the "fixed content" element will appear RELATIVE to the enclosing element (the div with "position:relative;") INSTEAD OF relative to the browser window!!!

<div id="divTermsOfUse" style="width:870px; z-index: 20; overflow:auto;">
    <div id="divCloser" style="position:relative; left: 852px;">
        <div style="position:fixed; z-index:22;">
            <a href="javascript:hideDiv('divTermsOfUse');">
                <span style="font-size:18pt; font-weight:bold;">X</span>
            </a>
        </div>
    </div>
    <div>  <!-- container for... -->
         lots of Text To Be Scrolled vertically...
         bhah! blah! blah!
    </div>
</div>

Above allowed me to locate a closing "X" button at the top of a lot of text in a div with vertical scrolling. The "X" sits in place (does not move with scrolled text and yet it does move left or right with the enclosing div container when the user resizes the width of the browser window! Thus it is "fixed" vertically, but positioned relative to the enclosing element horizontally!

Before I got this working the "X" scrolled up and out of sight when I scrolled the text content down.

Apologies for not providing my javascript hideDiv() function, but it would needlessly make this post longer. I opted to keep it as short as possible.

Skyway answered 11/2, 2014 at 1:34 Comment(1)
Solid cross-browser solution, works in IE8 like a charm.Raggletaggle
S
2
/* html */

/* this div exists purely for the purpose of positioning the fixed div it contains */
<div class="fix-my-fixed-div-to-its-parent-not-the-body">

     <div class="im-fixed-within-my-container-div-zone">
          my fixed content
     </div>

</div>



/* css */

/* wraps fixed div to get desired fixed outcome */
.fix-my-fixed-div-to-its-parent-not-the-body 
{
    float: right;
}

.im-fixed-within-my-container-div-zone
{
    position: fixed;
    transform: translate(-100%);
}
Sabbat answered 14/9, 2018 at 3:6 Comment(0)
P
1

It's possible if you use JavaScript. In this case, the jQuery plugin Sticky-Kit:

Pantelegraph answered 13/8, 2015 at 11:39 Comment(0)
S
1

I created a jsfiddle to demostrate how this works using transform.

HTML

<div class="left">
    Content
</div>
<div class="right">
<div class="fixedContainer">
    X
</div>
    Side bar
</div>

CSS

body {
  margin: 0;
}
.left {
  width: 77%;
  background: teal;
  height: 2000px;
}
.right {
  width: 23%;
  background: yellow;
  height: 100vh;
  position: fixed;
  right: 0;
  top: 0;
}
.fixedContainer {
    background-color:#ddd;
    position: fixed;
    padding: 2em;
    //right: 0;
    top: 0%;
    transform: translateX(-100px);
}

jQuery

$('.fixedContainer').on('click', function() {
    $('.right').animate({'width': '0px'});
  $('.left').animate({'width': '100%'});
});

https://jsfiddle.net/bx6ktwnn/1/

Scaife answered 9/8, 2016 at 21:7 Comment(0)
M
1

My project is .NET ASP Core 2 MVC Angular 4 template with Bootstrap 4. Adding "sticky-top" into main app component html (i.e. app.component.html) on the first row worked, as follows:

<div class='row sticky-top'>
    <div class='col-sm-12'>
        <nav-menu-top></nav-menu-top>
    </div>
</div>
<div class="row">
    <div class='col-sm-3'>
        <nav-menu></nav-menu>
    </div>
    <div class='col-sm-9 body-content'>
        <router-outlet></router-outlet>
    </div>
</div>

Is that the convention or did I oversimplify this?

Myronmyrrh answered 2/11, 2017 at 19:16 Comment(0)
M
1

When you use position:fixed CSS rule and try to apply top/left/right/bottom it position the element relative to window.

A workaround is to use margin properties instead of top/left/right/bottom

Message answered 17/3, 2020 at 8:23 Comment(0)
M
1

The magic is to take the screen width minus the container width and divide it by 2:

//1400px is according to container max-width (left can be also right)
.fixed {
  position: fixed;
  right: calc((100vw - 1400px)/2);
}

Note: css calc() function is almost, but not 100% supported. For most use-cases it is definitely supported enough. Click here for more details

Snippet (with a 300px container just to fit this website's widget):

.container {
  max-width: 300px;
  margin-left: auto;
  margin-right: auto;
}


.fixed {
  position: fixed;
  right: calc((100vw - 300px)/2);
}


@media screen and (max-width: 300px) {
  right: 0px;
}
<div style="height: 3000px">
    <div class="container">
        <button class="fixed">
            FIXED CONTENT
        </button>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Laborum, eum? Animi quidem accusamus minima vel, dolorem suscipit quia accusantium minus harum modi commodi distinctio! Iste voluptatum earum quam voluptate culpa ad, ipsum dolorum recusandae quis atque eligendi necessitatibus magnam nisi dolores beatae qui? Perspiciatis natus cum nostrum in quod odio sapiente doloremque rerum quo dolore tenetur facere, quisquam atque accusamus fugiat eligendi, deleniti nisi minus recusandae distinctio dignissimos! Dicta quos ipsum qui pariatur at vel veritatis veniam quisquam minus modi et voluptas aliquam laborum, cumque in quo magnam sapiente. Expedita ut dolore laboriosam tempora reprehenderit vero eaque blanditiis, cumque voluptatibus, velit nemo, veniam tenetur quisquam numquam adipisci quae odio repellendus neque incidunt! Cum odio corporis soluta voluptate nesciunt, quasi nobis deleniti neque porro expedita fugiat placeat alias autem pariatur animi error, dicta veritatis atque perspiciatis inventore tempora dolor ad! Mollitia in dolorem ipsam eos porro magni perspiciatis possimus maiores, itaque facere ut. Eos culpa eum error quia incidunt repellendus quam possimus, asperiores earum ipsum molestias dicta sint fugit atque veniam dolorum illo? Officia harum sint incidunt totam, reiciendis illum eos maxime sequi neque repellat quis, expedita eum, corporis quaerat nemo qui soluta aspernatur animi. Sint ad rem numquam omnis sit.
    </div>
 </div>
Monotint answered 20/9, 2020 at 13:48 Comment(0)
G
1

To achieve a similar purpose as the one requested "fixed position relative to container", for me position:fixed was not working since when I scrolled the page the element remained in a fixed position, but you can achieve a similar effect with the overflow feature.

On the snipet below, check how the heading appears fixed when in the parent container, but when you scroll the body it scrolls too

#grandpa{
    width: 100vw;
    height: 120vh;
    background-color:rgb(236, 233, 233);
    overflow:hidden;
}
#parent{
    width: 200px;
    height: 200px;
    background-color:teal;
    overflow:hidden;
}
#child1{
    padding:1em
}
#child2{
    height: 100px;
    background-color:khaki;
    overflow-y:scroll;
}
<div id="grandpa">
    <div id="parent">
        <div id="child1">
            heading
        </div>
        <div id="child2">
            <p>body</p>
            <p>body</p>
            <p>body</p>
            <p>body</p>
            <p>body</p>
            <p>body</p>
            <p>body</p>
            <p>body</p>
        </div>
    </div>
</div>
Greatly answered 11/11, 2021 at 6:6 Comment(0)
D
1

It is possible with this on the parent element:

container-type: inline-size

No clue if this is expected behavior but I just stumbled upon this.

Defector answered 8/9, 2023 at 12:50 Comment(1)
Just solved the issue for me. Idk how and why tbh and it seems to work cross browser.Reverberate
N
0

I did something like that awhile back. I was pretty new to JavaScript, so I'm sure you can do better, but here is a starting point:

function fixxedtext() {
    if (navigator.appName.indexOf("Microsoft") != -1) {
        if (document.body.offsetWidth > 960) {
            var width = document.body.offsetWidth - 960;
            width = width / 2;
            document.getElementById("side").style.marginRight = width + "px";
        }
        if (document.body.offsetWidth < 960) {
            var width = 960 - document.body.offsetWidth;
            document.getElementById("side").style.marginRight = "-" + width + "px";
        }
    }
    else {
        if (window.innerWidth > 960) {
            var width = window.innerWidth - 960;
            width = width / 2;
            document.getElementById("side").style.marginRight = width + "px";
        }
        if (window.innerWidth < 960) {
            var width = 960 - window.innerWidth;
            document.getElementById("side").style.marginRight = "-" + width + "px";
        }
    }
    window.setTimeout("fixxedtext()", 2500)
}

You will need to set your width, and then it gets the window width and changes the margin every few seconds. I know it is heavy, but it works.

Nubia answered 22/7, 2011 at 17:59 Comment(2)
one problem I can see with this approach is that it relies on a timer (2.5 seconds) and during that time, if the user resizes the window, it will take up to that time for it to correct itself. That's not the best thing when it comes to user experience. Also, if it can be helped, try using event listeners instead of timers.Haik
Like I said it a OLD script, one of my first, and have not needed to go back a fix it. So it is not the best , but it can be a good starting point.Nubia
W
0

I am late to answer this question but I am sure this is a common problem to exist in future as well and will definitely help the future searchers.

This can be solved by applying a trick. We can use calc here. Within calc we can use 100 vertical width and subtract 90% of the width and divide by 2. Please make changes to the 90% as per your needs. In your case it can be 100% or 70% whatever depending upon your specific requirement.

.your-class {
  position: fixed;
  right: calc((100vw - 90%)/2);
}

This worked for me. Please note that in my case I intended the floating element to be shifted on the right side. If you want it on the left please use left instead of right.

Wey answered 2/11, 2021 at 6:38 Comment(2)
The provided might not have been working 10 years ago. But it's nice to share what works at least now.Clarkin
@Clarkin Yes, right.Wey
J
0

In my experience, the best way to handle this was to kick the element out of the parent element.

position: sticky didn’t work for me because it didn’t stay fixed on scroll, and position:absolute wasn’t satisfying because it took it out of the document flow.

What I did simply was put the element at the same level as the parent element (so that they are siblings). That way it’s fixed above the element and isn’t taken out of the flow. No additional complicated css or js required.

Jumpy answered 26/8, 2022 at 7:0 Comment(0)
P
0

Use Proper HTML Element Positioning and Position: Sticky

Explanation:

  1. We have placed the sticky div above the scrollable, what this will do is that the sticky will stay on it's place on both scroll up and down, otherwise the sticky div can be shifted by any kind of scroll.
  2. We have given CSS property position: sticky and not fixed, because position: fixed will take the div out of flow of its container. And height of container is 400px so we have given top: 100px which is 25% of 400px to the sticky div and we have given bottom: 300px which is 75% of 400px.

.container {
    width: 600px;
    height: 480px;
    overflow-x: hidden;
    background-color: #212529;
    color: #FFFFFF;
    box-shadow: 0px 10px 10px #1d1d1d;
}


.sticky {
    position: sticky;
    top: 100px;
    bottom: 300px;
}

.scrollable {
    height: 140%;
    width: 100%;
}


/* Non-question related stylings */
.sticky button {
  background: darkslateblue;
  color: white;
  font-size: 16px;
  padding: 5px;
  margin: 10px;
  border: 1px solid darkgray;
  box-shadow: 0px 0px 10px 5px rgba(159, 90, 253, 1);
}
<html>
<!-- Place The Position Sticky Tag Above Overflowing Element -->
  
  <body>
    <div class="container">
    
      <div class="sticky">
        <button> I'm A Button </button>
      </div>

      <div class="scrollable">
        Lorem ipsum dolor, sit amet consectetur adipisicing elit. Incidunt ullam placeat, delectus suscipit nemo, corporis voluptatem soluta fuga dolore eum, aspernatur laborum eos?
      </div>
    
    </div>
  </body>
</html>
Proffer answered 17/10, 2023 at 15:42 Comment(0)
L
-1

In this case, you can change the positions of the fixed element according to its parent element.

you can get the position of your parent element using the following code.

function coordinatesSetter() {
    var elm = $('parentElement');
    var rect = elm.getBoundingClientRect(),
    scrollLeft = window.pageXOffset || document.documentElement.scrollLeft,
    scrollTop = window.pageYOffset || document.documentElement.scrollTop;

    return {top: rect.top + scrollTop, left: rect.left + scrollLeft});
 }
Lalapalooza answered 30/9, 2022 at 13:44 Comment(1)
it's very easy to do the same without the need of jquery or any javascript. I wouldn't recommend this approach.Smelter
D
-2

Check this:

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title></title>
    </head>
    <body style="width: 1000px !important;margin-left: auto;margin-right: auto">
        <div style="width: 100px; height: 100px; background-color: #ccc; position:fixed;">
        </div>
        <div id="1" style="width: 100%; height: 600px; background-color: #800000">
        </div>
        <div id="2" style="width: 100%; height: 600px; background-color: #100000">
        </div>
        <div id="3" style="width: 100%; height: 600px; background-color: #400000">
        </div>
    </body>
</html>
Despite answered 11/4, 2012 at 7:20 Comment(1)
I don't think this is accomplishing quite what the OP asked about.Sunfish

© 2022 - 2024 — McMap. All rights reserved.