Nested Sticky Element with Zero Left Does Not Sticky

Nested sticky element with zero left does not sticky

Let's add some border and we will clearly see what is happening:

.scroll {  width: 200px;  height: 200px;  border: 1px solid;  overflow: auto;}.scroll > div {  border:2px solid green;}
.container { width: 600px; height: 1000px; border:2px solid red!important;}.container > div { border:2px solid green;}
.sticky-left { position: sticky; left: 0;}
.sticky-top { position: sticky; top: 0;}
<div class="scroll">  <div class="sticky-top">sticky-top</div>  <div class="sticky-left">sticky-left</div>  <div class="container">    <div class="sticky-top">sticky-top-nested</div>    <div class="sticky-left">sticky-left-nested</div>  </div></div>

Why isn't position:sticky with left:0 working inside a scrollable container?

Add border to better see the issue which is related to the use a block level element and the restriction of width:100% (not the one your are setting which is useless but the default behavior of block elements)

.container {  overflow-x: scroll;}
.row { display: flex; border:1px solid;}
.item { min-width: 173px;}
.sticky { min-width: 250px; position: sticky; left: 0; background: red;}
<div class="container">  <div class="row">    <div class="item sticky">STICKY ROW 1</div>    <div class="item">1</div>    <div class="item">2</div>    <div class="item">3</div>    <div class="item">4</div>    <div class="item">5</div>    <div class="item">6</div>    <div class="item">7</div>    <div class="item">8</div>    <div class="item">9</div>    <div class="item">10</div>  </div>  <div class="row">    <div class="item sticky">STICKY ROW 2</div>    <div class="item">1</div>    <div class="item">2</div>    <div class="item">3</div>    <div class="item">4</div>    <div class="item">5</div>    <div class="item">6</div>    <div class="item">7</div>    <div class="item">8</div>    <div class="item">9</div>    <div class="item">10</div>  </div>  <div class="row">    <div class="item sticky">STICKY ROW 3</div>    <div class="item">1</div>    <div class="item">2</div>    <div class="item">3</div>    <div class="item">4</div>    <div class="item">5</div>    <div class="item">6</div>    <div class="item">7</div>    <div class="item">8</div>    <div class="item">9</div>    <div class="item">10</div>  </div></div>

Why is my element not sticking to the left when using position sticky in css?

The sticky element is a block level element inside another block level so this one is already taking 100% width if its parent element and there is no room for a left sticky behavior.

Add some border to better see:

.sticky {  position: -webkit-sticky;  position: sticky;  left: 0;  top: 0;  border:2px solid green;}
.scroll-horizontally-and-vertically { width: 4000px; height: 2000px; background-color: lightblue;}
<div style="border:2px solid red;">  <div class="sticky">    <h1>please stick to top and left</h1>  </div>  <div class="scroll-horizontally-and-vertically"></div></div>

Sticky element in a nested child

I switched the sticky position to right: 0px instead of left: 0px based on this:

A stickily positioned element is an element whose computed position
value is sticky. It's treated as relatively positioned until its
containing block crosses a specified threshold (such as setting top to
value other than auto) within its flow root (or the container it
scrolls within), at which point it is treated as "stuck" until meeting
the opposite edge of its containing block.

and this...

Note that a sticky element "sticks" to its nearest ancestor that has a
"scrolling mechanism" (created when overflow is hidden, scroll, auto,
or overlay), even if that ancestor isn't the nearest actually
scrolling ancestor. This effectively inhibits any "sticky" behavior
(see the GitHub issue on W3C CSSWG).
MDN

This keeps the sticky div in view and stuck to the right edge of the nearest scrollable element (the outer-most div in this case) in a horizontal context only, until meeting the opposite edge of its containing block (div with id of 'row').

<div id="scrollable-container" style="background-color: lightgrey; height: 150px; width: 600px; overflow: auto;">
<div id="fit" style="height: 150px; width: 800px;">
<div id="row" style="height: 100px; width: 800px; display: flex;">
<div id="cell" style="background-color: yellow; height: 100px; width: 600px;">The arguments object is useful for functions called with more arguments than they are formally declared to accept. This technique is useful for functions that can be passed a variable number of arguments, such as Math.min(). This example function accepts any number of string arguments and returns the longest one:</div>
<div id="cell-sticky"
style="background-color: red; height: 100px; width: 100px; position: sticky; right: 0px;"></div>
</div>
</div>
</div>

Nested flexboxes and position:sticky for top&bottom?

All your sticky elements need to belong to the same container to get this effect. So either remove sublist containers or use display:contents on them.

You need to remove a bunch of useless code. Also note that having bottom sticky for all your elements will only make the last one to be visible as it will be above all the others:

const list = document.querySelector(".actualList");for (let i = 0; i < 20; i++) {  const sublist = document.createElement("div");  sublist.classList.add("sublist");    const name = document.createElement("div");  name.classList.add("name");  name.innerText = `Test ${i + 1}`;  sublist.appendChild(name);    const rooms = document.createElement("div");  rooms.classList.add("rooms");  for (let j = 0; j < 4; j++) {    const room = document.createElement("div");    room.classList.add("room");    room.innerText = `Room ${j + 1}`;    rooms.appendChild(room);  }  sublist.appendChild(rooms);    list.appendChild(sublist);}
body, html {  margin: 0;}
.wrapper { height: 100vh; overflow: auto;}
.chat { background-color: aliceblue; height: 100%;}
.left { width: 300px; background-color: pink; display: flex; flex-direction: column; height: 100%;}
.header { border-bottom: 1px solid red; height: 37px;}
.list { overflow: auto;}
.actualList { flex: 1; display: flex; flex-direction: column;}
.sublist { display: contents;}
.name { position: sticky; bottom: 0; /* This doesn't appear to be working */ top: 0; margin: auto; background-color: coral; width: 100%;}
.room { padding-left: 10px;}
<div class="wrapper">    <div class="chat">      <div class="left">        <div class="header">          <b>Alice</b>          <div>Menu options</div>        </div>        <div class="list">          <div class="actualList">            <!-- generated -->          </div>        </div>      </div>    </div>  </div>

How does the position: sticky; property work?

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]

So in your example, you have to define the position where it should stick in the end by using the top property.

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 does not leave parent

Sticky works that way, it will remain sticky relative to its parent. You need to use fixed.
Check this codepen



Related Topics



Leave a reply



Submit