当定义了'height'属性时,'position: sticky'无法正常工作。

27
我正在构建一个落地页,用户首先看到一个主要区域,下面是一个页脚。向下滚动会发现页脚是一个固定的标题,我打算使用纯CSS来实现这一点。为了获得主内容和页脚的全屏外观,我将height属性设置为两个不同的值:92%和8%(使用vh也不起作用)。无论我在CSS中指定的height是什么(不同的单位等),我的页脚div都无法固定。只要我删除height属性,它就能按预期工作。
这是我页面在删除height属性之前的截图:

With %, landing

如你所见,它并不会粘住。

With %, scrolled

在删除了height属性值之后,它确实粘住了。

Without %, scrolled

以下是相关代码:

html,
body {
  height: 100%;
  margin: 0;
}

#main {
  height: 92%;
}

#landing {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  text-align: center;
}

#landingContent {
  width: 20vw;
}

#footerNav {
  height: 8%;
  display: flex;
  align-items: center;
  position: -webkit-sticky;
  position: sticky;
  top: 0px;
}
<div id="main">
  <div id="landing">
    <div id="landingContent">
      <h1 class="logo">Logo</h1>
      <p id="landingParagraph">Lorem ipsum, paragraph content, etc etc.</p>
      <button>Button</button>
    </div>
  </div>
</div>
<div id="footerNav">
  <div id="footerNavContent">
    <h1 class="logo">Logo</h1>
  </div>
</div>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>

我读过使用overflow属性可能会有问题,尽管它目前不存在,我也没有听说过其他人对height有任何问题。当然,我可能是错的。
我已经在以下浏览器上进行了测试:
  • Firefox 61(夜间版)
  • Safari 53(技术预览版)
  • Chrome 65
注意 - 从#main中删除height属性可以使#footerNav保持粘性。

@xuhaib,我很感激设置高度以确保页面的统一性并确保页脚和主要内容填满整个页面。如果这样说有意义的话。从页脚中删除高度会产生一个有趣的结果:页脚会保持粘性一段时间,但是一旦我滚动到某个点后,它就会“解除粘性”。在Firefox中进行了测试。 - Lachlan
你有什么理由不能使用JavaScript吗? - Pixelomo
@Pixelomo 没有任何特殊原因,我只是更愿意保持整洁,我想。 - Lachlan
2
完全不同意,CSS3的“sticky position属性”就是为他试图解决的问题而设计的。Temani说得一点没错。 - JΛYDΞV
不仅仅是高度的问题,只要在sticky-top中添加一个宽度CSS规则,就会失去“粘性”,并且会产生相同的效果,因此这不是由于高度引起的。 - Lee
显示剩余2条评论
3个回答

48

问题出在这里是关于 height,但不是你想的那个 height。让我们先从sticky position的定义开始:

被粘性定位的元素是指其计算位置值为 sticky 的元素。它被视为相对定位,直到其所包含的块(或者容器内滚动的块)中的某个阈值(例如将 top 设置为非 auto 值)跨越其流程根时,在此时,它被视为“固定”,直到遇到其包含块的相反边缘。

重要的部分在于最后一句话,它解释了当元素到达其包含块的边缘时,粘性定位将会 结束,而在您的情况下,粘性元素的包含块是 body,而您设置了 body 的高度为 height: 100% 并且您的内容溢出了。

因此,当将主体的高度设置为 92%,页脚的高度设置为 8% 时,您已经使页脚处于其包含块的相反边缘。下面是一个示例,我添加了一个背景颜色到 body 中,这样你就可以清楚地看到:

html,
body {
  height: 100%;
  margin: 0;
}
html {
  background:white;
}
body {
  background:blue;
}

#main {
  height: 92%;
}
#landing {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  text-align: center;
}
#landingContent {
  width: 20vw;
}
#footerNav {
  height: 8%;
  display: flex;
  align-items: center;
  position: sticky;
  top: 0px;
  background:red;
  color:#fff;
}
<div id="main">
    <div id="landing">
        <div id="landingContent">
            <h1 class="logo">Logo</h1>
            <p id="landingParagraph">Lorem ipsum, paragraph content, etc etc.</p>
            <button>Button</button>
        </div>
    </div>
</div>
<div id="footerNav">
    <div id="footerNavContent">
        <h1 class="logo">Logo</h1>
    </div>
</div>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>

正如您所看到的,标志已经在页面底部,因此无法将其作为固定元素进行移动。同时,您的内容溢出。

如果您稍微减小主要内容的高度,您将能够看到一个小的粘性行为,当页脚到达蓝色部分(body)的底部时,该行为将结束。

html,
body {
  height: 100%;
  margin: 0;
}
html {
  background:white;
}
body {
  background:blue;
}

#main {
  height: 82%;
}
#landing {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  text-align: center;
}
#landingContent {
  width: 20vw;
}
#footerNav {
  height: 8%;
  display: flex;
  align-items: center;
  position: sticky;
  top: 0px;
  background:red;
  color:#fff;
}
<div id="main">
    <div id="landing">
        <div id="landingContent">
            <h1 class="logo">Logo</h1>
            <p id="landingParagraph">Lorem ipsum, paragraph content, etc etc.</p>
            <button>Button</button>
        </div>
    </div>
</div>
<div id="footerNav">
    <div id="footerNavContent">
        <h1 class="logo">Logo</h1>
    </div>
</div>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>

为了解决这个问题,您只需要避免将 height:100% 设置给 body。您可以使用 min-height 或保持其高度自动。您还可以考虑使用 vh 单位来设置主体和页脚:

html,
body {
  /*height: 100%;
    no needed
  */ 
  margin: 0;
}
html {
  background:white;
}
body {
  background:blue;
}

#main {
  height: 92vh;
}
#landing {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  text-align: center;
}
#landingContent {
  width: 20vw;
}
#footerNav {
  height: 8vh;
  display: flex;
  align-items: center;
  position: sticky;
  top: 0px;
  background:red;
  color:#fff;
}
<div id="main">
    <div id="landing">
        <div id="landingContent">
            <h1 class="logo">Logo</h1>
            <p id="landingParagraph">Lorem ipsum, paragraph content, etc etc.</p>
            <button>Button</button>
        </div>
    </div>
</div>
<div id="footerNav">
    <div id="footerNavContent">
        <h1 class="logo">Logo</h1>
    </div>
</div>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>

更多详细/示例相关问题:

为什么使用position:sticky的元素不会粘着在父元素底部?

什么是“滚动框”?

如果您为position:sticky指定bottom:0,则为什么它与规格中的内容不同?


4

我遇到了同样的问题,但是我需要在父容器中使用 height: 100%;。在我的情况下,我有一个固定的导航条,内容需要增长到它的全长,并且页脚应该始终可见于页面底部(但没有位置属性)。

我通过将 overflow: auto; 设置为该父容器来解决问题。现在该父容器仍然是100%高度,但其内部的粘性容器不受高度限制。


-2

对于使用 position: sticky 的支持似乎有些薄弱。您可以在此页面上进行检查:

https://caniuse.com/#search=position%3A%20sticky

如果您想要一个固定在底部的页脚,可以使用position: absolute,这是每个浏览器都支持的。我拿了你的代码并创建了一个迷你版本来说明我的绝对定位的观点。
<!doctype html>
    <html>
        <head>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .footerNav {
            background-color: red;
            position: absolute;
            bottom: 0;
            width: 100%;
            height: 100px;
        }
    </style>
</head>
<body>
    <div id="main">
        <div id="landing">
            <div id="landingContent">
                <h1 class="logo">Logo</h1>
                <p id="landingParagraph">Lorem ipsum, paragraph content, etc etc.</p>
                <button>Button</button>
            </div>
        </div>
    </div>
    <div class="footerNav">
        <div id="footerNavContent">
            <h1 class="logo">Logo</h1>
        </div>
    </div>
</body>

请注意,我将id =“footerNav”更改为class =“footerNav”。我个人更喜欢使用类来应用样式。但是如果您仍然喜欢使用id,则可以使用它们。
如果您希望登录页面出现,然后用户向下滚动一点以查看页脚,则可以使用height:100vh,并从页脚中删除绝对位置,因为它将被主内容div推到下面。例如:
<!doctype html>
    <html>
<head>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        #main {
            height: 100vh;
        }

        #footerNav {
            background-color: red;
            position: relative;
            bottom: 0;
            width: 100%;
            height: 100px;
        }
    </style>
</head>
<body>
    <div id="main">
        <div id="landing">
            <div id="landingContent">
                <h1 class="logo">Logo</h1>
                <p id="landingParagraph">Lorem ipsum, paragraph content, etc etc.</p>
                <button>Button</button>
            </div>
        </div>
    </div>
    <div id="footerNav">
        <div id="footerNavContent">
            <h1 class="logo">Logo</h1>
        </div>
    </div>
</body>

我希望我的答案能在某种程度上对你有所帮助。


谢谢您的回复,但我认为您并没有真正回答我的问题:'sticky'行为是有效的,但当应用两个div的高度属性时,它会出现问题。 - Lachlan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接