It was my understanding, that if an element with position:sticky
is nested within a parent element: when the parent leaves the viewport, that "sticky" element will leave with it.
Here I have a "sticky" <ul>
within a <nav>
within <main>
. When scrolling through the main element, when the <nav>
would normally scroll off-screen, it instead behaves as if it's become position:sticky
. However, if I change the display
of the <nav>
to be either block
or inline-block
, it behaves as I thought that it would. What's happening here?
body {
border: 2px dotted gray;
padding: 2rem;
}
nav {
display: inline;
}
ul {
top: 0;
position: sticky;
width: 100%;
list-style: none;
padding: 1rem 0;
display: flex;
gap: 1rem;
font-weight: bold;
border: 2px dotted gray;
background: white;
}
<body>
<main>
<nav>
<ul>
<li>one</li>
<li>two</li>
<li>three</li>
</ul>
</nav>
<h1>Main Heading</h1>
<div>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean quis enim ipsum. Quisque vel lacinia urna. Aenean et cursus nisi. Mauris eleifend fermentum elit, id finibus sem varius id. Duis imperdiet massa at velit ultrices gravida id sit amet ipsum. Praesent convallis quis metus nec dignissim. Etiam et odio id odio tincidunt bibendum quis vel urna. Cras ultricies diam eget nisl posuere, vel mollis sapien venenatis. Nulla eu diam hendrerit, gravida dolor vitae, cursus nulla.</p>
<p>Maecenas vulputate viverra diam elementum volutpat. Sed vulputate ac velit et tincidunt. Mauris eget nisl ut mauris eleifend accumsan. Phasellus accumsan ultricies leo, vitae gravida tellus rutrum sed. Proin condimentum pulvinar rhoncus. Duis quis massa ligula. Cras ac est aliquet, facilisis leo nec, scelerisque arcu. Nunc ultricies sollicitudin semper. Nulla varius laoreet posuere. Suspendisse hendrerit nulla id mi rhoncus iaculis. Donec interdum ultricies risus, eget malesuada justo pellentesque placerat. Cras convallis eget dolor in tempus. Ut imperdiet tellus eu nibh bibendum rutrum.</p>
<p>Integer eros purus, porta non rhoncus a, accumsan et lectus. Ut a ullamcorper purus. Proin mattis fermentum lorem varius mollis. Nullam imperdiet, neque auctor sodales molestie, nulla enim suscipit leo, id cursus nibh quam vel neque. Curabitur mauris nunc, varius id pharetra sed, elementum nec tellus. Morbi luctus auctor egestas. Cras accumsan arcu ullamcorper porttitor imperdiet. Sed semper magna nec nibh venenatis, sed laoreet neque malesuada. Aenean sit amet erat molestie, efficitur lacus vitae, laoreet lectus. Proin elit enim, ultrices nec nibh eget, vehicula maximus odio. Nunc egestas dapibus porta. Mauris aliquet bibendum ultrices.</p>
<p>Praesent efficitur sit amet magna bibendum bibendum. In convallis nisl aliquam vulputate gravida. Praesent ornare pretium dapibus. Aliquam malesuada in metus eget eleifend. Morbi at cursus augue, sed sagittis dolor. Pellentesque facilisis urna metus, et maximus risus tristique et. Cras blandit condimentum pulvinar. Fusce mattis egestas tortor, ut aliquam libero ultrices eu. Praesent mauris enim, egestas id tristique in, mollis in tellus. Integer tristique augue quis lorem facilisis, non convallis lorem consequat. Morbi sagittis at mi ac finibus. Vivamus eget diam nec quam lobortis viverra. Morbi viverra ut odio non vehicula.</p>
<p>Proin faucibus tortor quis nisl placerat, eget commodo ante iaculis. Proin quis aliquam ante, a iaculis nisi. Vivamus porta mi et neque ullamcorper mattis. Suspendisse cursus, urna et placerat posuere, risus arcu tempor nunc, eget hendrerit nulla ex maximus ante. Morbi elit mauris, vestibulum vel elementum et, mattis non quam. Quisque aliquet congue quam, id dictum nunc scelerisque in. Mauris ipsum risus, vestibulum venenatis lorem vitae, porta semper ante. Aliquam eu velit vitae neque iaculis vestibulum id a magna. Integer malesuada at lacus ac vulputate.</p>
</div>
</main>
</body>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
It's all about "containing block". sticky position doesn't consider the parent element but consider its containing block which is the parent element in most of the cases but in your case it's not because:
For other elements, if the element's position is 'relative' or 'static', the containing block is formed by the content edge of the nearest ancestor box that is a block container or which establishes a formatting context. ref
sticky
is not mentioned there but it behave the same as relative
and static
(https://www.w3.org/TR/css-position-3/#def-cb)
If you check the definition of sticky you can read:
Identical to relative, except that its offsets are automatically adjusted in reference to the nearest ancestor scroll container’s scrollport (as modified by the inset properties) in whichever axes the inset properties are not both auto, to try to keep the box in view within its containing block as the user scrolls. This positioning scheme is called sticky positioning. ref
So the containing block in your case is no more nav
but main