Reputation: 14954
The relevant elements in the code below are .top
, .sticky
and .other
.
.sticky
and .other
are sitting inside the .navbar
container.
Now, making the whole .navbar
sticky is easy. Adding position: sticky; top: 0;
to that element does that. That's the general behavior I want.
The challenge I'm facing is:
How to make only the .sticky
element sticky so that everything underneath will always scroll underneath it?
If you run the current code, you can see that the .sticky
element only remains sticky until the yellow .other
element has scrolled underneath it. After that the .sticky
element stops being sticky.
That's the problem I'm trying to solve. How to keep the blue .sticky
element always sticky? (after you scroll up to the point where the green .top
part becomes hidden)
Ideally looking for a css-only solution. If that's not possible, a JavaScript/jQuery solution would be acceptable but has to work properly when scrolling in both directions up or down.
UPDATE:
I know that taking the yellow .other
element out of the header would solve the problem. But the problem is that the yellow .other
element needs to be part of the header. Both .sticky
and .other
need to be displayed next to each other on large screens and under each other on mobile screens. That's why they are currently child elements inside another container. So, moving the yellow element out of the header is not really an option I could use in this case.
.top {
min-height: 40px;
background-color: darkgreen;
}
.navbar {
/* position: sticky;*/
/* top: 0;*/
}
.sticky {
min-height: 50px;
background-color: lightblue;
position: sticky;
top: 0;
}
.other {
min-height: 90px;
background-color: yellow;
}
.content {
background-color: lightgray;
min-height: 600px;
}
.bottom {
background-color: darkgray;
min-height: 200px;
}
<div class="top">
Top
</div>
<div class="middle">
<header class="navbar">
<div class="header-container">
<div id="row-masthead">
<div class="sticky">
Sticky
</div>
<div class="other">
Other
</div>
</div>
</div>
</header>
<main class="content">
<h2>
Content
</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
</main>
</div>
<div class="bottom">
<h2>Footer</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
</div>
Upvotes: 4
Views: 518
Reputation: 272965
One solution is to consider the use of display:contents
in the containers of the sticky elements to make them like they don't exist and you will have what you want:
.top {
min-height: 40px;
background-color: darkgreen;
}
.navbar,
.header-container,
#row-masthead{
display:contents /* added this */
}
.sticky {
min-height: 50px;
background-color: lightblue;
position: sticky;
top: 0;
}
.other {
min-height: 90px;
background-color: yellow;
}
.content {
background-color: lightgray;
min-height: 600px;
}
.bottom {
background-color: darkgray;
min-height: 200px;
}
<div class="top">
Top
</div>
<div class="middle">
<header class="navbar">
<div class="header-container">
<div id="row-masthead">
<div class="sticky">
Sticky
</div>
<div class="other">
Other
</div>
</div>
</div>
</header>
<main class="content">
<h2>
Content
</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
</main>
</div>
<div class="bottom">
<h2>Footer</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
</div>
Another hacky solution is to create the needed space the sticky element using a combination of height and negative margin like below. The drawback is that you need to find the correct value to avoid creating a lot of space at the bottom and to have the needed space for the sticky.
.top {
min-height: 40px;
background-color: darkgreen;
}
div#row-masthead:after {
content: "";
display: block;
height: 200vh; /*big value here*/
}
div#row-masthead {
margin-bottom:-200vh; /*same value here*/
}
.sticky {
min-height: 50px;
background-color: lightblue;
position: sticky;
top: 0;
}
.other {
min-height: 90px;
background-color: yellow;
}
.content {
background-color: lightgray;
min-height: 600px;
}
.bottom {
background-color: darkgray;
min-height: 200px;
}
<div class="top">
Top
</div>
<div class="middle">
<header class="navbar">
<div class="header-container">
<div id="row-masthead">
<div class="sticky">
Sticky
</div>
<div class="other">
Other
</div>
</div>
</div>
</header>
<main class="content">
<h2>
Content
</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
</main>
</div>
<div class="bottom">
<h2>Footer</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
</div>
With some JS you can dynamically and correctly calculate the value:
var h = document.querySelector('.middle').offsetHeight - document.querySelector('.navbar').offsetHeight;
document.querySelector('#row-masthead').style.setProperty("--h", h+"px");
window.onresize = function(event) {
h = document.querySelector('.middle').offsetHeight - document.querySelector('.navbar').offsetHeight;
document.querySelector('#row-masthead').style.setProperty("--h", h+"px");
}
.top {
min-height: 40px;
background-color: darkgreen;
}
div#row-masthead:after {
content: "";
display: block;
height: var(--h,0);
}
div#row-masthead {
margin-bottom:calc(-1*var(--h,0));
}
.sticky {
min-height: 50px;
background-color: lightblue;
position: sticky;
top: 0;
}
.other {
min-height: 90px;
background-color: yellow;
}
.content {
background-color: lightgray;
min-height: 600px;
}
.bottom {
background-color: darkgray;
min-height: 200px;
}
<div class="top">
Top
</div>
<div class="middle">
<header class="navbar">
<div class="header-container">
<div id="row-masthead">
<div class="sticky">
Sticky
</div>
<div class="other">
Other
</div>
</div>
</div>
</header>
<main class="content">
<h2>
Content
</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
</main>
</div>
<div class="bottom">
<h2>Footer</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
</div>
Upvotes: 3
Reputation: 550
check the following code, it may help you. Check it into full page or full screen mode, in the desktop mode sticky and other sections are side by side and in mobile view other div is under the sticky div. It needs media queries for mobile view.
.top
{ min-height: 40px; background-color: darkgreen; }
.navbar { height:auto; }
.sticky {
min-height: 90px; background-color: lightblue;
width:50%; float:left;
}
.row_masthead
{ position: fixed; top: 0; width:100%; }
.other {
min-height: 90px; background-color: yellow;
width:50%; float:left;
}
.content {
background-color: lightgray; min-height: 600px;
margin-top:4%;
}
.bottom { background-color: darkgray; min-height: 200px; }
@media only screen and (max-width:768px) and (min-width:200px)
{
.sticky
{ width:100%; }
.other
{ width:100%; float:left; }
.content
{ margin-top:43%; }
}
<div class="top">
Top
</div>
<div class="middle">
<header class="navbar">
<div class="header-container">
<div id="row-masthead" class="row_masthead">
<div class="sticky">
Sticky
</div>
<div class="other">
Other
</div>
</div>
</div>
</header>
<main class="content">
<h2>
Content
</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
</main>
</div>
<div class="bottom">
<h2>Footer</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
</div>
Upvotes: 0
Reputation: 2452
From what I understand from position:sticky, you would have to redefine your HTML structure and move element with class .other out of the header. And also, uncomment your css code regarding the .navbar class.
Something like this:
.top {
min-height: 40px;
background-color: darkgreen;
}
.navbar {
position: sticky;
top: 0;
}
.sticky {
min-height: 50px;
background-color: lightblue;
position: sticky;
top: 0;
}
.other {
min-height: 90px;
background-color: yellow;
}
.content {
background-color: lightgray;
min-height: 600px;
}
.bottom {
background-color: darkgray;
min-height: 200px;
}
<div class="top">
Top
</div>
<div class="middle">
<header class="navbar">
<div class="header-container">
<div id="row-masthead">
<div class="sticky">
Sticky
</div>
</div>
</div>
</header>
<div class="other">
Other
</div>
<main class="content">
<h2>
Content
</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
</main>
</div>
<div class="bottom">
<h2>Footer</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus non vero quam suscipit veniam ex praesentium id sunt, voluptatibus ad ipsa asperiores enim quis omnis alias maxime saepe aut. Iste.
</p>
</div>
Upvotes: 0