Sticky Header verschwindet bei window resize

B

ByeBye 249712

Ich habe einen Header, welcher beim nach unten scrollen auf "position: fixed" gesetzt wird, sobald
dieser im window die Position "top = 0" errreicht hat.
Dies funktioniert zunächst einwandfrei; jedoch verschwindet der Header beim nach oben scrollen
während er auf "position: fixed" gesetzt ist, sobald ich die größe des Browserfensters in die vertikale Richtung verändere.
Für etwaige Ideen, welche zur Lösung beitragen könnten, wär ich sehr Dankbar.

Hier der Code:

Code:
jQuery(document).ready(function() {

var headerOffset = jQuery(".wrapper_header").offset().top;
var scrollPosition = null;


jQuery(window).resize(function() {
headerOffset = jQuery(".wrapper_header").offset().top;
});


jQuery(window).scroll(function() {

scrollPosition = jQuery(window).scrollTop();

if (scrollPosition >= headerOffset){
jQuery(".wrapper_header").addClass("fixed");
}else{
jQuery(".wrapper_header").removeClass("fixed");
}

});

});
 
Hi,

ich kenne die Struktur deines Dokumentes nicht. Aber ich denke, dass du die Klasse fixed nicht abhängig vom fixed-positionierten Element machen kannst. Dieses erscheint zwar immer am oberen Rand des Dokuments, besitzt allerdings ein unterschiedliches Offset im Dokument. Nach einem vertikalen Resize passt aus diesem Grund der aktuelle Wert nicht mehr und der Vergleich mit der Scrollposition schlägt fehl.

Vielleicht ist es an dieser Stelle besser, das Offset über die Höhe des übergeordneten Elementes zu bestimmen. Die Höhe wird initial bestimmt und bei jedem Resize neu berechnet. Damit sollte sich der StickyHeader immer an der richtigen Position befinden.

Beispiel:
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="Quaese">
<title>tutorials.de</title>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script>
(function($) {
    $(document).ready(function() {

        var header = $('.header'),

            getElementHeight = function(elem) {
                return elem.getBoundingClientRect().height;
            },

            handleSticky = function() {
                scrollPosition = $(window).scrollTop();

                if (scrollPosition >= headerOffset) {
                    $(".wrapper_header").addClass("fixed");
                } else {
                    $(".wrapper_header").removeClass("fixed");
                }
            },

            // Elementhöhe ermitteln
            headerOffset = getElementHeight(header[0]),
            scrollPosition;

        $(window).on('resize', function() {
            headerOffset = getElementHeight(header[0]);
        });


        $(window).on('scroll', handleSticky);
    });
})(jQuery);
</script>
<style>
html {
    height: 100%;
}
body {
    height: 180%;
    margin: 0;
    padding: 0;
}

.header {
    background: #0f0;
    padding-top: 10%;
}
.wrapper_header {
    background: #f00;
    height: 150px;
}
.fixed {
    position: fixed;
    top: 0;
    width: 100%;
}
</style>
</head>
<body>
<div class="header">
    header
</div>
<div class="wrapper_header">
    wrapper_header
</div>
</body>
</html>

Vielleicht hilft dir das weiter.

Ciao
Quaese
 
Hi,

Vielen Dank für dein Codebeispiel.
Leider funktioniert dein Code, angepasst an meine Problemstellung, bei mir nicht.
Wenn ich das richtig verstehe vergleichst du in deinem Beispiel die Höhe des Containers,
welcher sich um den gesamten Header befindet (bei mir der "wrapper_header"), mit der Scrollposition,
definiert über "scrollPosition", richtig?
Allerdings ist mir die herangehensweise leider etwas unklar und vermutlich für meinen Zweck
leider nicht zielführend, da bei mir der "wrapper_header" immer konstant bei 80 Pixeln liegt.

Ich Poste mal die nötigen Klassen in der CSS zur veranschaulichung
(Die Klasse "wrapper_header" umschließt die Klassen "header_background" und "header_menu"):


Code:
.wrapper_header{
        position: relative;
        width: 100%;
}


.header_background {
        position: absolute;
        width: 100%;
        height: 80px;
        background: #005ba1;
}


.header_menu {
        position: relative;
        width: 1200px;
        margin: auto;
}

.fixed {
position: fixed;
top: 0px;
}
 
Danke für deine Hilfe.

Hier ist die HTML:

HTML:
<!-- wrapper_header --->
 <div class="wrapper_header">

           <!-- header background --->
           <div class="header_background"></div>

           <div class="header_menu">
           <ul id="menu-headermenu" class="main-menu">[/code]
              <li class="menu-item-01"><a href="#Anker1">Inhalt1</a></li>
              <li class="menu-item-02"><a href="#Anker2">Inhalt2</a></li>
              <li class="menu-item-03"><a href="#Anker3">Inhalt3</a></li>
              <li class="menu-item-04"><a href="#Anker4">Inhalt4</a></li>
           </ul>
           </div>


<!-- Ende wrapper_header--->
</div>


Zur Vollständigkeit poste ich hier auch nochmal die CSS inklusive Listenelemente des Menüs:

CSS:
.wrapper_header{
        position: relative;
        width: 100%;
}


.header_background {
        position: absolute;
        width: 100%;
        height: 80px;
        background: #005ba1;
}


.header_menu {
        position: relative;
        width: 1200px;
        margin: auto;
}


.main-menu li{
   float: left;
   list-style: none;
}


.main-menu li a{
        line-height: 80px;
        text-align: center;
        text-decoration: none;
        font-family: helvetica;
        font-size: 25px;
        color: #ffffff;
}


.fixed {
position: fixed;
top: 0px;
}



Ich habe mir nochmal weiter den Kopf darüber zerbrochen warum der Header, wenn er schon
"fixed" ist, bei einem Resize des Windows verschwindet.
Und irgendwie erscheint mir das Ganze extrem unlogisch, da der Header nach dem Resize verschwindet
sobald auch nur der geringste Scroll mit dem Mausrad nach oben getätigt wird.
Denn selbst wenn er mit der "scrollPosition" im Vergelich mit dem "headerOffset" nach dem Resize
etwas durcheinander kommt, erschließt sich mir nicht warum der Header beim Upscrolling sofort verschwindet, hmm.
 
Hi,

würde es in diesem Fall nicht reichen, das Offset des Elements wrapper_header initial einmal zu ermitteln und diesen Wert immer zum Prüfen zu verwenden?
Code:
jQuery(document).ready(function() {

    var wrapperHeader = jQuery(".wrapper_header"),
        headerOffset = wrapperHeader.offset().top,
        $window = jQuery(window),
        scrollPosition = null;

    /*$window.resize(function() {
        headerOffset = wrapperHeader.offset().top;
    });*/

    jQuery(window).scroll(function() {
        scrollPosition = $window.scrollTop();

        if (scrollPosition >= headerOffset){
            wrapperHeader.addClass("fixed");
        }else{
            wrapperHeader.removeClass("fixed");
        }
    });
});
Den nicht notwendigen Teil habe ich auskommentiert. Außerdem habe ich die Elemente (.wrapper_header, window), auf die häufiger zugegriffen wird, auf Variablen geschrieben. Schließlich müssen die Elemente nicht bei jedem Durchlauf neu ermittelt werden.

Vielleicht kommt das deiner Vorstellung näher.

Ciao
Quaese
 
Hi,

So hatte ich es am Anfang auch.
Also ohne

Code:
$window.resize(function() {
        headerOffset = wrapperHeader.offset().top;
    });

Ohne diese Funktion verschwindet der Header zwar nach einem "Resize"
nicht sofort, wenn man nach oben scrollt. Allerdings funktioniert es dann trotzdem
nicht sauber, da nach einem "Resize" der Header nicht mehr genau bei "top=0"
auf "fixed" gesetzt wird.
Aber womöglich hast du recht und ich sollte diese Funktion besser weglassen.
Der "headerOffset" bliebe dann schonmal immer konstant.
Wahrscheinlich bräuchte man aber schon eine Funktion die bei einem Resize
irgendeinen Wert abfragt und neu definiert damit es rund läuft?!
 
Hi,

ich habe ein jsfiddle erstellt und da funktioniert das auch nach einem Resize hervorragend.

In dem Beispiel lasse ich die Offsetwerte ausgeben. Daran kannst du erkennen, dass sich das Offset beim Scrollen ändert. Um die Klasse fixed beim Unterschreiten des Schwellenwertes wieder vom Header nehmen zu können, ist es allerdings notwendig, dass der Wert fest bleibt.

Du kannst den geänderten Wert sehen, indem du wie folgt vorgehst:
1. scrolle nach unten
2. ändere die Grösse des Ergebnisfensters, indem du den Trennbalken zum CSS-Bereich verschiebst
3. scrolle vorsichtig um einige Pixel, um die Werte zu sehen

Der Wert
Offset (.wrapper_header, resize) ist grösser als scrollTop, das hätte zur Folge, dass die Klasse fixed vom Header genommen werden würde und der Header wieder ohne position: fixed positioniert werden würde und somit aus dem Anzeigebereich verschwindet.

Ich hoffe, du konntest der Erklärung folgen.

Ciao
Quaese
 
Hi,

Vielen Dank für dein Beispiel.
Ich war der Meinung dass sich nach einem Resize ehr die "ScrollPosition" ändert als
der "headerOffset". Da war ich wohl auf dem Holzweg. Sehr einleuchtendes Beispiel
auch im jsfiddle.
Ich habe dein Beispiel mal ausprobiert und irgendwie funktioniert es bei mir nicht.
Wenn ich das richtig verstehe fängst du den Offset des Headers nach dem Resize in
der Variable "headerOffsetResize" ab?! Aber was passiert dann mit dieser Variable?
Die wird ja dann gar nicht mehr benutzt?! Man könnte sie höchstens dann auf "headerOffset"
setzen, aber so hatte ich es quasi ja am Anfang auch und da hat es auch nicht funktioniert.
Bei mir funktioniert es so leider nicht. :(
Bei dir aber schon??
 
Die Variable habe ich nur eingeführt, um zu demonstrieren, dass die Berechnung/Bedingung damit nicht korrekt ist. Sonst habe ich das gleiche Script verwendet wie in meinem vorletzten Post geschrieben - ohne resize-Handler.

Ciao
Quaese
 
Zurück