WebDevBooster
WebDevBooster

Reputation: 14954

How to make only one child element sticky without affecting the rest?

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

Answers (3)

Temani Afif
Temani Afif

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

Sandeep
Sandeep

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

Pedro Figueiredo
Pedro Figueiredo

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

Related Questions