【问题标题】:How to make only one child element sticky without affecting the rest?如何在不影响其余子元素的情况下仅使一个子元素具有粘性?
【发布时间】:2019-08-21 11:37:51
【问题描述】:

下面代码中的相关元素是.top.sticky.other

.sticky.other 位于 .navbar 容器内。

现在,让整个 .navbar 变得粘滞很容易。将position: sticky; top: 0; 添加到该元素即可。这就是我想要的一般行为。

我面临的挑战是:

如何.sticky 元素设为粘性,以便其下方的所有内容始终滚动?

如果您运行当前代码,您可以看到 .sticky 元素仅保持粘性,直到黄色的 .other 元素在其下方滚动。之后,.sticky 元素不再具有粘性。

这就是我要解决的问题。如何让蓝色的.sticky 元素始终保持粘性? (在您向上滚动到绿色 .top 部分被隐藏的点之后)

理想情况下寻找纯 CSS 解决方案。如果这不可能,JavaScript/jQuery 解决方案是可以接受的,但在向上或向下两个方向滚动时必须正常工作。

更新:

我知道从标题中取出黄色的.other 元素可以解决问题。但问题是黄色的.other 元素需要成为标题的一部分。 .sticky.other都需要在大屏幕上并排显示,在手机屏幕上并排显示。这就是为什么它们目前是另一个容器中的子元素。因此,在这种情况下,将黄色元素移出标题并不是我真正可以使用的选项。

.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>

【问题讨论】:

  • 你试过postion:fixed吗?
  • @Soothran 我不会有 position: fixedsticky 行为,对吗?我正在寻找您使用position: sticky 获得的行为。

标签: javascript jquery css sticky


【解决方案1】:

一种解决方案是考虑在粘性元素的容器中使用display:contents,使它们看起来不存在,而你将拥有你想要的:

.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>

另一个hacky 解决方案是使用高度和负边距的组合为粘性元素创建所需的空间,如下所示。缺点是您需要找到正确的值以避免在底部创建大量空间并为粘性提供所需的空间。

.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>

使用一些 JS 可以动态且正确地计算值:

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>

【讨论】:

  • 太棒了!喜欢你的解决方案。我想我们还得等一下,直到旧版浏览器消失,这样display: contents 才能放心使用。
  • 你能解释一下JS解决方案背后的想法吗?
  • @WebDevBooster 我会喜欢这个答案来记住 100K 动作 ;) ... 对于 JS,这个想法是计算中间部分内缺失的内容。如果您希望元素粘在中间部分,那么缺少的高度将为height of the middle part - height of the actual stikcy container,而实际的粘性容器是导航栏。您可以使用不同的公式找到高度。你只需要找到你想要得到的缺失高度在哪里。
【解决方案2】:

根据我对 position:sticky 的理解,您必须重新定义 HTML 结构并将带有 .other 类的元素移出标题。此外,取消注释您关于 .navbar 类的 CSS 代码。

类似这样的:

.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>

【讨论】:

  • 我知道这是一个选择。问题是黄色的.other 元素需要成为标题的一部分。 .sticky.other需要在大屏幕上并排显示,在手机屏幕上并排显示。这就是为什么它们目前是另一个容器中的子元素。
  • 如果您希望它们在较小的屏幕中并排放置,您可以使用一些 css 网格和 css 变量来产生这种效果。看看:codepen.io/pedro-figueiredo/pen/vYByebw,好像只要做一些小改动就可以达到你想要的效果:)
  • 我最初的 HTML 结构的原因是在大屏幕上将sticky 属性添加到整个标题中,这样蓝色和黄色元素就像一个粘性元素一样。有没有办法通过您的方法实现相同的行为?
  • 当然,如果我明白你想要什么,所需的行为已在 codepen 中更新。 codepen.io/pedro-figueiredo/pen/vYByebw 这样一来,html 结构并没有改变。
  • 现在,有了你的最后一篇文章,我们又回到了起点。这就是我面临的问题。移动设备上的黄色部分需要表现得像下面的灰色内容部分,但在桌面上,黄色和蓝色需要粘在一起。这就是问题所在!
【解决方案3】:

检查以下代码,它可能对您有所帮助。将其检查为全页或全屏模式,在桌面模式下为粘性和其他部分并排,在移动视图中其他 div 在粘性 div 下。它需要用于移动视图的媒体查询。

.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>

【讨论】:

  • 绿色的.top 部分在哪里?你为什么不直接运行你的代码来看看它的问题呢?我的意思是,这就是“运行代码 sn-p”功能的用途!我明确指出.top 是相关部分之一。你不能只是隐藏它。请重新阅读我的问题几次以了解问题所在。
猜你喜欢
  • 2020-09-04
  • 1970-01-01
  • 1970-01-01
  • 2020-12-17
  • 2016-02-25
  • 2013-02-21
  • 1970-01-01
  • 1970-01-01
  • 2018-08-18
相关资源
最近更新 更多