Why Isn't Position:Sticky with Left:0 Working Inside a Scrollable Container

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>

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>

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>

Why position sticky is not working in my code?

Its because you have overflow-x-hidden in parent . sticky doesn't work if parent overflow is hidden.

{!categorySearch && (
<div className="max-w-2xl mx-auto z-40 relative font-metropolis_semibold">
<div className="sticky top-0">
<div className=" z-40 bg-white w-full transition-all">
<div
id="logo"
className={
logo
? "px-md mt-10 font-medium"
: "px-md mt-10 font-medium animate"
}
>
<div className="overflow-x-hidden ">
<img
src={settings.logo_intro_image_url}
alt={settings.name}
className="max-w-full object-contain company-logo"
style={{ height: settings.logo_height }}
id="company-logo"
/>
</div>
</div>
<div
className={`${
logo
? "shadow-none border-none"
: "border-b-2 border-gray-200"
}`}
>
<TopOptions
showOption={showOption}
setShowOption={setShowOption}
addBorder={logo}
outlets={outlets}
languageLabels={languageLabels}
settings={selectedOutlet.settings}
/>
</div>
</div>
{Object.keys(bannerArray).length === 1 ? (
<div className="w-full px-md border-b-8 border-banner pb-md">
{bannerArray &&
bannerArray.map((banner, index) => {
return (
<>
<PosterSlider
key={index}
image={banner.image}
loadingBanners={loadingBanners}
isSingle={Object.keys(bannerArray).length === 1}
/>
</>
);
})}
</div>
) : (
<div className="max-h-full h-19.7 hide-scroll px-md flex overflow-x-auto gap-5p border-b-8 border-light-bg-gray">
{bannerArray &&
bannerArray.map((banner, index) => {
return (
<PosterSlider
key={index}
image={banner.image}
loadingBanners={loadingBanners}
isSingle={Object.keys(bannerArray).length === 1}
/>
);
})}
</div>
)}
<div className="flex flex-row justify-between items-center px-md my-25p">
<p className="font-metropolis_regular text-sm break-words">
{languageLabels.like_to_order}
</p>
<img
src={Search}
alt="search"
onClick={() => setCategorySearch(true)}
/>
</div>
<div className="grid grid-flow-row w-full grid-cols-2 place-items-center gap-10p px-md pb-20">
{categoryList.map((category) => {
// console.log(category);
return (
<Dishes
key={category.category_id}
category={category}
languageLabels={languageLabels}
loading={loadingCategories}
/>
);
})}
</div>
<BottomNavigation
languageLabels={languageLabels}
isLoyalty={settings.enable_reward_points_functionality}
/>
</div>
</div>
)}

why sticky position does not work in child div

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.

With that in mind, we know we need our threshold to be met, meaning that top:0 means when #menubar has 0 offset from top of it's containing block.

The containing block in our case is #header and it's height is defined by it's content, therefore the threshold is never met, because there's no overflow/scroll within it.

To see this more clearly we can apply some heights.

#menubar {  height: 50px;  width: 100%;  background-color: red;  position: sticky;  /* when there's 10px space left between menubar and header */  /* make it stick */  top: 10px;}
#header { border: 5px solid lime; height: 1000px;}
.content { border: 5px solid orange; height: 1000px;}
<div id="container">  <div id="header">    <div id="bannerbox">      <img src="images/banner.png" height="100%" width="100%" />    </div>    <div id="menubar">      i'm stuck sticky    </div>    <div id="cityinfo">cityinfo</div>  </div>
<div id="content" class="content"> header height is almost done, so the threshold will not be met very soon, this is what's hapening when the header has no overflow/scroll, menubar becomes sticky and goes back to normal almost instantly perhaps it never happens we don't know, it depends on how the user agant handles it. </div> <div id="footer"></div></div>

position:sticky ignoring right value in chrome

You are confusing between how absolute and fixed works compared to sticky.

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, ref

right and left will define the offset only when the element can stick on scroll. They will never position the element to the right or the left of the container.

Some examples:

.box {
border:2px solid;
height:100px;
margin:0 40px;
}
.box > div {
position:sticky;
height:100%;
width:100px;
background:red;
right:20px;
left:20px;
}

body {
width:200vw;
}
a left sticky behavior
<div class="box">
<div></div>
</div>
I move the element to the right using margin and we have a right sticky behavior
<div class="box">
<div style="margin-left:auto;"></div>
</div>

Sticky header doesn't stick anymore when scrolled beyond a certain point

It's related to the stretch default alignment of flex box. Disable it using align-self: start

.container {
outline: 1px solid black;
margin: 60px;
height: 300px;
width: 400px;
display: flex;
gap: 20px;
overflow-y: auto;
}
.container > div:first-child {
align-self: start; /* added */
}

.sticky-header {
position: sticky;
top: 0;
padding: 8px;
text-align: center;
background-color: #ddd;
}

.sticky-sidebar {
position: sticky;
top: 0;
padding: 8px;
background-color: #eee;
}
<div class="container">
<div>
<div class="sticky-header">Sticky header</div>
<div>
Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up
one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus
Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line
in section 1.10.32. There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable. If you are going to use
a passage of Lorem Ipsum, you need to be sure there isn't anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the
Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or
non-characteristic words etc.
</div>
</div>
<div class="sticky-sidebar">Sidebar</div>
</div>

My position: sticky element isn't sticky when using flexbox

Since flex box elements default to stretch, all the elements are the same height, which can't be scrolled against.

Adding align-self: flex-start to the sticky element set the height to auto, which allowed scrolling, and fixed it.

Currently this is supported in all major browsers, but Safari is still behind a -webkit- prefix, and other browsers except for Firefox have some issues with position: sticky tables.

.flexbox-wrapper {  display: flex;  overflow: auto;  height: 200px;          /* Not necessary -- for example only */}.regular {  background-color: blue; /* Not necessary -- for example only */  height: 600px;          /* Not necessary -- for example only */}.sticky {  position: -webkit-sticky; /* for Safari */  position: sticky;  top: 0;  align-self: flex-start; /* <-- this is the fix */  background-color: red;  /* Not necessary -- for example only */}
<div class="flexbox-wrapper">  <div class="regular">    This is the regular box  </div>  <div class="sticky">    This is the sticky box  </div></div>


Related Topics



Leave a reply



Submit