6

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

asked Jun 24, 2022 at 10:21
1
  • You haven't actually said what the problem is! I want to know because I have also found a problem. When an element in the sticky header receives focus, the page content scrolls up. If scroll-padding-top is 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. Commented Jul 11, 2023 at 8:56

3 Answers 3

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;
}
answered Jul 21, 2023 at 6:02
Sign up to request clarification or add additional context in comments.

Comments

2

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.

answered Mar 12, 2024 at 0:00

Comments

1

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.

answered Jun 17 at 13:50

1 Comment

Thanks! This is a good solution/workaround to the problem. And there is no indication that the browser bug will be fixed anytime soon. For my use case: html:has(#element:focus-within) { scroll-padding-block-start:0 }

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.