Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sticky Footer ! #17

Open
phenomLi opened this issue Mar 1, 2018 · 0 comments
Open

Sticky Footer ! #17

phenomLi opened this issue Mar 1, 2018 · 0 comments
Labels

Comments

@phenomLi
Copy link
Owner

phenomLi commented Mar 1, 2018

平时在做项目或者造轮子的时候,经常会有这样一个需求:

当页面内容超出屏幕,页脚模块会像正常页面一样,被推到内容下方,需要拖动滚动条才能看到。而当页面内容小于屏幕高度,页脚模块会固定在屏幕底部,就像是底边距为零的固定定位。



这种特殊的布局方式,就叫固定底部(Sticky Footer)

以前我曾经碰到过类似的需求,当时情况并不允许使用flex,于是一直束手无策,所以Sticky Footer算是我一直存在的CSS的一个知识漏洞,现在掌握了,赶紧记下来。



Sticky Footer的主要实现方式

Sticky Footer的实现方式有不少,我这里就只介绍最常用的3种。

很多文章介绍Sticky Footer实现方法的时候,喜欢将flex方法放在最后一位,然而我会放在第一位,原因是他们是按照CSS属性的常用程度来排序的,我这里会按照理解难易程度来排序。

下面所有的例子都会以这样的基础HTML来实现:

<body>
    <!-- 内容 -->
    <div class="content">
        Content
    </div>
    <!-- 页脚 -->
    <div class="footer">Footer</div>
</body>

壹:FLEX

flex方法应该是最简单方便的实现方式了,只要记住理解每个flex属性,就很容易实现一个Sticky Footer。一个简单地例子:

body {
    padding: 0;
    margin: 0;
    box-sizing: border-box;

    /**
    * 核心代码
    * flex-direction: column  => 使flex容器的主轴变成纵轴
    * justify-content: space-between => 让内容在主轴中向主轴两端靠
    */
    display: flex;
    flex-direction: column;
    justify-content: space-between;
}

非常简单,只需要在body里面设置样式,没什么可说的,理解了flex就很容易懂。


貳:绝对定位

绝对定位的实现方式比flex稍微复杂了一点点:

.content {
    /**
    * 核心代码
    * padding-bottom: 50px  => 因为footer为绝对定位,
    * 为了防止content覆盖了footer,所以要给content设置一个padding-bottom,
    * 而且padding-bottom的值要等于footer的高度
    */
    padding-bottom: 50px;

    padding: 40px 0 40px 0;
    background-color: aquamarine;
    text-align: center;
}

.footer {
    /**
    * 核心代码
    * 相对于flex方法,缺点就是footer一定要设置定高
    */
    position: absolute;
    left: 0;
    bottom: 0;
    height: 50px;

    width: 100%;
    text-align: center;
    background-color: #eee;
}

要理解这种方法的关键在于要理解Content的margin-bottom的作用。

为什么要设置跟Footer一样高度的margin-bottom?因为Footer是绝对定位,当Content达到某个高度时,必定会发生Content和Footer覆盖的现象(按照CSS叠层规则,是Footer覆盖Content),所以Content一定要腾出跟Footer一样高的空间用作给Footer覆盖,看图:

这种方法比第一种flex难理解一点,个人不推荐这种方法,因为绝对定位是一种不稳定的布局。


叁:负MARGIN(最hack的方法)

很巧妙的一种方法,也是很hack的一种方法。第一次看见的时候花了很久才弄明白,之后觉得十分惊艳。先看实现方式:

html, body {
    /**
    * 核心代码
    * 设置html和body的height为100%,让body的高度等于document的高度,
    * 主要目的是为了content的min-height能生效
    */
    height: 100%;

    padding: 0;
    margin: 0;
}


.content {
    /**
    * 核心代码
    * margin-bottom: -50px  => 关键1,用负的margin-bottom让footer层叠到content,而且数值也是要和footer设置的高度一致
    * padding-bottom: 50px => 跟绝对定位的方法一样,设置padding-botom消除层叠带来的影响
    * box-sizing: border-box => 设置border-box,规范盒子模型,消除padding对height的影响
    * min-height: 100%  => 关键2,让content占满body的空间
    */
    margin-bottom: -50px;
    padding-bottom: 50px;
    box-sizing: border-box;
    min-height: 100%;

    background-color: aquamarine;
    text-align: center;
}

.footer {
    /**
    * 核心代码
    * 这种方法也需要设置footer定高
    */
    height: 50px;

    text-align: center;
    background-color: #eee;
}

为什么这种方法可以?原理又是什么,我们来图解一下:

首先,若设置了Content的min-height为100%`,那么很显然Content会占满整个浏览器可视区域,所以Footer会被挤到下面,超出浏览器可视区域,浏览器会出现滚动条,这显然不好。

为什么要使用min-height而不是height,是因为要让当Content的子元素小于浏览器可视高度时,Content可填满浏览器可视区域,而当Content的子元素大于浏览器可视高度时,Content的高度能被子元素撑开。只有min-height有这样灵活的特性。


所以,我们可以利用负margin的特性,让Footer层叠在Content上面:

为了消除层叠带来的影响,可以在Content上设置padding-bottom

基本的原理就是这样子,主要还是利用了 负margin和min-height的特性。



总结

个人建议:

在平常开发中,如果不是十分在意兼容性,推荐使用flex,如果是比较在意兼容性的,最好使用负margin的方法。至于绝对定位的方法,最好不要优先考虑。

@phenomLi phenomLi added the CSS label Apr 7, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant