如何使用纯CSS定义可变高度的粘性页脚?

49

需要注意的关键点是,页脚的高度不会固定,而会随其内容而变化。

当我说“粘性页脚”时,我使用的是通用定义,“即页脚永远不会高于视口底部,但如果有足够的内容,它将被隐藏,直到用户向下滚动足够的距离才能看到它。”

还要注意,我不需要支持旧版浏览器。如果CSS display: table和相关属性在此处有帮助,则可以使用。

3个回答

103

这里所有其他的解决方案都已经过时,要么使用JavaScript,要么使用 table 的技巧。

随着 CSS flex 模型 的出现,解决可变高度的粘性页脚问题变得非常容易:虽然大多数人更熟悉 Flexbox 用于水平方向上的布局,但它同样适用于垂直布局问题。你只需将垂直区域包裹在弹性容器中,并选择要扩展的哪些区域。它们将自动占用容器中所有可用的空间。

请注意标记和 CSS 是多么简单。没有任何 table 技巧等。

96%+ 的今天使用的浏览器 都支持弹性模式。

html, body {
  height: 100%;
  margin: 0; padding: 0;  /* to avoid scrollbars */
}

#wrapper {
  display: flex;  /* use the flex model */
  min-height: 100%;
  flex-direction: column;  /* learn more: http://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/ */
}

#header {
  background: yellow;
  height: 100px;  /* can be variable as well */
}

#body {
  flex: 1;
  border: 1px solid red;
}

#footer{
  background: lime;
}
<div id="wrapper">
  <div id="header">Title</div>
  <div id="body">Body</div>
  <div id="footer">
    Footer<br/>
    of<br/>
    variable<br/>
    height<br/>
  </div>
</div>


我还发现了一个问题,就是在Chrome上的Linux系统中,#wrapper的min-height: 100%而不是height: 100%。这会导致使用min-height时整个页面可以滚动,但只有body部分可以使用height来滚动。 - Milimetric
1
搜索了数小时后,找到了最佳解决方案。 - Riyad Khalifeh
很棒的解决方案!一开始我一直在想为什么要将flex=1分配给body - 直到我看到它指的是具有相同名称的div(id#body)。如果您将其重命名为#main或#content,可能会更清晰。顺便问一下,包装器div是否必要,或者display:flex是否可以直接分配给“真正的”body? - Ben
如果您不想从HTML设置100%的高度,请使用min-height: 100vh - ospider
为了让页眉和页脚始终保持在屏幕上,可以使用以下方法:将包装器高度设置为100vh,将页眉和页脚位置设置为sticky,并将正文的flex-direction设置为column。 - Byron Broughten

18
你可以完全使用纯CSS来实现这一点。 点击这个链接。
这个概念使用 display: table-cell 来组织你的页面部分,而不是正常的 display: blockHTML
<body class="Frame">
    <header class="Row"><h1>Catchy header</h1></header>
    <section class="Row Expand"><h2>Awesome content</h2></section>
    <footer class="Row"><h3>Sticky footer</h3></footer>
</body>

CSS

的翻译是:

CSS

.Frame {
    display: table;
    table-layout: fixed;
    height: 100%;
    width: 100%;
}
.Row {
    display: table-row;
    height: 1px;
}
.Row.Expand {
    height: auto;
}

虽然示例代码缺少一些东西,但是使用这种技术是可能的。 - Alan H.
你是正确的!我已经修改了我的代码来纠正这个问题,很高兴它能够工作! - cereallarceny
示例中没有 table-cell。您是否意味着 table-row?无论如何,现代方法是使用 CSS flexbox 模型 - Dan Dascalescu
你应该在类Frame中添加 table-layout: fixed;。如果没有这个属性,在IE浏览器中可能会出现宽度问题。无论最大宽度如何,内容都会溢出。 - Philipp Michael
@cereallarceny 这解决了问题。谢谢。我的朋友 ✌ - Dzenis H.

-1

你可以通过以下方式将页脚固定在视口底部:

position: fixed;
bottom: 0;

然而,这将使它即使有内容也会出现。

为了防止这种情况,您需要一些JavaScript:

(window.onscroll = function() {
    var foot = document.getElementById('footer');
    foot.style.position = "static";
    if( foot.offsetTop < document.documentElement.scrollTop + document.body.scrollTop + document.documentElement.offsetHeight - foot.offsetHeight)
        foot.style.position = "fixed";
})();

(...)();包装器使得onscroll函数在页面加载时被调用一次,因为这也是必要的)
(上述函数未经测试,但应该可以工作-如果不能,请告诉我,我会制作一个实际的测试页面)


(...)(); 只是一个自执行函数,不是吗? - Aaria Carter-Weir
是的 - 这基本上使函数在不需要滚动的情况下被调用一次,然后每次触发onscroll事件时再次调用。 - Niet the Dark Absol
那么这不正确吗?“(The (...)();包装器使得onscroll函数在页面加载时被调用一次,因为这也是必要的)” - Aaria Carter-Weir
我在重复自己,但做得很糟糕XD对于任何困惑感到抱歉。 - Niet the Dark Absol
我现在明白你的意思了。我稍微有点困惑,但那是一种相当不错的方法。 - Aaria Carter-Weir

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