Sticky top div with absolute positioning
Asked Answered
F

10

58

I'm using absolute positioning to have a div fill up the entire browser window. However, I wan't to combine this with a sticky div that sometimes is there and sometimes not.

To make things a little clearer, check out this jsFiddle: http://jsfiddle.net/henrikandersson/aDdRS/

I want the "top", "left" and "subheader" to stay where they are at all times. I also want the "content" div to fill up what is left of the window. However, sometimes I want to display the "alert" div before "content". So far so good, as you can see in the jsFiddle. But, I want "alert" to stick to the "subheader" and stay there when scrolling. As you can see if you resize the window, "alert" will now be scrolled along with "content" - I don't want it to be.

Anyone got an idea of how to solve this?

EDIT: I made a change in my jsFiddle, I placed the "alert" where it should be (between subheader and content-area). As you can see ( http://jsfiddle.net/henrikandersson/aDdRS/12 ) it does not push the "content-area" down since content-area has top:20px. And I can't set top:40px for example since "alert" should be able to vary in height and I want content-area to have the same css with or without the alert above.

EDIT #2: This question deals with the same problem, but there is no solution for that question either. Seems like it's not possible without using JavaScript: variable height scrolling div, positioned relative to variable height sibling

Franco answered 30/11, 2011 at 15:56 Comment(3)
Would it be possible to have the <div id="alert"></div> to be not there, if it is empty, or in other words, just print this div, if it has a content?Madsen
@HerrSerker yes, it should be possible to hide/display the div, but this is kind of part of the problem (see edit above)Franco
I mean not hide/display with CSS, but fully remove it from source code id empty? If so, me edited fiddel fits your needs, if not, it fits your needs in browsers with supprt for :empty pseudo-classMadsen
C
77

2018-6-18

I choose the CSS way with position: sticky.

that https://github.com/abouolia/sticky-sidebar .
doesn't work for me (I am using Vue.js 2.0 SPA with vue-router & vuex)

I also want the element position: absolute first,
and then position: sticky

Solution

  1. parent HTML element use position: absolute to have the right position.

(don't forget to set height for parent. for example height:100%)

  1. child HTML element position: sticky

work for me. enter image description here

enter image description here

Cyd answered 18/6, 2018 at 9:24 Comment(8)
I made a Youtube video on this answer: (30 second) youtube.com/watch?v=LVlD6NmCjts&feature=youtu.beCyd
I managed to make it work with the opposite: parent sticky and child as absolute (which gives the parent a height of 0). But thanks for pointing in the right direction :)Anaximenes
Thanks for the video, good answer. I was also able to get this to work.Smoothen
It's important to set the height to 100% for this to work!Feminacy
If you can't set the height to 100%, I can confirm that @RyanPergent's method works. Set the parent to sticky and the child to absolute. You still need the container (whatever is scrolling) to have position relative though.Colwin
No parent or 100% height needed!Headrick
Do you have reproducible code?Paulie
MDN docs also says: "Note that a sticky element "sticks" to its nearest ancestor that has a "scrolling mechanism" (created when overflow is hidden, scroll, auto, or overlay), even if that ancestor isn't the nearest actually scrolling ancestor." Didn't work for me until I removed overflow: hidden from the parentBesom
A
23

position: fixed is a combination of both absolute and sticky

Anacardiaceous answered 4/1, 2022 at 18:9 Comment(2)
No, it's not. It might work like that in some cases, but that's not what fixed is. The absolute position in relative to the closest positioned ancestor, while fixed is to the initial containing block established by the viewport. developer.mozilla.org/en-US/docs/Web/CSS/positionNeoteny
fixed is not a combination of both. Its fixed to the viewport, not to the parent. It overflows the parent even if you have position: relative;.Incrocci
P
6

Use float: left; and width: 0; and you can use transform: translateX(xxx); for set left position.

Problem solved :)

Pita answered 26/9, 2019 at 8:39 Comment(1)
Smart solution hahaha. Thanks a lot helped me so muchCountercurrent
M
5

edit
update with some enhancements

body {
    height: 100%;
    overflow: hidden;
}
#top{
    position: absolute;
    background: yellow;
    height: 50px;
    width: 100%;
    top: 0;
}
#left {
    background: #e3e3e3;
    position: absolute;
    bottom: 0;
    left: 0;
    top: 50px;
    width: 200px;
}

#right {
    position: absolute;
    bottom: 0;
    left: 200px;
    right: 0;
    top: 50px;
}
#sub-header {
    height: 20px;
    background: orange;
}
#content-area {
    position: absolute;
    top: 20px;
    right: 0;
    bottom: 0;
    left: 0;
}
#alert {
    background: red;
    color: white;

}
#content {
    width: 100%;
    top: 0px;
    left: 0px;
    bottom: 0px;
    right: 0px;
    overflow-y: auto;
    position: absolute;
}
#alert + #content {
    top: 20px;
}
#alert:empty + #content {
    top: 0px;
}
<body>
<div class="container">
    <div id="top">top</div>
    <div id="left">left</div>
    <div id="right">
        <div id="sub-header">subheader</div>
        <div id="content-area">
            <div id="alert">alert!</div>
            <div id="content">content<br /><br /><br />Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc eget nunc magna, eget vehicula ligula. Vestibulum in massa massa, ut feugiat arcu. Suspendisse feugiat commodo tellus, id aliquam dolor cursus eu. Aliquam erat volutpat. Nulla interdum ipsum ut lectus sollicitudin blandit sodales ante malesuada. Etiam ac neque ut turpis faucibus luctus non et arcu. Maecenas ut risus ut odio fringilla sagittis. Sed nulla lorem, suscipit at condimentum quis, adipiscing eget turpis. Morbi accumsan est at tellus hendrerit sed blandit nibh sagittis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Praesent gravida, velit id sodales bibendum, nulla leo rutrum quam, vel tempus justo mi vitae sapien. In imperdiet blandit rhoncus. Phasellus at massa nulla, ut tincidunt est. Nam viverra dui non enim semper consequat. Etiam sed libero sed ante condimentum bibendum ultrices eu nunc.

Integer massa nibh, interdum eget consectetur sed, scelerisque a ipsum. Fusce et ligula erat. Vestibulum lacus enim, facilisis id sollicitudin non, condimentum eu sem. Donec quis magna nec massa vulputate hendrerit. Nam leo nulla, fermentum eu congue quis, imperdiet sit amet orci. Aliquam ornare felis commodo est rhoncus blandit. Quisque at neque ac turpis vulputate sagittis. Donec et viverra risus. Fusce posuere lacus aliquam erat molestie sed tincidunt elit placerat. Sed pulvinar varius neque. Nullam congue adipiscing quam egestas convallis. Sed molestie massa euismod dolor facilisis laoreet.

Cras sit amet nisi sapien, non fringilla arcu. Aenean euismod gravida sem. Donec eu luctus justo. Aliquam erat volutpat. Mauris vestibulum sagittis magna, eget bibendum dolor tempor nec. Nunc rhoncus suscipit felis eu imperdiet. Sed fermentum diam non turpis tempor sit amet adipiscing leo elementum. Donec aliquam consequat elit id auctor.

Praesent vehicula, nibh a elementum imperdiet, urna nulla iaculis leo, ac hendrerit sem massa ac tortor. Suspendisse viverra consectetur libero a luctus. Maecenas iaculis mi id urna fermentum condimentum viverra tellus vulputate. Suspendisse potenti. Aliquam fermentum nulla quis dolor commodo scelerisque. Donec cursus laoreet consectetur. Praesent ultricies arcu ut ante hendrerit imperdiet. Etiam at metus lectus. Aliquam ut ligula neque. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;

Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec auctor scelerisque purus non sollicitudin. Sed elementum facilisis nisl, eget commodo est congue in. Etiam tincidunt viverra felis, vel tincidunt nulla pretium vel. Phasellus commodo bibendum magna et imperdiet. Aenean euismod condimentum magna eget venenatis. Pellentesque lorem eros, ornare at egestas vel, tincidunt non nunc. Quisque non diam nisl, ut consectetur metus. Fusce ipsum tortor, viverra et lobortis et, ullamcorper non magna. Duis elementum molestie sem, et ullamcorper neque eleifend non. Nunc iaculis quam eros, in pellentesque nunc. Donec tincidunt faucibus est, porta cursus eros imperdiet volutpat.</div>
        </div>
    </div>
    
</div>
<body>

first post
Why not scroll just the .content and not the .content-area

body {
    height: 100%;
    overflow: hidden;
}
#top{
    position: absolute;
    background: yellow;
    height: 50px;
    width: 100%;
    top: 0;
}
#left {
    background: #e3e3e3;
    position: absolute;
    bottom: 0;
    left: 0;
    top: 50px;
    width: 200px;
}

#right {
    position: absolute;
    bottom: 0;
    left: 200px;
    right: 0;
    top: 50px;
}
#sub-header {
    height: 20px;
    background: orange;
}
#content-area {
    position: absolute;
    top: 20px;
    right: 0;
    bottom: 0;
    left: 0;
}
#alert {
    background: red;
    color: white;

}
#content {
    width: 100%;
    height: 100%;
    overflow-y: auto;
}
<body>
<div class="container">
    <div id="top">top</div>
    <div id="left">left</div>
    <div id="right">
        <div id="sub-header">subheader</div>
        <div id="content-area">
            <div id="alert">alert!</div>
            <div id="content">content<br /><br /><br />Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc eget nunc magna, eget vehicula ligula. Vestibulum in massa massa, ut feugiat arcu. Suspendisse feugiat commodo tellus, id aliquam dolor cursus eu. Aliquam erat volutpat. Nulla interdum ipsum ut lectus sollicitudin blandit sodales ante malesuada. Etiam ac neque ut turpis faucibus luctus non et arcu. Maecenas ut risus ut odio fringilla sagittis. Sed nulla lorem, suscipit at condimentum quis, adipiscing eget turpis. Morbi accumsan est at tellus hendrerit sed blandit nibh sagittis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Praesent gravida, velit id sodales bibendum, nulla leo rutrum quam, vel tempus justo mi vitae sapien. In imperdiet blandit rhoncus. Phasellus at massa nulla, ut tincidunt est. Nam viverra dui non enim semper consequat. Etiam sed libero sed ante condimentum bibendum ultrices eu nunc.

Integer massa nibh, interdum eget consectetur sed, scelerisque a ipsum. Fusce et ligula erat. Vestibulum lacus enim, facilisis id sollicitudin non, condimentum eu sem. Donec quis magna nec massa vulputate hendrerit. Nam leo nulla, fermentum eu congue quis, imperdiet sit amet orci. Aliquam ornare felis commodo est rhoncus blandit. Quisque at neque ac turpis vulputate sagittis. Donec et viverra risus. Fusce posuere lacus aliquam erat molestie sed tincidunt elit placerat. Sed pulvinar varius neque. Nullam congue adipiscing quam egestas convallis. Sed molestie massa euismod dolor facilisis laoreet.

Cras sit amet nisi sapien, non fringilla arcu. Aenean euismod gravida sem. Donec eu luctus justo. Aliquam erat volutpat. Mauris vestibulum sagittis magna, eget bibendum dolor tempor nec. Nunc rhoncus suscipit felis eu imperdiet. Sed fermentum diam non turpis tempor sit amet adipiscing leo elementum. Donec aliquam consequat elit id auctor.

Praesent vehicula, nibh a elementum imperdiet, urna nulla iaculis leo, ac hendrerit sem massa ac tortor. Suspendisse viverra consectetur libero a luctus. Maecenas iaculis mi id urna fermentum condimentum viverra tellus vulputate. Suspendisse potenti. Aliquam fermentum nulla quis dolor commodo scelerisque. Donec cursus laoreet consectetur. Praesent ultricies arcu ut ante hendrerit imperdiet. Etiam at metus lectus. Aliquam ut ligula neque. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;

Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec auctor scelerisque purus non sollicitudin. Sed elementum facilisis nisl, eget commodo est congue in. Etiam tincidunt viverra felis, vel tincidunt nulla pretium vel. Phasellus commodo bibendum magna et imperdiet. Aenean euismod condimentum magna eget venenatis. Pellentesque lorem eros, ornare at egestas vel, tincidunt non nunc. Quisque non diam nisl, ut consectetur metus. Fusce ipsum tortor, viverra et lobortis et, ullamcorper non magna. Duis elementum molestie sem, et ullamcorper neque eleifend non. Nunc iaculis quam eros, in pellentesque nunc. Donec tincidunt faucibus est, porta cursus eros imperdiet volutpat.</div>
        </div>
    </div>
    
</div>
<body>
Madsen answered 30/11, 2011 at 17:12 Comment(8)
If #alert is empty, it is not visible.Madsen
Since content in your example has height 100%, the entire scrollbar will not be visible. In my example overflow does not have any effect on the div.Franco
Yes, this is almost what I want. The problem is that alert can't vary in height now. If there is no other way to do this I guess I can live with that. Do you know how well #alert + #content and #alert:empty + #content will work in older browsers, say IE7?Franco
#alert + #contentshould work with no problem, if you do not add the elements with javascript dynamically. #alert:empty + #content will not work in IE8- quirksmode.org/css/contents.htmlMadsen
In that case, I recommend using JavaScript. On page load, get the CSS height of #alert and adjust the CSS top of #contentMadsen
Hm, that's a problem I'm afraid, I need support for IE7 (definitely for IE8). And I was trying to avoid using JavaScript for this since I need it to work well even if the user resizes the browser window, making the content of alert take up more rows than when calculating the height of the div - and I don't want to have to count on resize.Franco
I think there is not much we can do about that. Need to propose float:top and float:bottom to the W3C :)Madsen
I chose to go with a JavaScript solution after all, seems like the only really good solution if IE8 users are going to be included in the fix. +1 for great help though yunzen, thanks alot!Franco
F
2
  • Add fixed height & width 100% to alert + position:fixed
  • Add padding-top to content
  • Only downfall is of course the extra padding if there is no alert...

See http://jsfiddle.net/aDdRS/5/

Figurative answered 30/11, 2011 at 16:10 Comment(1)
Yeah, the problem is that I need the layout (the padding) to be the same with or without the alert. Also, this makes the scrollbar hidden in part behind the alert.Franco
D
2

The alert scrolls with the content because it's inside the content-area which has overflow-y: auto.

Move it out of the content-area (put it in between subheader and content-area), and remove the position: absolute (and top/left/right/bottom) attributes from the content. In that example I see no reason for content to be absolute-positioned, normal flow will put it where it wants to be.

Dabber answered 30/11, 2011 at 16:47 Comment(2)
Yep, placing the alert between subheader and content-area is what I want, however when I remove absolute positioning and top/left/bottom/right, content does not fill the entire height of the window which I need it to.Franco
But it is not 100%, it is 100% minus the height of the divs above it.Franco
F
0

I chose to go with a JavaScript approach after all. Would have preferred a pure CSS approach but my need for IE8 support stood in the way. This answer by Myles Gray is pretty much what I did - https://mcmap.net/q/1546605/-variable-height-scrolling-div-positioned-relative-to-variable-height-sibling

Franco answered 23/9, 2012 at 7:22 Comment(0)
H
0

Sticky + absolute w/o parent:

html,
body {
  height: 250vh;
  color: #fff;
  position: relative;
}

.child {
  margin: 100px auto -100px;
  height: 100px;
  width: 200px;
  background-color: firebrick;
  position: sticky;
  top: 50px;
  padding: 10px;
}
<div class="child">Hi, I'm sticky AND absolutely positioned!</div>
Headrick answered 6/9, 2022 at 14:42 Comment(0)
I
0

You can keep the position to absolute then create a new property called background-attachment then set it to fixed. This gives you the ability to have two elements within the same parent.

Illuminance answered 14/7, 2023 at 16:22 Comment(0)
V
0

Set sticky's height as 0px and overflowing the inside child.

<div class="sticky">
  <div class="contents"></div>
</div>
.sticky{
  position:sticky;
  height:0;
  overflow:visible;
}

.contents{
  position:relative; // Or absolute if you need.
  width:100px;
  height:100px;
  background:yellow;
}
Valence answered 16/4 at 11:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.