最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

html - Why doesn't the left sticky position work when the scroll container is the body? - Stack Overflow

programmeradmin2浏览0评论

I've tested this with the scroll container being a div and being the body, and when the container is the body, the sticky position doesn't work properly. It seems to me that the only sticky that works on the body is the top: 0, but I am trying to apply the left: 0. I still want to use the body as the scroll container because if I use a div container, the mobile's functionalities won't work (e.g. hiding the search bar when scrolling down). These are the tests:

Body as the container, doesn't work properly

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body style="margin: 0">
        <div style="background-color: blue; height: 100px; position: sticky; left: 0">
            TEST
        </div>
        <div style="height: 1000px; width: 1000px; background-color: red">
            TEST
        </div>
</body>
</html>

I've tested this with the scroll container being a div and being the body, and when the container is the body, the sticky position doesn't work properly. It seems to me that the only sticky that works on the body is the top: 0, but I am trying to apply the left: 0. I still want to use the body as the scroll container because if I use a div container, the mobile's functionalities won't work (e.g. hiding the search bar when scrolling down). These are the tests:

Body as the container, doesn't work properly

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body style="margin: 0">
        <div style="background-color: blue; height: 100px; position: sticky; left: 0">
            TEST
        </div>
        <div style="height: 1000px; width: 1000px; background-color: red">
            TEST
        </div>
</body>
</html>

Div as the container, works properly

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body style="margin: 0">
    <div style="height: 100dvh; overflow: auto">
        <div style="background-color: blue; height: 100px; position: sticky; left: 0">
            TEST
        </div>
        <div style="height: 1000px; width: 1000px; background-color: red">
            TEST
        </div>
    </div>
</body>
</html>

Share Improve this question asked Apr 1 at 4:46 CristoferCristofer 654 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 0

Building on the answer by @TemaniAfif, it seems that if you style the body with both overflow: auto and contain: layout, the horizontal stickiness works as expected.

body {
  margin: 0;
  overflow: auto;
  contain: layout;
}
<div style="background-color: blue; height: 100px; position: sticky; left: 0">
  TEST
</div>
<div style="height: 100px; width: 1000px; background-color: red">
  TEST
</div>

Use with caution, though ... I don’t have any experience with strong containment, so I have no idea what negative side-effects this may have.

Another potential implementation, rather than having the body do the horizontal scrolling, would be to have the red element do it. Then you wouldn’t need to use sticky positioning on the blue element or containment control on the body. The body can still take care of the vertical scrolling, but each section takes care of its own horizontal scrolling.

There is a special behavior with the scrolling mechanism when the body element is involved.

Here are both demos where I am adding some padding and borders:

body {
  padding: 20px;
  margin: 20px;
  border: 5px solid green;
}
<div style="background-color: blue; height: 100px; position: sticky; left: 0">
  TEST
</div>
<div style="height: 1000px; width: 1000px; background-color: red">
  TEST
</div>

body {
 margin: 0;
}
.box {
  padding: 20px;
  margin: 20px;
  border: 5px solid green;
}
<div style="height: 50dvh; overflow: auto" class="box">
  <div style="background-color: blue; height: 100px; position: sticky; left: 0">
    TEST
  </div>
  <div style="height: 1000px; width: 1000px; background-color: red">
    TEST
  </div>
</div>

Notice how in both cases, the sticky element is within the boundaries of its parent container but we don't have the same result when it comes to the scrollbar.

In the first case, you are not scrolling the body element but the whole document (due to an overflow propagation). In the second case, you are scrolling the element with set overflow: auto

You are observing this behaviour because the scrolling context is different in both the cases. 1. Div as the container In this case, the outer div has overflow: auto, which means it creates a new scrolling context. The sticky element (the blue div) is contained within this scrolling context. When you scroll horizontally, the blue div sticks to the left edge of the scrolling container.

2. Body as the container If you remove the outer div (the one with overflow: auto), the sticky div no longer has a scrolling context. Instead, it is now relative to the viewport. When you scroll horizontally, the sticky element does not stick because it is not contained within a scrolling context that allows it to behave as sticky.

However, in both scenarios, when you scroll vertically, the sticky element (the blue div) will stick to the top of its containing block (or the viewport if there is no containing block) once it reaches the top of the viewport. This is because the vertical scroll does not depend on the presence of a scrolling container; it simply needs to reach the top of the viewport.

Hope this helps. Thanks

发布评论

评论列表(0)

  1. 暂无评论