"position: sticky;" 属性 是如何工作的?
How does the "position: sticky;" property work?
我想让导航栏在用户滚动页面后固定在视口的顶部,但它不起作用,我也不知道为什么。如果你能帮忙,这是我的 HTML 和 CSS 代码:
.container {
min-height: 300vh;
}
.nav-selections {
text-transform: uppercase;
letter-spacing: 5px;
font: 18px "lato",sans-serif;
display: inline-block;
text-decoration: none;
color: white;
padding: 18px;
float: right;
margin-left: 50px;
transition: 1.5s;
}
.nav-selections:hover{
transition: 1.5s;
color: black;
}
ul {
background-color: #B79b58;
overflow: auto;
}
li {
list-style-type: none;
}
<main class="container">
<nav style="position: sticky; position: -webkit-sticky;">
<ul align="left">
<li><a href="#/contact" class="nav-selections" style="margin-right:35px;">Contact</a></li>
<li><a href="#/about" class="nav-selections">About</a></li>
<li><a href="#/products" class="nav-selections">Products</a></li>
<li><a href="#" class="nav-selections">Home</a></li>
</ul>
</nav>
</main>
Sticky positioning is a hybrid of relative and fixed positioning. The element is treated as relative positioned until it crosses a specified threshold, at which point it is treated as fixed positioned.
...
You must specify a threshold with at least one of top
, right
, bottom
, or left
for sticky positioning to behave as expected. Otherwise, it will be indistinguishable from relative positioning.
[source: MDN]
因此在您的示例中,您必须使用 top
属性.
来定义它最后应该粘贴的位置
html, body {
height: 200%;
}
nav {
position: sticky;
position: -webkit-sticky;
top: 0; /* required */
}
.nav-selections {
text-transform: uppercase;
letter-spacing: 5px;
font: 18px "lato", sans-serif;
display: inline-block;
text-decoration: none;
color: white;
padding: 18px;
float: right;
margin-left: 50px;
transition: 1.5s;
}
.nav-selections:hover {
transition: 1.5s;
color: black;
}
ul {
background-color: #B79b58;
overflow: auto;
}
li {
list-style-type: none;
}
<nav>
<ul align="left">
<li><a href="#/contact" class="nav-selections" style="margin-right:35px;">Contact</a></li>
<li><a href="#/about" class="nav-selections">About</a></li>
<li><a href="#/products" class="nav-selections">Products</a></li>
<li><a href="#" class="nav-selections">Home</a></li>
</ul>
</nav>
来自我的评论:
position:sticky
needs a coordonate to tel where to stick
nav {
position: sticky;
top: 0;
}
.nav-selections {
text-transform: uppercase;
letter-spacing: 5px;
font: 18px "lato", sans-serif;
display: inline-block;
text-decoration: none;
color: white;
padding: 18px;
float: right;
margin-left: 50px;
transition: 1.5s;
}
.nav-selections:hover {
transition: 1.5s;
color: black;
}
ul {
background-color: #B79b58;
overflow: auto;
}
li {
list-style-type: none;
}
body {
height: 200vh;
}
<nav>
<ul align="left">
<li><a href="#/contact" class="nav-selections" style="margin-right:35px;">Contact</a></li>
<li><a href="#/about" class="nav-selections">About</a></li>
<li><a href="#/products" class="nav-selections">Products</a></li>
<li><a href="#" class="nav-selections">Home</a></li>
</ul>
</nav>
除了 FF 和 Chrome 之外,还有其他浏览器可以使用的 polyfill。这是一个实验性的规则,可以通过浏览器随时执行或不执行。 Chrome 几年前添加,然后又放弃了,好像又回来了……但是多久了?
最接近的是 position:relative + 滚动到达粘点时更新坐标,如果你想把它变成 javascript 脚本
检查祖先元素是否设置了溢出(例如overflow:hidden
);尝试切换它。您可能需要检查 DOM 树,它比您预期的要高 =).
这可能会影响后代元素上的 position:sticky
。
我有同样的问题,我找到了答案here。
如果您的元素没有按预期粘附,首先要检查的是应用到容器的规则。
具体来说,查找在元素的任何父元素上设置的任何溢出 属性。 您不能在 position: sticky
元素的父元素上使用:overflow: hidden
、overflow: scroll
或 overflow: auto
。
我遇到的更多事情:
当您的粘性元素是组件时(angular 等)
如果 'sticky' 元素本身是具有自定义元素选择器的组件,例如名为 <app-menu-bar>
的 angular 组件,您将需要添加跟随组件的 css:
:host { display: block; } // or use flexbox
或
app-menu-bar { display: block; } // (in the containing component's css)
Safari on iOS in particular seems to require `display:block` even on the root element `app-root` of an angular application or it won't stick.
如果您正在创建组件并在组件内部定义 css(阴影 DOM/封装样式),请确保应用 position: sticky
到 'outer' 选择器(例如,devtools 中的 app-menu-bar
应该显示粘性位置)而不是 div
在 组件中的顶级。使用 Angular,这可以通过 css 中的 :host
选择器为您的组件实现。
:host
{
position: sticky;
display: block; // this is the same as shown above
top: 0;
background: red;
}
其他
如果粘性元素后面的元素有纯色背景,您必须添加以下内容以阻止它在下方滑动:
.sticky-element { z-index: 100; }
.parent-of-sticky-element { position: relative; }
如果使用 top
,您的粘性元素必须 在您的内容之前 ,如果使用 在它之后 bottom
.
在包装元素上使用 overflow: hidden
时会出现一些复杂情况——通常它会杀死内部的粘性元素。 Better explained in this question
移动浏览器可能会在屏幕键盘可见时禁用 sticky/fixed 定位的项目。我不确定确切的规则(有人知道吗)但是当键盘可见时,您正在查看 window 中的某种 'window' 并且您不会轻易能够让东西粘在屏幕的实际可见顶部。
确保你有:
position: sticky;
而不是
display: sticky;
其他可用性问题
- 如果您的设计要求将内容粘贴到移动设备的屏幕底部,请务必谨慎。例如,在 iPhone X 上,它们会显示一条窄线来指示滑动区域(返回主页)- 并且该区域内的元素不可点击。因此,如果您坚持使用某些东西,请务必在 iPhone X 上测试用户是否可以激活它。如果人们不能点击,那么大的 'Buy Now' 按钮是没有用的!
- 如果您在 Facebook 上投放广告,网页将显示在 Facebook 移动应用程序的 'webview' 控件中。尤其是在显示视频时(您的内容仅从屏幕的下半部分开始)- 他们通常会通过将您的页面放在一个可滚动的视口中来完全弄乱粘性元素,这实际上允许您的粘性元素从页面顶部消失。请务必在实际广告的上下文中进行测试,而不仅仅是在 phone 的浏览器甚至 Facebook 的浏览器中进行测试,它们的行为可能都不同。
这是 MarsAndBack 和 Miftah Mizwar 回答的延续。
他们的回答是正确的。但是,很难确定问题的祖先。
为了使这个变得非常简单,只需在您的浏览器控制台中 运行 这个 jQuery 脚本,它会告诉您每个祖先的溢出值 属性。
$('.your-sticky-element').parents().filter(function() {
console.log($(this));
console.log($(this).css('overflow'));
return $(this).css('overflow') === 'hidden';
});
如果一个祖先没有 overflow: visible
改变它的 CSS 以便它有!
此外,如其他地方所述,请确保您的粘性元素在 CSS:
.your-sticky-element {
position: sticky;
top: 0;
}
这里有两个答案:
从 body
标签中删除 overflow
属性
将 height: 100%
设置为 body
以解决 overflow-y: auto
的问题
min-height: 100%
not-working instead of height: 100%
有趣的时刻对我来说并不明显:至少在 Chrome 70 position: sticky
如果您使用 DevTools 设置它则不会应用。
似乎要粘贴的导航栏不应该在任何 div 或包含其他内容的部分中。 None 的解决方案对我有用,直到我将导航栏从导航栏与另一个顶部栏共享的 div 中取出。我以前用一个公共 div 包裹了顶部栏和导航栏。
确实需要删除 overflow
或将其设置为 initial
才能使 position: sticky
作用于子元素。我在我的 Angular 应用程序中使用了 Material 设计,发现 一些 Material 组件更改了 overflow
值。我的方案的修复是
mat-sidenav-container, mat-sidenav-content {
overflow: initial;
}
我不得不使用以下 CSS 来让它工作:
.parent {
display: flex;
justify-content: space-around;
align-items: flex-start;
overflow: visible;
}
.sticky {
position: sticky;
position: -webkit-sticky;
top: 0;
}
如果上面的方法不起作用那么...
遍历所有祖先并确保这些元素中的 none 个具有 overflow: hidden
。您必须将其更改为 overflow: visible
如果 danday74 的修复不起作用,请检查 parent 元素是否有高度。
就我而言,我有两个孩子,一个向左漂浮,一个向右漂浮。
我想让右边的浮动变得粘稠,但不得不在 parent 的末尾添加一个 <div style="clear: both;"></div>
来给它高度。
我知道这是旧的post。但是如果有像我这样的人最近才开始弄乱 position: sticky 这可能会有用。
在我的例子中,我使用 position: sticky 作为网格项。它不工作,问题是 overflow-x: hidden 在 html
元素上。一旦我删除 属性 它就可以正常工作。将 overflow-x: 隐藏在 body
元素上似乎可行,但还不知道为什么。
我相信 this article 说了很多 sticky
的工作原理
How CSS Position Sticky Really Works!
CSS position sticky has two main parts, sticky item & sticky container.
Sticky Item — is the element that we defined with the position: sticky styles. The element will float when the viewport position
matches the position definition, for example: top: 0px
.
Sticky Container —is the HTML element which wraps the sticky item. This is the maximum area that the sticky item can float in.
When you define an element with position: sticky you’re automatically
defining the parent element as a sticky container!
我知道这似乎已经回答了,但我 运行 进入了一个特定的案例,我觉得大多数答案都没有抓住要点。
overflow:hidden
的答案涵盖了 90% 的情况。这或多或少是 "sticky nav" 的情况。
但是粘性行为最好在容器的高度内使用。想想您网站右栏中的时事通讯表格,它会随着页面向下滚动。
如果您的粘性元素是容器的唯一子元素,则容器大小完全相同,没有滚动空间。
您的容器必须是您希望元素在其中滚动的高度。在我的 "right column" 场景中,哪个是左栏的高度。
实现此目的的最佳方法是在列上使用 display:table-cell
。如果你不能,并且像我一样被困在 float:right
中,你将不得不猜测左列高度或使用 Javascript.
计算它
我使用了 JS 解决方案。它适用于 Firefox 和 Chrome。有任何问题,请告诉我。
html
<body>
<header id="header">
<h1>Extra-Long Page Heading That Wraps</h1>
<nav id="nav">
<ul>
<li><a href="" title="">Home</a></li>
<li><a href="" title="">Page 2</a></li>
<li><a href="" title="">Page 3</a></li>
</ul>
</nav>
</header>
<main>
<p><!-- ridiculously long content --></p>
</main>
<footer>
<p>FOOTER CONTENT</p>
</footer>
<script src="navbar.js" type="text/javascript"></script>
</body>
css
nav a {
background: #aaa;
font-size: 1.2rem;
text-decoration: none;
padding: 10px;
}
nav a:hover {
background: #bbb;
}
nav li {
background: #aaa;
padding: 10px 0;
}
nav ul {
background: #aaa;
list-style-type: none;
margin: 0;
padding: 0;
}
@media (min-width: 768px) {
nav ul {
display: flex;
}
}
js
function applyNavbarSticky() {
let header = document.querySelector('body > header:first-child')
let navbar = document.querySelector('nav')
header.style.position = 'sticky'
function setTop() {
let headerHeight = header.clientHeight
let navbarHeight = navbar.clientHeight
let styleTop = navbarHeight - headerHeight
header.style.top = `${styleTop}px`
}
setTop()
window.onresize = function () {
setTop()
}
}
万一您遇到了这个问题并且您的粘性贴无法正常工作 - 尝试将父项设置为:
display: unset
为我工作
z-index
也很重要。有时它会起作用,但您只是看不到它。尝试将其设置为某个非常高的数字以确保万无一失。也不要总是把 top: 0
放在更高的位置,以防它隐藏在某个地方(在工具栏下)。
粘性元素的真实行为是:
- 首先是相对的
- 然后暂时修复
- 最后,它从视野中消失了
粘性定位元素被视为相对定位,直到其包含块在其流根(或它滚动的容器)内超过指定阈值(例如将 top 设置为 auto 以外的值),此时它被视为“卡住”,直到遇到其包含块的相对边缘。
元素根据文档的正常流定位,然后相对于其最近的滚动祖先和包含块(最近的块级祖先)进行偏移,包括 table 相关元素,基于top、right、bottom 和 left 的值。偏移量不影响任何其他元素的位置。
这个值总是创建一个新的堆叠上下文。请注意,粘性元素“粘附”到其最近的具有“滚动机制”的祖先(当溢出被隐藏、滚动、自动或覆盖时创建),即使该祖先不是最近的实际滚动祖先。
这个例子将帮助您理解:
这就是让我绊倒的原因...我的粘性 div 在另一个 div 里面,所以 parent div 在粘性 [= 之后需要一些额外的内容18=],使 parent div“足够高”以便粘性 div 在您向下滚动时“滑过”其他内容。
所以在我的例子中,在粘性 div 之后,我必须添加:
%div{style:"height:600px;"}
(我的应用程序有两个 side-by-side div,左边是一个“高大”的图像,右边是一个简短的数据输入表单,我希望数据输入表单能够向下滚动时浮动在图像旁边,因此表单始终在屏幕上。在我添加上面的“额外内容”之前它不会工作,所以粘性 div 有一些东西可以“滑过”[=11] =]
使用此博客 (https://www.designcise.com/web/tutorial/how-to-fix-issues-with-css-position-sticky-not-working) 中的策略,我为那些无法控制页面中所有组件的人想出了一个选项
我正在使用 Angular 并且在 ngOnInit 方法中我 运行 此代码将父项的可见属性更改为可见
/**
* position: sticky
* only works if all parent components are visibile
*/
let parent = document.querySelector('.sticky').parentElement;
while (parent) {
const hasOverflow = getComputedStyle(parent).overflow;
if (hasOverflow !== 'visible') {
parent.style.overflow = 'visible';
// console.log(hasOverflow, parent);
}
parent = parent.parentElement;
}
我知道为时已晚。但我找到了一个解决方案 即使您在父元素中使用溢出或 display:flex sticky 也可以工作。
步骤:
为要设置粘性的元素创建父元素(确保创建的元素是相对于 body 或全宽和全高父元素)。
将以下样式添加到父元素:
{
位置:绝对;
高度:100vmax;
}
对于粘性元素,确保添加高于页面中所有元素的z-index。
就是这样!现在它必须工作了。问候
关于 position
sticky
的最常见错误之一是:
- 浏览器不支持
- 不包括任何上右下左属性。请记住,如果您没有提供足够的信息,浏览器将不知道如何正确处理它。如果没有它,它将只是
statically
定位。
我已经写过关于这个的内容以及更多关于这个 article 的内容。只是放一个参考,所以我不会重复太多。
Sticky
如果您的 parent 使用显示器 flex
,则位置将不起作用。当我在一个解决方案中阅读这篇文章时
Since flex box elements default to stretch, all the elements are the same height, which can't be scrolled against.
因此,如果您在 parent 上使用 display: flex;
,则必须将其添加到粘性元素 align-self: flex-start;
并将高度设置为自动 height: auto;
这是粘性元素 class 的样子
.stick-ontop {
position: -webkit-sticky !important; // for safari
position: sticky !important;
top: 0;
align-self: flex-start;
height: auto;
}
我遇到了同样的问题。对我来说,问题是 display: 'none' 在大屏幕上(媒体查询)和 display: 'initial' 在智能手机上。如果我删除了显示 css 属性 并在桌面上添加了不透明度和指针事件 none 一切正常。
另一种非常常见的 position: sticky
可能不起作用的情况是,如果它的父项有 display: flex
或 display: grid
。
在这种情况下发生的情况是粘性位置起作用,但您看不到它,因为元素已完全拉伸。尝试使用 align-self: baseline
降低它的高度,您会看到效果。
尽管阅读了整个页面并尝试了除厨房水槽之外的所有内容,但这在我的移动设备上根本不起作用。根本没有粘性动作——这是我唯一需要它工作的地方。我已经排除了任何会阻止此屏幕宽度运行的特殊指定或覆盖。清除我的移动格式代码作为测试,没有看到任何变化。在我的笔记本电脑上的 Chrome 浏览器上完美运行,在我的新 S10 上的 chrome 浏览器上完全不运行。
1.Position 如果在元素的任何父元素上将 overflow 设置为 hidden、scroll 或 auto,sticky 很可能不起作用。
2.Position 如果任何父元素设置了高度,粘性可能无法正常工作。
注意空白网格区域!
在我的例子中,我有这样的事情:
.cart-areas {
grid-template-columns: 2fr 0.2fr 1.5fr;
grid-template-areas:
'order . summary'
'order . .'
'order . .';
}
我希望 summary
网格项目在用户完成结帐表单时具有粘性。由于那些 empty grid items
(标有 .
),它不起作用。
解决方案是像这样删除那些空项目:
.cart-areas {
grid-template-columns: 2fr 0.2fr 1.5fr;
grid-template-areas:
'order . summary'
'order . summary'
'order . summary';
}
// 粘码
const stickyItem = document.querySelector(".item-to-made-sticky")
document.addEventListener("滚动", () => {
stickyItem.style.transform = translateY(${window.scrollY}px)
})
从其他方向攻击这个Q
假设这是一个游戏 Find the nearest scrolling ancestor
。
<!-- sticky not working -->
<h1 style="position: sticky; top:0;">Hello World</h1>
问题:
- 1/3:粘性节点?
<h1>
.
- 2/3:老祖宗?
<body>
.
- 3/3:
<body>
滚动? FALSE
=>“无效”。
修复:“粘滞正在工作”(<body>
滚动?TRUE
)。
body{
min-height: 300vh;
}
<!-- sticky working -->
<h1 style="position: sticky; top: 0;">Hello World</h1>
考虑到这一点 - 这里有一些“不工作”粘性的“hello world”“著名”场景 :) 大多数情况与这些情况中的一个或多个有关。
案例 1:缺少“顶部”(易于修复):
不工作:
/* not working example */
aside{
position: sticky;
background: lightgray;
}
main{
height: 200vh;
}
<aside>
<h2>sticky Aside</h2>
</aside>
<main>
<h1>Article</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui dicta minus molestiae vel beatae natus eveniet ratione temporibus aperiam harum alias officiis assumenda officia quibusdam deleniti eos cupiditate dolore doloribus!
</p>
</main>
修复(添加顶部):
aside{
position: sticky;
top: 0;
}
main{
height: 200vh;
}
<aside>
<h2>sticky Aside</h2>
</aside>
<main>
<h1>Article</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui dicta minus molestiae vel beatae natus eveniet ratione temporibus aperiam harum alias officiis assumenda officia quibusdam deleniti eos cupiditate dolore doloribus!
</p>
</main>
案例 2:粘性节点和溢出(易于修复):
我通过添加 #extra-wrapper
和溢出设置 auto
- 或 - hidden
- 或 - visible
- 但 没有 任何剪辑的内容。
“问题”现在最近的滚动祖先(#extra-wrapper
)“没有”任何滚动(没有滚动条拖动选项==“没有滚动祖先”)。
不工作:
/* not working example */
#overflow-wrapper{
overflow: scroll;
}
aside{
position: sticky;
background: lightgray;
top: 0px;
}
main{
height: 200vh;
}
<div id="overflow-wrapper">
<aside>
<h2>sticky Aside</h2>
</aside>
<main>
<h1>Article</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui dicta minus molestiae vel beatae natus eveniet ratione temporibus aperiam harum alias officiis assumenda officia quibusdam deleniti eos cupiditate dolore doloribus!
</p>
</main>
</div>
修复 - 剪辑内容(现在它们是“最近的滚动祖先”)。
工作:
/* not working example */
#overflow-wrapper{
overflow: scroll;
max-height: 60vh; /* clip the content */
}
aside{
position: sticky;
background: lightgray;
top: 0px;
}
main{
height: 200vh;
}
<div id="overflow-wrapper">
<aside>
<h2>sticky Aside</h2>
</aside>
<main>
<h1>Article</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui dicta minus molestiae vel beatae natus eveniet ratione temporibus aperiam harum alias officiis assumenda officia quibusdam deleniti eos cupiditate dolore doloribus!
</p>
</main>
</div>
案例 3:与“错误/不滚动”节点相关的粘滞(难以修复)
同样,Sticky 偏移量相对于其最近的滚动祖先。
我通过将 #extra-wrapper
添加到 sticky
元素来“销毁”即时贴。为什么它不起作用?现在#extra-wrapper
的高度==高度aside
内容(box model)==“无滚动祖先”==“无效果”。
不工作:
/* not working example */
aside{
position: sticky;
top: 0;
background: lightgray;
}
main{
height: 200vh;
}
<div id="extra-wrapper">
<aside>
<h2>sticky Aside</h2>
</aside>
</div>
<main>
<h1>Article</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui dicta minus molestiae vel beatae natus eveniet ratione temporibus aperiam harum alias officiis assumenda officia quibusdam deleniti eos cupiditate dolore doloribus!
</p>
</main>
这才是真正“发生”的事情(我将高度添加到 #extra-wrapper
):
#extra-wrapper{
background: lightgray;
height: 40vh;
}
aside{
position: sticky;
top: 0;
}
main{
height: 200vh;
}
<div id="extra-wrapper">
<aside>
<h2>sticky Aside</h2>
</aside>
</div>
<main>
<h1>Article</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui dicta minus molestiae vel beatae natus eveniet ratione temporibus aperiam harum alias officiis assumenda officia quibusdam deleniti eos cupiditate dolore doloribus!
</p>
</main>
修复:
更改粘性节点:
#extra-wrapper{
position: sticky;
top: 0;
}
aside{
}
#layout{
displ
}
main{
height: 200vh;
}
<div id="extra-wrapper">
<aside>
<h2>sticky Aside</h2>
</aside>
</div>
<main>
<h1>Article</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui dicta minus molestiae vel beatae natus eveniet ratione temporibus aperiam harum alias officiis assumenda officia quibusdam deleniti eos cupiditate dolore doloribus!
</p>
</main>
案例 4:显示:flexbox/Grid 布局 - 默认为均匀列(很难修复)
您创建 flex/grid 布局并将其中一个列设置为 sticky
。默认情况下,cols 高度为 even = “最近的祖先”(包装器)的高度 == Cols 高度 = 无滚动效果。
不工作:
#extra-wrapper{
position: sticky;
top: 0;
border: 1px solid red;
}
aside{
}
#layout{
display: flex;
}
main{
height: 200vh;
}
<div id="layout">
<div id="extra-wrapper">
<aside>
<h2>sticky Aside</h2>
</aside>
</div>
<main>
<h1>Article</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui dicta minus molestiae vel beatae natus eveniet ratione temporibus aperiam harum alias officiis assumenda officia quibusdam deleniti eos cupiditate dolore doloribus!
</p>
</main>
</div>
修复:例如将粘滞 max-height
设置为 90vh
(现在 cols 高度 不均匀 )。
工作:
#extra-wrapper{
position: sticky;
top: 0;
border: 1px solid red;
max-height: 90vh;
}
aside{
}
#layout{
display: flex;
}
main{
height: 200vh;
}
<div id="layout">
<div id="extra-wrapper">
<aside>
<h2>sticky Aside</h2>
</aside>
</div>
<main>
<h1>Article</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui dicta minus molestiae vel beatae natus eveniet ratione temporibus aperiam harum alias officiis assumenda officia quibusdam deleniti eos cupiditate dolore doloribus!
</p>
</main>
</div>
如果父级有浮动则不起作用:属性.
我想让导航栏在用户滚动页面后固定在视口的顶部,但它不起作用,我也不知道为什么。如果你能帮忙,这是我的 HTML 和 CSS 代码:
.container {
min-height: 300vh;
}
.nav-selections {
text-transform: uppercase;
letter-spacing: 5px;
font: 18px "lato",sans-serif;
display: inline-block;
text-decoration: none;
color: white;
padding: 18px;
float: right;
margin-left: 50px;
transition: 1.5s;
}
.nav-selections:hover{
transition: 1.5s;
color: black;
}
ul {
background-color: #B79b58;
overflow: auto;
}
li {
list-style-type: none;
}
<main class="container">
<nav style="position: sticky; position: -webkit-sticky;">
<ul align="left">
<li><a href="#/contact" class="nav-selections" style="margin-right:35px;">Contact</a></li>
<li><a href="#/about" class="nav-selections">About</a></li>
<li><a href="#/products" class="nav-selections">Products</a></li>
<li><a href="#" class="nav-selections">Home</a></li>
</ul>
</nav>
</main>
Sticky positioning is a hybrid of relative and fixed positioning. The element is treated as relative positioned until it crosses a specified threshold, at which point it is treated as fixed positioned.
...
You must specify a threshold with at least one oftop
,right
,bottom
, orleft
for sticky positioning to behave as expected. Otherwise, it will be indistinguishable from relative positioning. [source: MDN]
因此在您的示例中,您必须使用 top
属性.
html, body {
height: 200%;
}
nav {
position: sticky;
position: -webkit-sticky;
top: 0; /* required */
}
.nav-selections {
text-transform: uppercase;
letter-spacing: 5px;
font: 18px "lato", sans-serif;
display: inline-block;
text-decoration: none;
color: white;
padding: 18px;
float: right;
margin-left: 50px;
transition: 1.5s;
}
.nav-selections:hover {
transition: 1.5s;
color: black;
}
ul {
background-color: #B79b58;
overflow: auto;
}
li {
list-style-type: none;
}
<nav>
<ul align="left">
<li><a href="#/contact" class="nav-selections" style="margin-right:35px;">Contact</a></li>
<li><a href="#/about" class="nav-selections">About</a></li>
<li><a href="#/products" class="nav-selections">Products</a></li>
<li><a href="#" class="nav-selections">Home</a></li>
</ul>
</nav>
来自我的评论:
position:sticky
needs a coordonate to tel where to stick
nav {
position: sticky;
top: 0;
}
.nav-selections {
text-transform: uppercase;
letter-spacing: 5px;
font: 18px "lato", sans-serif;
display: inline-block;
text-decoration: none;
color: white;
padding: 18px;
float: right;
margin-left: 50px;
transition: 1.5s;
}
.nav-selections:hover {
transition: 1.5s;
color: black;
}
ul {
background-color: #B79b58;
overflow: auto;
}
li {
list-style-type: none;
}
body {
height: 200vh;
}
<nav>
<ul align="left">
<li><a href="#/contact" class="nav-selections" style="margin-right:35px;">Contact</a></li>
<li><a href="#/about" class="nav-selections">About</a></li>
<li><a href="#/products" class="nav-selections">Products</a></li>
<li><a href="#" class="nav-selections">Home</a></li>
</ul>
</nav>
除了 FF 和 Chrome 之外,还有其他浏览器可以使用的 polyfill。这是一个实验性的规则,可以通过浏览器随时执行或不执行。 Chrome 几年前添加,然后又放弃了,好像又回来了……但是多久了?
最接近的是 position:relative + 滚动到达粘点时更新坐标,如果你想把它变成 javascript 脚本
检查祖先元素是否设置了溢出(例如overflow:hidden
);尝试切换它。您可能需要检查 DOM 树,它比您预期的要高 =).
这可能会影响后代元素上的 position:sticky
。
我有同样的问题,我找到了答案here。
如果您的元素没有按预期粘附,首先要检查的是应用到容器的规则。
具体来说,查找在元素的任何父元素上设置的任何溢出 属性。 您不能在 position: sticky
元素的父元素上使用:overflow: hidden
、overflow: scroll
或 overflow: auto
。
我遇到的更多事情:
当您的粘性元素是组件时(angular 等)
如果 'sticky' 元素本身是具有自定义元素选择器的组件,例如名为
<app-menu-bar>
的 angular 组件,您将需要添加跟随组件的 css::host { display: block; } // or use flexbox
或
app-menu-bar { display: block; } // (in the containing component's css)
Safari on iOS in particular seems to require `display:block` even on the root element `app-root` of an angular application or it won't stick.
如果您正在创建组件并在组件内部定义 css(阴影 DOM/封装样式),请确保应用
position: sticky
到 'outer' 选择器(例如,devtools 中的app-menu-bar
应该显示粘性位置)而不是div
在 组件中的顶级。使用 Angular,这可以通过 css 中的:host
选择器为您的组件实现。:host { position: sticky; display: block; // this is the same as shown above top: 0; background: red; }
其他
如果粘性元素后面的元素有纯色背景,您必须添加以下内容以阻止它在下方滑动:
.sticky-element { z-index: 100; } .parent-of-sticky-element { position: relative; }
如果使用
top
,您的粘性元素必须 在您的内容之前 ,如果使用 在它之后bottom
.在包装元素上使用
overflow: hidden
时会出现一些复杂情况——通常它会杀死内部的粘性元素。 Better explained in this question移动浏览器可能会在屏幕键盘可见时禁用 sticky/fixed 定位的项目。我不确定确切的规则(有人知道吗)但是当键盘可见时,您正在查看 window 中的某种 'window' 并且您不会轻易能够让东西粘在屏幕的实际可见顶部。
确保你有:
position: sticky;
而不是
display: sticky;
其他可用性问题
- 如果您的设计要求将内容粘贴到移动设备的屏幕底部,请务必谨慎。例如,在 iPhone X 上,它们会显示一条窄线来指示滑动区域(返回主页)- 并且该区域内的元素不可点击。因此,如果您坚持使用某些东西,请务必在 iPhone X 上测试用户是否可以激活它。如果人们不能点击,那么大的 'Buy Now' 按钮是没有用的!
- 如果您在 Facebook 上投放广告,网页将显示在 Facebook 移动应用程序的 'webview' 控件中。尤其是在显示视频时(您的内容仅从屏幕的下半部分开始)- 他们通常会通过将您的页面放在一个可滚动的视口中来完全弄乱粘性元素,这实际上允许您的粘性元素从页面顶部消失。请务必在实际广告的上下文中进行测试,而不仅仅是在 phone 的浏览器甚至 Facebook 的浏览器中进行测试,它们的行为可能都不同。
这是 MarsAndBack 和 Miftah Mizwar 回答的延续。
他们的回答是正确的。但是,很难确定问题的祖先。
为了使这个变得非常简单,只需在您的浏览器控制台中 运行 这个 jQuery 脚本,它会告诉您每个祖先的溢出值 属性。
$('.your-sticky-element').parents().filter(function() {
console.log($(this));
console.log($(this).css('overflow'));
return $(this).css('overflow') === 'hidden';
});
如果一个祖先没有 overflow: visible
改变它的 CSS 以便它有!
此外,如其他地方所述,请确保您的粘性元素在 CSS:
.your-sticky-element {
position: sticky;
top: 0;
}
这里有两个答案:
从
body
标签中删除overflow
属性将
height: 100%
设置为body
以解决overflow-y: auto
的问题
min-height: 100%
not-working instead ofheight: 100%
有趣的时刻对我来说并不明显:至少在 Chrome 70 position: sticky
如果您使用 DevTools 设置它则不会应用。
似乎要粘贴的导航栏不应该在任何 div 或包含其他内容的部分中。 None 的解决方案对我有用,直到我将导航栏从导航栏与另一个顶部栏共享的 div 中取出。我以前用一个公共 div 包裹了顶部栏和导航栏。
确实需要删除 overflow
或将其设置为 initial
才能使 position: sticky
作用于子元素。我在我的 Angular 应用程序中使用了 Material 设计,发现 一些 Material 组件更改了 overflow
值。我的方案的修复是
mat-sidenav-container, mat-sidenav-content {
overflow: initial;
}
我不得不使用以下 CSS 来让它工作:
.parent {
display: flex;
justify-content: space-around;
align-items: flex-start;
overflow: visible;
}
.sticky {
position: sticky;
position: -webkit-sticky;
top: 0;
}
如果上面的方法不起作用那么...
遍历所有祖先并确保这些元素中的 none 个具有 overflow: hidden
。您必须将其更改为 overflow: visible
如果 danday74 的修复不起作用,请检查 parent 元素是否有高度。
就我而言,我有两个孩子,一个向左漂浮,一个向右漂浮。
我想让右边的浮动变得粘稠,但不得不在 parent 的末尾添加一个 <div style="clear: both;"></div>
来给它高度。
我知道这是旧的post。但是如果有像我这样的人最近才开始弄乱 position: sticky 这可能会有用。
在我的例子中,我使用 position: sticky 作为网格项。它不工作,问题是 overflow-x: hidden 在 html
元素上。一旦我删除 属性 它就可以正常工作。将 overflow-x: 隐藏在 body
元素上似乎可行,但还不知道为什么。
我相信 this article 说了很多 sticky
的工作原理
How CSS Position Sticky Really Works! CSS position sticky has two main parts, sticky item & sticky container.
Sticky Item — is the element that we defined with the position: sticky styles. The element will float when the viewport position matches the position definition, for example:
top: 0px
.Sticky Container —is the HTML element which wraps the sticky item. This is the maximum area that the sticky item can float in.
When you define an element with position: sticky you’re automatically defining the parent element as a sticky container!
我知道这似乎已经回答了,但我 运行 进入了一个特定的案例,我觉得大多数答案都没有抓住要点。
overflow:hidden
的答案涵盖了 90% 的情况。这或多或少是 "sticky nav" 的情况。
但是粘性行为最好在容器的高度内使用。想想您网站右栏中的时事通讯表格,它会随着页面向下滚动。 如果您的粘性元素是容器的唯一子元素,则容器大小完全相同,没有滚动空间。
您的容器必须是您希望元素在其中滚动的高度。在我的 "right column" 场景中,哪个是左栏的高度。
实现此目的的最佳方法是在列上使用 display:table-cell
。如果你不能,并且像我一样被困在 float:right
中,你将不得不猜测左列高度或使用 Javascript.
我使用了 JS 解决方案。它适用于 Firefox 和 Chrome。有任何问题,请告诉我。
html
<body>
<header id="header">
<h1>Extra-Long Page Heading That Wraps</h1>
<nav id="nav">
<ul>
<li><a href="" title="">Home</a></li>
<li><a href="" title="">Page 2</a></li>
<li><a href="" title="">Page 3</a></li>
</ul>
</nav>
</header>
<main>
<p><!-- ridiculously long content --></p>
</main>
<footer>
<p>FOOTER CONTENT</p>
</footer>
<script src="navbar.js" type="text/javascript"></script>
</body>
css
nav a {
background: #aaa;
font-size: 1.2rem;
text-decoration: none;
padding: 10px;
}
nav a:hover {
background: #bbb;
}
nav li {
background: #aaa;
padding: 10px 0;
}
nav ul {
background: #aaa;
list-style-type: none;
margin: 0;
padding: 0;
}
@media (min-width: 768px) {
nav ul {
display: flex;
}
}
js
function applyNavbarSticky() {
let header = document.querySelector('body > header:first-child')
let navbar = document.querySelector('nav')
header.style.position = 'sticky'
function setTop() {
let headerHeight = header.clientHeight
let navbarHeight = navbar.clientHeight
let styleTop = navbarHeight - headerHeight
header.style.top = `${styleTop}px`
}
setTop()
window.onresize = function () {
setTop()
}
}
万一您遇到了这个问题并且您的粘性贴无法正常工作 - 尝试将父项设置为:
display: unset
为我工作
z-index
也很重要。有时它会起作用,但您只是看不到它。尝试将其设置为某个非常高的数字以确保万无一失。也不要总是把 top: 0
放在更高的位置,以防它隐藏在某个地方(在工具栏下)。
粘性元素的真实行为是:
- 首先是相对的
- 然后暂时修复
- 最后,它从视野中消失了
粘性定位元素被视为相对定位,直到其包含块在其流根(或它滚动的容器)内超过指定阈值(例如将 top 设置为 auto 以外的值),此时它被视为“卡住”,直到遇到其包含块的相对边缘。
元素根据文档的正常流定位,然后相对于其最近的滚动祖先和包含块(最近的块级祖先)进行偏移,包括 table 相关元素,基于top、right、bottom 和 left 的值。偏移量不影响任何其他元素的位置。
这个值总是创建一个新的堆叠上下文。请注意,粘性元素“粘附”到其最近的具有“滚动机制”的祖先(当溢出被隐藏、滚动、自动或覆盖时创建),即使该祖先不是最近的实际滚动祖先。
这个例子将帮助您理解:
这就是让我绊倒的原因...我的粘性 div 在另一个 div 里面,所以 parent div 在粘性 [= 之后需要一些额外的内容18=],使 parent div“足够高”以便粘性 div 在您向下滚动时“滑过”其他内容。
所以在我的例子中,在粘性 div 之后,我必须添加:
%div{style:"height:600px;"}
(我的应用程序有两个 side-by-side div,左边是一个“高大”的图像,右边是一个简短的数据输入表单,我希望数据输入表单能够向下滚动时浮动在图像旁边,因此表单始终在屏幕上。在我添加上面的“额外内容”之前它不会工作,所以粘性 div 有一些东西可以“滑过”[=11] =]
使用此博客 (https://www.designcise.com/web/tutorial/how-to-fix-issues-with-css-position-sticky-not-working) 中的策略,我为那些无法控制页面中所有组件的人想出了一个选项
我正在使用 Angular 并且在 ngOnInit 方法中我 运行 此代码将父项的可见属性更改为可见
/**
* position: sticky
* only works if all parent components are visibile
*/
let parent = document.querySelector('.sticky').parentElement;
while (parent) {
const hasOverflow = getComputedStyle(parent).overflow;
if (hasOverflow !== 'visible') {
parent.style.overflow = 'visible';
// console.log(hasOverflow, parent);
}
parent = parent.parentElement;
}
我知道为时已晚。但我找到了一个解决方案 即使您在父元素中使用溢出或 display:flex sticky 也可以工作。
步骤:
为要设置粘性的元素创建父元素(确保创建的元素是相对于 body 或全宽和全高父元素)。
将以下样式添加到父元素:
{ 位置:绝对; 高度:100vmax; }
对于粘性元素,确保添加高于页面中所有元素的z-index。
就是这样!现在它必须工作了。问候
关于 position
sticky
的最常见错误之一是:
- 浏览器不支持
- 不包括任何上右下左属性。请记住,如果您没有提供足够的信息,浏览器将不知道如何正确处理它。如果没有它,它将只是
statically
定位。
我已经写过关于这个的内容以及更多关于这个 article 的内容。只是放一个参考,所以我不会重复太多。
Sticky
如果您的 parent 使用显示器 flex
,则位置将不起作用。当我在一个解决方案中阅读这篇文章时
Since flex box elements default to stretch, all the elements are the same height, which can't be scrolled against.
因此,如果您在 parent 上使用 display: flex;
,则必须将其添加到粘性元素 align-self: flex-start;
并将高度设置为自动 height: auto;
这是粘性元素 class 的样子
.stick-ontop {
position: -webkit-sticky !important; // for safari
position: sticky !important;
top: 0;
align-self: flex-start;
height: auto;
}
我遇到了同样的问题。对我来说,问题是 display: 'none' 在大屏幕上(媒体查询)和 display: 'initial' 在智能手机上。如果我删除了显示 css 属性 并在桌面上添加了不透明度和指针事件 none 一切正常。
另一种非常常见的 position: sticky
可能不起作用的情况是,如果它的父项有 display: flex
或 display: grid
。
在这种情况下发生的情况是粘性位置起作用,但您看不到它,因为元素已完全拉伸。尝试使用 align-self: baseline
降低它的高度,您会看到效果。
尽管阅读了整个页面并尝试了除厨房水槽之外的所有内容,但这在我的移动设备上根本不起作用。根本没有粘性动作——这是我唯一需要它工作的地方。我已经排除了任何会阻止此屏幕宽度运行的特殊指定或覆盖。清除我的移动格式代码作为测试,没有看到任何变化。在我的笔记本电脑上的 Chrome 浏览器上完美运行,在我的新 S10 上的 chrome 浏览器上完全不运行。
1.Position 如果在元素的任何父元素上将 overflow 设置为 hidden、scroll 或 auto,sticky 很可能不起作用。
2.Position 如果任何父元素设置了高度,粘性可能无法正常工作。
注意空白网格区域!
在我的例子中,我有这样的事情:
.cart-areas {
grid-template-columns: 2fr 0.2fr 1.5fr;
grid-template-areas:
'order . summary'
'order . .'
'order . .';
}
我希望 summary
网格项目在用户完成结帐表单时具有粘性。由于那些 empty grid items
(标有 .
),它不起作用。
解决方案是像这样删除那些空项目:
.cart-areas {
grid-template-columns: 2fr 0.2fr 1.5fr;
grid-template-areas:
'order . summary'
'order . summary'
'order . summary';
}
// 粘码
const stickyItem = document.querySelector(".item-to-made-sticky")
document.addEventListener("滚动", () => {
stickyItem.style.transform = translateY(${window.scrollY}px)
})
从其他方向攻击这个Q
假设这是一个游戏 Find the nearest scrolling ancestor
。
<!-- sticky not working -->
<h1 style="position: sticky; top:0;">Hello World</h1>
问题:
- 1/3:粘性节点?
<h1>
. - 2/3:老祖宗?
<body>
. - 3/3:
<body>
滚动?FALSE
=>“无效”。
修复:“粘滞正在工作”(<body>
滚动?TRUE
)。
body{
min-height: 300vh;
}
<!-- sticky working -->
<h1 style="position: sticky; top: 0;">Hello World</h1>
考虑到这一点 - 这里有一些“不工作”粘性的“hello world”“著名”场景 :) 大多数情况与这些情况中的一个或多个有关。
案例 1:缺少“顶部”(易于修复):
不工作:
/* not working example */
aside{
position: sticky;
background: lightgray;
}
main{
height: 200vh;
}
<aside>
<h2>sticky Aside</h2>
</aside>
<main>
<h1>Article</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui dicta minus molestiae vel beatae natus eveniet ratione temporibus aperiam harum alias officiis assumenda officia quibusdam deleniti eos cupiditate dolore doloribus!
</p>
</main>
修复(添加顶部):
aside{
position: sticky;
top: 0;
}
main{
height: 200vh;
}
<aside>
<h2>sticky Aside</h2>
</aside>
<main>
<h1>Article</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui dicta minus molestiae vel beatae natus eveniet ratione temporibus aperiam harum alias officiis assumenda officia quibusdam deleniti eos cupiditate dolore doloribus!
</p>
</main>
案例 2:粘性节点和溢出(易于修复):
我通过添加 #extra-wrapper
和溢出设置 auto
- 或 - hidden
- 或 - visible
- 但 没有 任何剪辑的内容。
“问题”现在最近的滚动祖先(#extra-wrapper
)“没有”任何滚动(没有滚动条拖动选项==“没有滚动祖先”)。
不工作:
/* not working example */
#overflow-wrapper{
overflow: scroll;
}
aside{
position: sticky;
background: lightgray;
top: 0px;
}
main{
height: 200vh;
}
<div id="overflow-wrapper">
<aside>
<h2>sticky Aside</h2>
</aside>
<main>
<h1>Article</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui dicta minus molestiae vel beatae natus eveniet ratione temporibus aperiam harum alias officiis assumenda officia quibusdam deleniti eos cupiditate dolore doloribus!
</p>
</main>
</div>
修复 - 剪辑内容(现在它们是“最近的滚动祖先”)。
工作:
/* not working example */
#overflow-wrapper{
overflow: scroll;
max-height: 60vh; /* clip the content */
}
aside{
position: sticky;
background: lightgray;
top: 0px;
}
main{
height: 200vh;
}
<div id="overflow-wrapper">
<aside>
<h2>sticky Aside</h2>
</aside>
<main>
<h1>Article</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui dicta minus molestiae vel beatae natus eveniet ratione temporibus aperiam harum alias officiis assumenda officia quibusdam deleniti eos cupiditate dolore doloribus!
</p>
</main>
</div>
案例 3:与“错误/不滚动”节点相关的粘滞(难以修复)
同样,Sticky 偏移量相对于其最近的滚动祖先。
我通过将 #extra-wrapper
添加到 sticky
元素来“销毁”即时贴。为什么它不起作用?现在#extra-wrapper
的高度==高度aside
内容(box model)==“无滚动祖先”==“无效果”。
不工作:
/* not working example */
aside{
position: sticky;
top: 0;
background: lightgray;
}
main{
height: 200vh;
}
<div id="extra-wrapper">
<aside>
<h2>sticky Aside</h2>
</aside>
</div>
<main>
<h1>Article</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui dicta minus molestiae vel beatae natus eveniet ratione temporibus aperiam harum alias officiis assumenda officia quibusdam deleniti eos cupiditate dolore doloribus!
</p>
</main>
这才是真正“发生”的事情(我将高度添加到 #extra-wrapper
):
#extra-wrapper{
background: lightgray;
height: 40vh;
}
aside{
position: sticky;
top: 0;
}
main{
height: 200vh;
}
<div id="extra-wrapper">
<aside>
<h2>sticky Aside</h2>
</aside>
</div>
<main>
<h1>Article</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui dicta minus molestiae vel beatae natus eveniet ratione temporibus aperiam harum alias officiis assumenda officia quibusdam deleniti eos cupiditate dolore doloribus!
</p>
</main>
修复: 更改粘性节点:
#extra-wrapper{
position: sticky;
top: 0;
}
aside{
}
#layout{
displ
}
main{
height: 200vh;
}
<div id="extra-wrapper">
<aside>
<h2>sticky Aside</h2>
</aside>
</div>
<main>
<h1>Article</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui dicta minus molestiae vel beatae natus eveniet ratione temporibus aperiam harum alias officiis assumenda officia quibusdam deleniti eos cupiditate dolore doloribus!
</p>
</main>
案例 4:显示:flexbox/Grid 布局 - 默认为均匀列(很难修复)
您创建 flex/grid 布局并将其中一个列设置为 sticky
。默认情况下,cols 高度为 even = “最近的祖先”(包装器)的高度 == Cols 高度 = 无滚动效果。
不工作:
#extra-wrapper{
position: sticky;
top: 0;
border: 1px solid red;
}
aside{
}
#layout{
display: flex;
}
main{
height: 200vh;
}
<div id="layout">
<div id="extra-wrapper">
<aside>
<h2>sticky Aside</h2>
</aside>
</div>
<main>
<h1>Article</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui dicta minus molestiae vel beatae natus eveniet ratione temporibus aperiam harum alias officiis assumenda officia quibusdam deleniti eos cupiditate dolore doloribus!
</p>
</main>
</div>
修复:例如将粘滞 max-height
设置为 90vh
(现在 cols 高度 不均匀 )。
工作:
#extra-wrapper{
position: sticky;
top: 0;
border: 1px solid red;
max-height: 90vh;
}
aside{
}
#layout{
display: flex;
}
main{
height: 200vh;
}
<div id="layout">
<div id="extra-wrapper">
<aside>
<h2>sticky Aside</h2>
</aside>
</div>
<main>
<h1>Article</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui dicta minus molestiae vel beatae natus eveniet ratione temporibus aperiam harum alias officiis assumenda officia quibusdam deleniti eos cupiditate dolore doloribus!
</p>
</main>
</div>
如果父级有浮动则不起作用:属性.