I've created sticky scroll-spy navigation for the page, but there's weird behavior when user focus link or checkbox. This bug only occurs when container has position sticky, on position fixed this won't happen. I tried to remove all scripts, remove navigation on the left side problem persists, and changing class names. Checked this issue on Chrome, Edge, Opera & Firefox. My only idea to fix this is some javascript that will imitate position sticky behavior, but maybe there's some simpler solution.
<div id="secondary-nav" class="single-product-tabs white-shadow">
<nav class="tabs-links js-scrollspy-tabs scrollspy-tabs tabs-dark container-fluid">
<div class="effect" style="transform: translateX(500px)">
<div class="bg"></div>
<div class="shadow"></div>
</div>
<ul class="tabs-list">
<li><a href="#dane-podstawowe">Dane podstawowe</a></li>
<li><a href="#dane-techniczne">Dane techniczne</a></li>
<li><a href="#opis">Opis</a></li>
<li><a href="#zalaczniki">Załączniki</a></li>
</ul>
</nav>
<div class="single-product-settings">
<div class="dropdown dark-dropdown">
<span>Waluta:</span><button type="button">PLN</button>
<ul>
<li><button>PLN</button></li>
<li><button>USD</button></li>
<li><button>€</button></li>
</ul>
</div>
<label class="switch-wrapper">
<span>Ceny brutto:</span>
<div class="switch">
<input type="checkbox" id="show-gross-prices">
<span class="wajcha round"></span>
</div>
</label>
</div>
</div>
.single-product-tabs {
background: var(--gray5);
padding: 32px 32px 0 0;
position: sticky;
// position: fixed;
inset: 56px 0 auto 0;
z-index: 50;
display: flex;
}
Movie: https://youtu.be/9GRIWGO0g_g
3 Answers 3
This problem may be related to one or more issues/bugs with position: sticky.
See the following open Chromium bugs...
https://bugs.chromium.org/p/chromium/issues/detail?id=1257719 https://bugs.chromium.org/p/chromium/issues/detail?id=1178622
In my case, with a navigation panel at the top of the page, I'm seeing the same or similar problem commented by @Bennett McElwee above. That is, if an element within a position: sticky element receives focus, tabbing (using keyboard) to subsequent elements within the position: sticky element will scroll the page.
In Firefox, the problem is different - less pronounced - but it's still not working as it should.
I have not found a method to get position: sticky to work as I need it to, without encountering this problem.
My workaround, in part, is to use position: fixed instead and add padding to the top of the main element.
.navigate-banner {
...
position: fixed;
top: 0;
left: 0;
right: 0;
...
}
main {
padding-block-start: calc(var(--navigate-banner-current-height) * 1px);
}
This Codepen scroll-margin-top / scroll-padding, smooth scroll and fixed headers by Sven Wolferman is very helpful to demonstrate the workaround.
Update 2025 September
@tmo256's solution below is simpler and better. See https://stackoverflow.com/a/79669209/2542335
In my case, all that is needed is...
html:has(.navigate-banner:focus-within) {
scroll-padding-block-start: 0;
}
Comments
The original question doesn't specify the actual problem that's happening (and the linked video is now gone), but I came across this looking for answers as to why my page was scrolling when I moved keyboard focus within a position: sticky element positioned at top: 0, so I assume that was the original issue.
Cause
As per the Chromium bugs linked by @Graymatter (Bug #40796549, Bug #40749247), it seems like are some browser issues with scroll padding interacting with position: sticky. The issue seems to be that as focus moves, the browser to tries to scroll the window to add sufficient scroll padding around elements that are focused near the edge of the viewport. As the linked bugs suggest, the logic should probably be accounting for the fact that trying to adjust for scroll-padding inside certain position: sticky elements will often not work as intended, for example in the case of a header that's always stuck to the top of the screen. In these cases the current behaviour just causes pointless scrolling, with the focused element still ending up in the same position relative to the edge of the viewport as it would have without trying to adjust for scroll-padding.
Workaround
There's no clear fix on the horizon for those bugs, so a possible simple workaround mentioned in the comments of the linked bugs is to simply set scroll-padding to 0 for your scroll container. You can set it for the root window by doing this:
:root {
scroll-padding: 0;
}
I think it's not ideal, since it overrides scroll padding for the entire document (or your entire site), and may affect the usability of other elements. Probably best to use with caution after reading about what setting scroll-padding will mean.
Just as a point of interest, I came across a spec proposal to allow setting or overriding scroll-padding per element, which would probably be helpful, but isn't likely in the near future.
Comments
Found this post looking for a solution to this issue. For lack of a better solution, I currently have implemented the following workaround:
body:has(#element:focus), html:has(#element:focus) { scroll-padding:0 }
I admit I don't love this solution - I'm somewhat concerned about the performance of this workaround, but it did fix my problem while allowing me to keep scroll-padding and the sticky elements. I don't have a ton of :has rules, but I'll keep my eye on it.
scroll-padding-topis set to less than the bottom of the focused element, the page scrolls up by that amount; if more, then the page scrolls up by about 440px. This is absolutely bonkers and it is driving me mad.