helperPack 4.1.5: sticky-header script caches the viewport width and overwrites window.onscroll

  • Hello,

    We run BlackOps on a large WoltLab 6.2.8 board. While investigating a member's bug report we read through the sticky-header script in __headerContentMenu and found two things worth passing on. Both are in com.cls-design.style.helperPack 4.1.5.

    First, so it is clear where we stand: your CSS pairing is correct, and we initially said otherwise in public. We had USE_STICKYMENU switched off and our own sticky navigation
    running, so html.fixedUI was never set and your compensating rule never fired. We concluded your rule was dead code, which was wrong, and we have corrected that. With your sticky menu enabled the pairing behaves exactly as intended:

    html:not(.fixedUI) .dropdownMenuContainer .userMenu { position: absolute !important }
    html.fixedUI .dropdownMenuContainer .userMenu { top: 66px !important }

    The two issues below are in the script itself.


    1. The viewport width is read once at page load and never re-read

    var viewportWidth = window.innerWidth || document.documentElement.clientWidth;
    var root = document.documentElement;
    window.onscroll = function() {
    if (viewportWidth > 1024) {
    ...
    }
    };

    viewportWidth is captured when the script runs, but the handler keeps testing that stale value for the life of the page. If the window is resized from a wide viewport to a narrow one, or a tablet is rotated, the guard still passes and the header keeps pinning at widths where it should not.

    Measured on BlackOps Blue, loading at 1920x1080 and then resizing to 900px wide:

    html.fixedUI still present
    .pageHeaderContainer position: fixed, top: 137px, height: 0

    A page loaded directly at 900px is fine, because the captured value is then correct. It is only the resize and rotate cases that are affected.

    Reading the width inside the handler, or recomputing it on resize, would fix it.


    2. window.onscroll is assigned destructively and is not throttled

    window.onscroll = function() { ... };

    This replaces any existing window.onscroll handler, and is itself replaced by anything that assigns later - whichever script runs last silently wins, with no error. On our installation nothing else uses it (window.onscroll is null before your script runs), so there is no live breakage here; we are raising it because it is fragile against any plugin or customisation that happens to use the same property.

    The handler also runs on every scroll event and reads layout, rather than being throttled through requestAnimationFrame.

    window.addEventListener('scroll', function () { ... }, { passive: true });

    with a requestAnimationFrame guard inside would address both points and would no longer collide with anything.


    Questions, if you have a moment

    - Is a later helperPack release available in which either of these is already addressed?
    We are on 4.1.5 with BlackOps 6.2.0.

    - Is #pageLogoContainer.offsetHeight (146px on our install) the intended pin threshold, or is it meant to track something else? We ask because we are considering enabling USE_STICKYMENU and retiring our own sticky navigation, and we would rather follow your design than keep a local override.

    - Is there any reason not to run USE_STICKYMENU alongside a third-party sticky navigation during a transition? In our testing the two coexist without conflict, but we would rather hear it from you than assume.

    We are not asking you to support our customisations - our own side is already resolved.
    These are just two things we found in your code that you would probably want to know about.

    Thank you for the styles; BlackOps has been on our board for years.

    Kind regards,
    LinuxSat-Support

  • Hi,

    The script being used is very old and has never been updated. It hasn't caused any problems so far, so there wasn't a particularly high priority on changing anything.

    It’s true that the width (1024px) isn’t monitored. Back then, that was a safeguard to ensure it wouldn’t be used on mobile devices. At the time, I didn’t think there was any chance that someone would actually resize the page from “mobile” to “desktop” and run into problems with the menu.

    Back when WoltLab Suite 3.0 came out—has it been 10 years now?—I was just glad I’d managed to get it working at all.

    So there’s no new version of the script.

    It’s true that `pageLogoContainer.offsetHeight` determines the correct height for triggering the toggle. This happens when the main menu is at the top of the screen.

    I’d remove the script and replace it with a custom menu. Since everything else is controlled via CSS anyway, there won’t be any issues if you set the `.fixedUI` class when needed.

    So much for the old script.

    I’ve actually written a new script for the menu that I’m currently testing. It does more than the old script. For one thing, it monitors the width so that it always works correctly when switching from “mobile” to “desktop” mode. It also automatically sets the menu’s position correctly every time without any css. It doesn’t matter whether the maximum width is defined as fixed or variable. The old script usually only works error-free with a fixed maximum width. And last but not least, you can animate it both when fixing the menu and when unfixing it.

    That was at least the intention as a replacement for the script. However, since the header is being redesigned in WoltLab Suite 6.3 and you actually no longer need any JavaScript for a sticky menu, I’m not sure if the change is even worth it anymore.

    I'll take a look at that and then probably release an update for the old script.

    Regards Tom

    Deine Anfrage wurde nicht beantwortet? Dann bitte einfach noch mal kurz im Thema nachfragen.

    On the road to 20K :jump: