Twitter Bootstrap Affix - 如何固定在底部?

19
我已阅读文档,感觉我按照他们的示例做了一样的事情。但是当我尝试时,无法使其正常工作。我希望它能像文档中展示的那样工作。在滚动过标题后,它变为position: fixed,然后一旦接触页脚,它就变为position: absolute并固定在底部。

示例: http://jsfiddle.net/uvnGP/1/

JS

$("#account-overview-container").affix({
    offset: {
        top: $("header").outerHeight(true),
        bottom: $("footer").outerHeight(true)
    }
});

SASS

#account-overview-container {
    &.affix{
        top:10px;
        bottom:auto;
    }

    &.affix-top{
        //Do I need this?
    }

    &.affix-bottom{
        position:absolute;
        top:auto;
        bottom:140px;
    }
}

2
我也遇到了同样的问题。一旦它达到底部约束,我会看到一个闪烁,并注意到它在“affix”和“affix-bottom”之间快速来回切换。你解决了吗? - Ross Hambrick
3
不确定是否有解决办法。这个问题似乎完全被忽视了。 - Seed
如果您正在使用Bootstrap 3,那么有一个错误已经在主分支中修复,但尚未发布:https://github.com/twbs/bootstrap/commit/0fab6e7ea77ef838adaf78adf56c951ae6e16cdc#diff-3bd3c6fb42dd795d80a9306802e8c4da - michelpm
10个回答

15

虽然您的代码有所变化,但解决方案适用于可变的页眉和页脚高度,响应式宽度,并且可以更改为固定页眉。

这是链接:

http://jsfiddle.net/uvnGP/131/

问题在于,当附加内容到达底部时,会向容器 (#sidebar) 添加一个 top 和 bottom 的 CSS 样式。解决方法是将 bottom 样式重置为自动,这样只有 top 样式才会作用于您的容器。

以下是代码:

var headerHeight = $('header').outerHeight(true); // true value, adds margins to the total height
var footerHeight = $('footer').innerHeight();
$('#account-overview-container').affix({
    offset: {
        top: headerHeight,
        bottom: footerHeight
    }
}).on('affix.bs.affix', function () { // before affix
    $(this).css({
        /*'top': headerHeight,*/    // for fixed height
            'width': $(this).outerWidth()  // variable widths
    });
}).on('affix-bottom.bs.affix', function () { // before affix-bottom
    $(this).css('bottom', 'auto'); // THIS is what makes the jumping
});

这个方法很好用,你可以在CSS中使用auto !important来代替jquery处理程序中的affix-bottom:http://www.bootply.com/PWvY5VyzSy 这只是另一种选择。 - Carol Skelly
谢谢,我知道现在有“sticky”功能,但是我需要这个解决方案 ;) - Sagive

3
如果您不介意在标记中使用“data-”属性而不是SASS,则可以使用以下方法: http://www.bootply.com/l95thIfavC 您还会看到我删除了JS affix。 HTML
<div class="well well-small affix-top" data-spy="affix" data-offset-top="150" id="account-overview-container">

CSS

body{
    position:relative;
}
header,
footer{
    background: #ccc;
    padding:40px 0;
    text-align:center;
}
header{
    margin-bottom: 10px;
}

.affix-top {
    top: 155px;
    position:absolute;
}
.affix {
    bottom:140px;
}

Bootstrap 3更新内容

要使用affix-bottom,您需要设置页脚或固定元素下方的空间高度。这里是一个示例:http://www.bootply.com/l95thIfavC


16
如何使其在顶部和底部词缀位置都起作用呢?目前好像只能处理其中一个位置。每次我尝试两个位置一起使用时,当我接近底部时它会在这两个位置之间切换,导致屏幕不停闪烁。 - FiniteLooper
@michelpm,没有,我确实没做到 :( 由于其他人似乎也遇到了同样的问题,并且我没有看到任何可行的解决方案来真正解决这个问题,所以我放弃了底部词缀。 - FiniteLooper
1
@ChrisBarr,我已经成功让它工作了。CSS中的底部值和插件中的值不匹配。由于affix要么评估为pin,要么评估为unpin,因为两者都是true,所以每次滚动时它都会切换pin,导致你提到的疯狂闪烁。 - michelpm
@ChrisBarr 我在我的回答中详细说明了使其在您的应用程序上运行的步骤。如果您喜欢在浏览器上进行检查,您可以看一下quora.com的赞/踩按钮,它们运行得非常流畅。 - michelpm
1
哦,真的吗?那么,你能看一下我链接的fiddle演示,并指出其中的问题吗? - FiniteLooper

1
简短回答:如果您正在使用边框,请注意affix内的内容未使用box-sizing: border-box;
解释:在affix.js中使用的jQuery offset()函数,用于计算元素相对于文档的当前位置时,不考虑边框。
引用:

注意:jQuery不支持获取隐藏元素的偏移坐标,也不考虑设置在body元素上的边框、外边距或内边距。

因此,如果您的affix内部内容具有边框,并且其box-sizing设置为border-box,则高度将包括边框,但偏移量不会,导致affix使用的计算略有偏差。

那么如何解决边框的问题呢? - ahnbizcad
一个非常好的开始,但没有给出任何修复的提示。这是最糟糕的逗我玩的方式。 - Techdragon

1
Paco Rivera的解决方案有效!但并非他预期的那样。真正消除闪烁(跳跃)问题的是这一行代码:
.on('affix.bs.affix', function () { // before affix
    $(this).css({
        'width': $(this).outerWidth()  // variable widths
    });
})

奇怪的是,你甚至不需要设置CSS宽度。只是读取这个参数已经有所帮助了。我将代码简化为以下片段,它仍然有效:
.on('affix.bs.affix', function () { // before affix
    $(this).width();
});

在 Bootstrap Affix 插件的下一个版本发布之前,我将保持这样的状态,希望他们能够一劳永逸地解决这个问题。


1
我已经成功在我的应用程序中实现了它,关键是使底部样式与传递给固定调用的底部一致。如果您的页脚具有固定高度,并且最近的定位父级是body,则需要为两者传递相同的值。这对于Bootstrap 2.3文档来说足够好,如此处此处所示。

--

假设您没有固定高度的页脚:

步骤1:最近的定位父级(offset parent)

首先,我们使用绝对定位将其固定在底部,但由于您最近的定位父级将是body(包括页脚),因此您没有底部的固定值。为了解决这个问题,我们必须创建一个新的定位父级,它包含除页脚以外的所有内容(重要提示:标题可能也在外面)。将position: relative;设置为顶部的.container或其祖先之一(重要提示:页脚必须在此元素之后)。

步骤2:页脚高度

现在,您的底部相对于其容器而不是body,但是affix的底部值(用于知道何时将affix固定在底部)仍然相对于body的末尾,因此您必须传递一个函数来计算容器后面元素的高度,如果只有页脚,则足以使用此代码:$('footer').outerHeight(true)

步骤3:故障排除

现在,您已经全部正确了,但是仍有三件事可能导致粘贴位置不正确并出现疯狂闪烁:

  1. 您没有考虑到除页脚以外的其他视觉元素,比如第二个页脚或者不总是显示的有用的 rails-footnotes gem

  2. 浏览器扩展会附加元素到DOM中,如果它们被隐藏或者不在流中,那么就不应该计算它们的高度。解决方法是只计算您的应用程序已知的元素,但是扩展可能会破坏您的应用程序。您可以通过使用没有安装扩展的浏览器或配置来测试扩展是否会引起问题,或者通过进入"隐私模式"(Chromium的无痕浏览 (Ctrl+Shift+n),Firefox的隐私浏览 (Ctrl+Shift+p))来检查。

  3. Javascript库也会附加元素到DOM中,因此也不应计算其高度。

为了解决这些问题,您可以尝试使用整个单词(带Underscore.js的CoffeeScript):

_($('footer').nextAll(':visible').addBack())
  .filter((el) -> el.offsetParent?)
  .reduce(((memo, el) -> memo + $(el).outerHeight(true)), 0)

同样的事情,使用Javascript和jQuery.fn.each:

var sum = 0
$('footer').nextAll(':visible').each(function() {
  this.offsetParent != null && sum += $(this).outerHeight(true)
}
return sum

或者你只考虑你已知的元素(我更喜欢这种方式,另一种是我为了挑战而编写的):

$('footer').outerHeight(true) + ($('#footnotes_debug').outerHeight(true) || 0)

0

我通过一些试错的过程完成了这项工作,但这是对我有效的方法。

JS

$(document).ready(function() {
var SidebarTop = $('#your-affix').offset().top - x; //adjust x to meet your required positioning
    SidebarBottom = $('.site-footer').outerHeight() + x;

    $('#your-affix').affix({
        offset: {
        top: SidebarTop,
        bottom: SidebarBottom
        }
    });
});

CSS

#your-affix.affix {
    top: boo px; //the px from top of the window where you want your sidebar
                 //be when you scroll
    width: foo px; //your sidebar width
  }
#your-affix.affix-bottom {
    position: absolute;
    width: foo px; //your sidebar width
}

在这段代码之后,当侧边栏到达页脚时会变成“未固定”状态。并且当它到达底部偏移选项时,停止跳转到站点顶部。

0

如果您在小提琴上稍微增加窗口大小,它似乎可以按预期工作。考虑到在附加组件中断的尺寸下网站将无法使用,您应该忽略它,或者更改布局以适应较小的空间而不是试图解决问题。文档中的Bootstrap附加组件不用于较小的分辨率,我建议您也这样做。


0

.affix-top.affix-bottom 设置 position: absolute,为 .affix 设置 position: fixed

根据官方 文档


0
只需按照下面所示的方式替换 bootstrap 中的词缀代码片段。

代码如下 -

this.$element.offset({ top: document.body.offsetHeight - offsetBottom - this.$element.height() }) 

并且这将替换它

this.$element.offset({ top: scrollHeight - offsetBottom - this.$element.height() })

干杯。


0

一种可能的解决方案是通过设置 bottom: null 来完全忽略 affix-bottom 的情况,如下所示:

$("#my-selector").affix({
    offset: {
        top: $("#some-thing").outerHeight(true),
        bottom: null
    }
});

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