position:sticky 不工作
position:sticky is not working
我有这个 HTML 代码:
<div class="header">
<div class="desc">Description</div>
<div class="logo"><img src=""/></div>
<div class="navbar"></div></div>
.header 的高度为 150px。 .navbar 的高度为 20px。当用户滚动时,我希望 .navbar 停留在顶部。所以我去了 CSS 并设置了 position:sticky 和 top:0。但这没有用。我最初以为 firefox 不支持 position:sticky,但事实并非如此,因为我能够看到它的工作演示。我用谷歌搜索但没有找到任何帮助。任何人都知道为什么这不起作用?
您的 HTML 代码原样
<div class="header">
<div class="desc">Description</div>
<div class="logo"><img src=""/></div>
<div class="navbar"></div></div>
并为导航栏写CSS class
.header {
height: 150px;
background-color: #d1d1d1;
}
.navbar {
background: #999;
border-bottom: 1px solid #333;
border-top: 1px solid #333;
color: #FFF;
margin: 0;
padding: 2px 0 0 12px;
position: -webkit-sticky;
position: sticky;
top: -1px;
}
希望这会有所帮助
如果将导航栏移到 header 之外,它会正常工作。见下文。原因根据MDN:
The element is positioned according to the normal flow of the document, and then offset relative to its flow root and containing block based on the values of top, right, bottom, and left.
对于包含块:
The containing block is the ancestor to which the element is relatively positioned
所以,如果我没有误解的话,导航栏在 header 滚动到视口外后立即位于偏移量 0 处(这显然意味着您再也看不到它了) ).
.navbar {
background: hotpink;
width: 100%;
height: 50px;
position: -webkit-sticky;
position: sticky;
top: 0;
}
.header {
height: 150px;
background: grey;
}
body {
height: 800px;
position: relative;
}
<div class="header">
<div class="desc">Description</div>
<div class="logo"><img src=""/></div>
</div>
<div class="navbar"></div>
不知何故,您的代码仅在 .navbar
元素不在另一个容器(如 header 中)时才有效。我把它移出来然后它工作正常。 I created a codepen snippet for that, check it out
<header>
<div class="logo">Logo</div>
<div class="description"><div>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo, veritatis.</div></div>
</header>
<div class="navbar">
<ul>
<li><a href="#">navitem1</a></li>
<li><a href="#">navitem2</a></li>
<li><a href="#">navitem3</a></li>
<li><a href="#">navitem4</a></li>
</ul>
</div>
现在 position:sticky
得到了很好的支持,正如您在 canIuse 上看到的那样。当然IE目前还不支持,但是新的Edge版本会带来全面的支持!我发现了一些关于这个主题的有趣文章:
- 工作演示(chrome,firefox)https://codepen.io/simevidas/pen/JbdJRZ
- 参考文献:http://caniuse.com/#search=sticky
- MDN 上的粘性文章,包括最新的浏览器支持tablehttps://developer.mozilla.org/en-US/docs/Web/CSS/position#Sticky_positioning
不过horizon上有好消息传来。我认为下次会提供更好的浏览器支持。
对于遇到此问题的任何其他人,位置粘性对我不起作用,因为 body
元素设置了 overflow-x: hidden;
。
在 header 内的 nav 之后添加更多内容提供了粘性行为,但只是暂时的 - 如果用户向下滚动太多, nav 会随着 header 一起消失,因为它不能跳出 header 的底部边框。
因此,使用纯 CSS 的唯一解决方案是将 nav 放在即使在用户滚动到页面底部(直接在 正文 内或某种跨越页面底部或至少跨越 页脚) 的容器内。
如果这个解决方案不可行,另一种方法是使用JavaScript。在转换到CSS之前,我使用了下面的代码(很久以前在某处找到类似jQuery的解决方案,不记得在哪里,所以功劳归于匿名作者;Vanilla JS可以很容易地从这个):
$(document).ready(function () {
var sticky_navigation_offset_top = $('nav').offset().top;
var sticky_navigation = function () {
var scroll_top = $(window).scrollTop();
if (scroll_top > sticky_navigation_offset_top) {
$('nav').css({
'position': 'fixed',
'top': 0,
'left': 0,
'right': 0,
'margin-left': 'auto',
'margin-right': 'auto'
});
} else {
$('nav').css({
'position': 'relative'
});
}
};
sticky_navigation();
$(window).scroll(function () {
sticky_navigation();
});
});
为什么 position: sticky;
可能不起作用的两个最常见的罪魁祸首是:
- 您还没有定义
top: 0;
、bottom: 0;
、left: 0
或类似的东西
- 您的粘性元素的父级之一已将溢出(x 或 y)设置为
hidden
、scroll
或 auto
。
对我来说这是第一个。
从上面的答案和一些信息进行扩展,使其与 flexbox parent 和 overflow 而非 visible 一起工作(下面的示例假设您使用 vertical - sticky 并将 top 或 bottom 设置为特定值,并将 position 设置为 sticky):
最常见的情况是你有一个祖先元素(不仅仅是直接父元素)溢出 属性 设置为可见以外的东西,因此没有 space 留在附近。
要快速查明是否属于这种情况,您可以 运行 浏览器控制台中的此脚本 (请确保将 .your-sticky-element class 更改为元素的选择器):
var stickyElement = document.querySelector('.your-sticky-element');
var parent = stickyElement.parentElement;
while (parent) {
var hasOverflow = getComputedStyle(parent).overflow;
if(hasOverflow != 'visible') {
console.log(hasOverflow, parent);
}
parent = parent.parentElement;
}
解决方案:
a) 如果你发现有溢出集,你可以去掉它,这应该可以解决
b) 如果必须保留溢出设置,则必须使父元素的高度高于粘性元素的高度。如果父元素没有高度或粘性元素填满了所有高度,则意味着当页面滚动时根本没有地方可以粘在里面。它不需要一个明确的高度(垂直),但你可以检查你的粘性元素是否有额外的 space 留在它自己之后。
父级不高于粘性元素留下额外space。这种特殊情况可能是由不同的情况引起的,但解决方法与上述相同,请参阅1.b
如果你的粘性元素的父元素是一个 flexbox(align-items 的默认值为 normal)并且如果粘性元素本身没有合适的 align-self 设置,滚动时将没有 space 留给粘性元素保持(例如,如果它是 align-self: stretch 或 auto [默认值])。这是因为子元素被拉伸以填满父元素的高度。
解决方案:
在这种情况下,为粘性元素设置 align-self: flex-start 可以解决问题,因为元素将站在起点,在其后留下额外的 space。
指南:有弹性盒和没有弹性盒的情况要复杂得多,但一般的经验法则是你的粘性元素需要 space滚动时父对象是粘性的。
遇到一些不明显的水平粘滞行为:如果宽度为 100%,则粘滞不起作用。宽度应小于容器大小。
我的粘性 header 只能部分工作...滚动几次后它会消失,但最初会工作
看来问题是我将 parent 设置为高度 100%。
我实际上并不需要这个,因为 body 一个就足够了,所以我删除了它,一切都很好..永远坚持
虽然现在这会阻止我的页脚在他们没有内容时停留在底部!
我有这个 HTML 代码:
<div class="header">
<div class="desc">Description</div>
<div class="logo"><img src=""/></div>
<div class="navbar"></div></div>
.header 的高度为 150px。 .navbar 的高度为 20px。当用户滚动时,我希望 .navbar 停留在顶部。所以我去了 CSS 并设置了 position:sticky 和 top:0。但这没有用。我最初以为 firefox 不支持 position:sticky,但事实并非如此,因为我能够看到它的工作演示。我用谷歌搜索但没有找到任何帮助。任何人都知道为什么这不起作用?
您的 HTML 代码原样
<div class="header">
<div class="desc">Description</div>
<div class="logo"><img src=""/></div>
<div class="navbar"></div></div>
并为导航栏写CSS class
.header {
height: 150px;
background-color: #d1d1d1;
}
.navbar {
background: #999;
border-bottom: 1px solid #333;
border-top: 1px solid #333;
color: #FFF;
margin: 0;
padding: 2px 0 0 12px;
position: -webkit-sticky;
position: sticky;
top: -1px;
}
希望这会有所帮助
如果将导航栏移到 header 之外,它会正常工作。见下文。原因根据MDN:
The element is positioned according to the normal flow of the document, and then offset relative to its flow root and containing block based on the values of top, right, bottom, and left.
对于包含块:
The containing block is the ancestor to which the element is relatively positioned
所以,如果我没有误解的话,导航栏在 header 滚动到视口外后立即位于偏移量 0 处(这显然意味着您再也看不到它了) ).
.navbar {
background: hotpink;
width: 100%;
height: 50px;
position: -webkit-sticky;
position: sticky;
top: 0;
}
.header {
height: 150px;
background: grey;
}
body {
height: 800px;
position: relative;
}
<div class="header">
<div class="desc">Description</div>
<div class="logo"><img src=""/></div>
</div>
<div class="navbar"></div>
不知何故,您的代码仅在 .navbar
元素不在另一个容器(如 header 中)时才有效。我把它移出来然后它工作正常。 I created a codepen snippet for that, check it out
<header>
<div class="logo">Logo</div>
<div class="description"><div>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo, veritatis.</div></div>
</header>
<div class="navbar">
<ul>
<li><a href="#">navitem1</a></li>
<li><a href="#">navitem2</a></li>
<li><a href="#">navitem3</a></li>
<li><a href="#">navitem4</a></li>
</ul>
</div>
现在 position:sticky
得到了很好的支持,正如您在 canIuse 上看到的那样。当然IE目前还不支持,但是新的Edge版本会带来全面的支持!我发现了一些关于这个主题的有趣文章:
- 工作演示(chrome,firefox)https://codepen.io/simevidas/pen/JbdJRZ
- 参考文献:http://caniuse.com/#search=sticky
- MDN 上的粘性文章,包括最新的浏览器支持tablehttps://developer.mozilla.org/en-US/docs/Web/CSS/position#Sticky_positioning
不过horizon上有好消息传来。我认为下次会提供更好的浏览器支持。
对于遇到此问题的任何其他人,位置粘性对我不起作用,因为 body
元素设置了 overflow-x: hidden;
。
在 header 内的 nav 之后添加更多内容提供了粘性行为,但只是暂时的 - 如果用户向下滚动太多, nav 会随着 header 一起消失,因为它不能跳出 header 的底部边框。
因此,使用纯 CSS 的唯一解决方案是将 nav 放在即使在用户滚动到页面底部(直接在 正文 内或某种跨越页面底部或至少跨越 页脚) 的容器内。
如果这个解决方案不可行,另一种方法是使用JavaScript。在转换到CSS之前,我使用了下面的代码(很久以前在某处找到类似jQuery的解决方案,不记得在哪里,所以功劳归于匿名作者;Vanilla JS可以很容易地从这个):
$(document).ready(function () {
var sticky_navigation_offset_top = $('nav').offset().top;
var sticky_navigation = function () {
var scroll_top = $(window).scrollTop();
if (scroll_top > sticky_navigation_offset_top) {
$('nav').css({
'position': 'fixed',
'top': 0,
'left': 0,
'right': 0,
'margin-left': 'auto',
'margin-right': 'auto'
});
} else {
$('nav').css({
'position': 'relative'
});
}
};
sticky_navigation();
$(window).scroll(function () {
sticky_navigation();
});
});
为什么 position: sticky;
可能不起作用的两个最常见的罪魁祸首是:
- 您还没有定义
top: 0;
、bottom: 0;
、left: 0
或类似的东西 - 您的粘性元素的父级之一已将溢出(x 或 y)设置为
hidden
、scroll
或auto
。
对我来说这是第一个。
从上面的答案和一些信息进行扩展,使其与 flexbox parent 和 overflow 而非 visible 一起工作(下面的示例假设您使用 vertical - sticky 并将 top 或 bottom 设置为特定值,并将 position 设置为 sticky):
最常见的情况是你有一个祖先元素(不仅仅是直接父元素)溢出 属性 设置为可见以外的东西,因此没有 space 留在附近。 要快速查明是否属于这种情况,您可以 运行 浏览器控制台中的此脚本 (请确保将 .your-sticky-element class 更改为元素的选择器):
var stickyElement = document.querySelector('.your-sticky-element'); var parent = stickyElement.parentElement; while (parent) { var hasOverflow = getComputedStyle(parent).overflow; if(hasOverflow != 'visible') { console.log(hasOverflow, parent); } parent = parent.parentElement; }
解决方案:
a) 如果你发现有溢出集,你可以去掉它,这应该可以解决
b) 如果必须保留溢出设置,则必须使父元素的高度高于粘性元素的高度。如果父元素没有高度或粘性元素填满了所有高度,则意味着当页面滚动时根本没有地方可以粘在里面。它不需要一个明确的高度(垂直),但你可以检查你的粘性元素是否有额外的 space 留在它自己之后。
父级不高于粘性元素留下额外space。这种特殊情况可能是由不同的情况引起的,但解决方法与上述相同,请参阅1.b
如果你的粘性元素的父元素是一个 flexbox(align-items 的默认值为 normal)并且如果粘性元素本身没有合适的 align-self 设置,滚动时将没有 space 留给粘性元素保持(例如,如果它是 align-self: stretch 或 auto [默认值])。这是因为子元素被拉伸以填满父元素的高度。
解决方案:
在这种情况下,为粘性元素设置 align-self: flex-start 可以解决问题,因为元素将站在起点,在其后留下额外的 space。
指南:有弹性盒和没有弹性盒的情况要复杂得多,但一般的经验法则是你的粘性元素需要 space滚动时父对象是粘性的。
遇到一些不明显的水平粘滞行为:如果宽度为 100%,则粘滞不起作用。宽度应小于容器大小。
我的粘性 header 只能部分工作...滚动几次后它会消失,但最初会工作
看来问题是我将 parent 设置为高度 100%。
我实际上并不需要这个,因为 body 一个就足够了,所以我删除了它,一切都很好..永远坚持
虽然现在这会阻止我的页脚在他们没有内容时停留在底部!