gpt4 book ai didi

css - 如果您为位置 : sticky, 指定 `bottom: 0` 为什么它做的事情与规范不同?

转载 作者:技术小花猫 更新时间:2023-10-29 11:22:42 24 4
gpt4 key购买 nike

这是我在MDN上看一篇文章时的一个问题 position property .我认为 sticky 的行为之间存在明显差异在那里描述和实际行为。

根据 MDN,固定位置元素被视为相对位置元素,直到超过指定的阈值,当超过阈值时,它们被视为固定位置元素,直到到达父元素的边界( Link )。

Sticky positioning can be thought of as a hybrid of relative and fixed positioning. A stickily positioned element is treated as relatively positioned until it crosses a specified threshold, at which point it is treated as fixed until it reaches the boundary of its parent. For instance...

#one { position: sticky; top: 10px; } 

...would position the element with id one relatively until the viewport were scrolled such that the element would be less than 10 pixels from the top. Beyond that threshold, the element would be fixed to 10 pixels from the top.



因此,我创建了以下代码并确认了操作。

body {
margin: 0;
}

.container {
display: flex;
flex-direction: column;
}

.container>* {
width: 100%;
}

header {
background: #ffa;
height: 130vh;
}

main {
background: #faf;
height: 210vh;
}

footer {
background: #faa;
height: 8vh;
position: sticky;
bottom: 0;
}

.footer {
background: #aff;
height: 100vh;
}
<div class="container">
<header>HEADER</header>
<main>MAIN CONTENT</main>
<footer>FOOTER</footer>
<div class="footer"></div>
</div>


根据 MDN article ,这段代码“是一个相对放置元素,直到元素的位置通过滚动视口(viewport)距视口(viewport)底部小于0px,当它离底部大于0px时成为固定放置元素”我在想。

然而,结果是“滚动到固定位置元素,直到元素的位置通过滚动视口(viewport)从视口(viewport)下端小于0px,当从下端大于0px时成为相对排列的元素结尾”。

为什么指定 bottom:0结果与 MDN 中显示的行为相反?

top: 0指定,当元素未到达 bottom: 0时应用相对位置的视口(viewport),当它到达时,应用固定位置。当 bottom: 0指定,则相反。当元素未到达 bottom: 0 时应用相对位置的视口(viewport),到达时应用固定位置

我读了 CSS3但它的机制很难读懂

最佳答案

According to the MDN, fixed position elements are treated as relative position elements until the specified threshold is exceeded



这里完全是语言问题,因为上面的句子并不意味着元素一定要开始 position:relative 然后 变得固定。它说直到超过指定的阈值。那么,如果最初我们超过了指定的阈值怎么办?这实际上是你的例子的情况。

换句话说, position:sticky有两个状态。
  • 它被视为相对
  • 当超过指定的阈值时,它被视为固定

  • 哪个是第一个取决于您的 HTML 结构。

    下面是一个基本的例子来说明:

    body {
    height:150vh;
    margin:0;
    display:flex;
    flex-direction:column;
    border:2px solid;
    margin:50px;
    }

    .b {
    margin-top:auto;
    position:sticky;
    bottom:0;
    }

    .a {
    position:sticky;
    top:0;
    }
    <div class="a"> 
    I will start relative then I will be fixed
    </div>
    <div class="b">
    I will start fixed then I will be relative
    </div>


    你也可以混合使用。我们开始固定,变得相对,然后再次固定:

    body {
    height:250vh;
    margin:0;
    display:flex;
    flex-direction:column;
    border:2px solid;
    margin:50px;
    }
    body:before,
    body:after {
    content:"";
    flex:1;
    }

    .a {
    position:sticky;
    top:0;
    bottom:0;
    }
    <div class="a"> 
    I will start fixed then relative then fixed
    </div>


    正如你在上面的例子中看到的,两个状态都是独立的。如果条件 position:fixed是真的那么我们有 position:fixed ,如果不是,那么它是相对的。

    我们可以认为浏览器会实现这个伪代码:
    on_scroll_event() {
    if(threshold exceeded)
    position <- fixed
    else
    position <- relative
    }

    为了更准确和完整地了解该机制,您需要考虑 3 个要素。粘性元素(以及 top/bottom/left/right 的值),粘性元素的包含 block 和带有滚动框的最近祖先。
  • 带有滚动框的最近祖先只是具有与可见性不同的溢出的最近祖先,默认情况下它将是视口(viewport)(正如我在此处解释的: What are `scrolling boxes`? )。此元素上的滚动将控制粘性行为。
  • 粘性元素的包含 block 与相关元素的包含 block 相同 ref

  • 左/上/下/右是相对于滚动框计算的,包含 block 将定义粘性元素的限制。

    下面是一个例子来说明:

    body {
    margin:0;
    }
    .wrapper {
    width:300px;
    height:150px;
    border:2px solid red;
    overflow:auto;
    }

    .parent {
    height:200%;
    margin:100% 0;
    border:2px solid;
    }

    .sticky {
    position:sticky;
    display:inline-block;
    margin:auto;
    top:20px;
    background:red;
    }
    .non-sticky {
    display:inline-block;
    background:blue;
    }
    <div class="wrapper"><!-- our scrolling box -->
    <div class="parent"><!-- containing block -->
    <div class="sticky">I am sticky</div>
    <div class="non-sticky">I am the relative position</div>
    </div>
    </div>


    最初我们的元素是隐藏的,这是合乎逻辑的,因为它不能超出其包含 block (其限制)。一旦我们开始滚动,我们将看到我们的粘性元素和相关元素的行为完全相同。当我们有 20px 的距离时在粘性元素和滚动框的顶部边缘之间,我们达到了阈值,我们开始有 position:fixed直到我们再次到达底部包含 block 的限制(即我们不再有粘性行为的空间)

    现在让我们用底部替换顶部

    body {
    margin:0;
    }
    .wrapper {
    width:300px;
    height:150px;
    border:2px solid red;
    overflow:auto;
    }

    .parent {
    height:200%;
    margin:100% 0;
    border:2px solid;
    }

    .sticky {
    position:sticky;
    display:inline-block;
    margin:auto;
    bottom:20px;
    background:red;
    }
    .non-sticky {
    display:inline-block;
    background:blue;
    }
    <div class="wrapper"><!-- our scrolling box -->
    <div class="parent"><!-- containing block -->
    <div class="sticky">I am sticky</div>
    <div class="non-sticky">I am the relative position</div>
    </div>
    </div>


    什么都不会发生,因为当距离为 20px 时在元素和滚动框的底部边缘之间,粘性元素已经接触到包含 block 的顶部边缘,它不能出去。

    让我们在之前添加一个元素:

    body {
    margin:0;
    }
    .wrapper {
    width:300px;
    height:150px;
    border:2px solid red;
    overflow:auto;
    }

    .parent {
    height:200%;
    margin:100% 0;
    border:2px solid;
    }

    .sticky {
    position:sticky;
    display:inline-block;
    margin:auto;
    bottom:20px;
    background:red;
    }
    .non-sticky {
    display:inline-block;
    background:blue;
    }

    .elem {
    height:50px;
    width:100%;
    background:green;
    }
    <div class="wrapper"><!-- our scrolling box -->
    <div class="parent"><!-- containing block -->
    <div class="elem">elemen before</div>
    <div class="sticky">I am sticky</div>
    <div class="non-sticky">I am the relative position</div>
    </div>
    </div>


    现在我们已经创建了 50px有粘性行为的空间。让我们用底部添加回顶部:

    body {
    margin:0;
    }
    .wrapper {
    width:300px;
    height:150px;
    border:2px solid red;
    overflow:auto;
    }

    .parent {
    height:200%;
    margin:100% 0;
    border:2px solid;
    }

    .sticky {
    position:sticky;
    display:inline-block;
    margin:auto;
    bottom:20px;
    top:20px;
    background:red;
    }
    .non-sticky {
    display:inline-block;
    background:blue;
    }

    .elem {
    height:50px;
    width:100%;
    background:green;
    }
    <div class="wrapper"><!-- our scrolling box -->
    <div class="parent"><!-- containing block -->
    <div class="elem">elemen before</div>
    <div class="sticky">I am sticky</div>
    <div class="non-sticky">I am the relative position</div>
    </div>
    </div>


    现在我们有顶部和底部的行为,逻辑可以恢复如下:
    on_scroll_event() {
    if( top_sticky!=auto && distance_top_sticky_top_scrolling_box <20px && distance_bottom_sticky_bottom_containing_block >0) {
    position <- fixed
    } else if(bottom_sticky!=auto && distance_bottom_sticky_bottom_scrolling_box <20px && distance_top_sticky_top_containing_block >0) {
    position <- fixed
    } else (same for left) {
    position <- fixed
    } else (same for right) {
    position <- fixed
    } else {
    position <- relative
    }
    }

    关于css - 如果您为位置 : sticky, 指定 `bottom: 0` 为什么它做的事情与规范不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55965662/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com